Merge pull request #1258 from KLayout/wip

Wip
This commit is contained in:
Matthias Köfferlein 2023-01-24 21:48:27 +01:00 committed by GitHub
commit ab8cfee1ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
212 changed files with 12050 additions and 2856 deletions

1
.gitignore vendored
View File

@ -37,6 +37,7 @@ build-*
bin-*
mkqtdecl.tmp
mkqtdecl5.tmp
mkqtdecl6.tmp
testtmp
*build.macos*
*bin.macos*

View File

@ -29,6 +29,7 @@ SOURCES = \
dbEdgePairs.cc \
dbEdgeProcessor.cc \
dbEdges.cc \
dbEdgesLocalOperations.cc \
dbFillTool.cc \
dbFuzzyCellMapping.cc \
dbGenericShapeIterator.cc \
@ -243,6 +244,7 @@ HEADERS = \
dbEdgePairs.h \
dbEdgeProcessor.h \
dbEdges.h \
dbEdgesLocalOperations.h \
dbEdgesToContours.h \
dbFillTool.h \
dbFuzzyCellMapping.h \
@ -260,6 +262,7 @@ HEADERS = \
dbLayoutLayers.h \
dbLayoutQuery.h \
dbLayoutStateModel.h \
dbLayoutToNetlistEnums.h \
dbLayoutUtils.h \
dbLibrary.h \
dbLibraryManager.h \
@ -288,6 +291,7 @@ HEADERS = \
dbPolygonTools.h \
dbPolygonGenerators.h \
dbPropertiesRepository.h \
dbPropertyConstraint.h \
dbReader.h \
dbRecursiveInstanceIterator.h \
dbRecursiveShapeIterator.h \
@ -372,6 +376,7 @@ HEADERS = \
dbRegionUtils.h \
dbEdgesUtils.h \
dbRegionProcessors.h \
gsiDeclDbContainerHelpers.h \
gsiDeclDbHelpers.h \
dbNetlistCompare.h \
dbNetlistReader.h \

View File

@ -151,6 +151,7 @@ RegionDelegate *
AsIfFlatEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const
{
std::unique_ptr<FlatRegion> region (new FlatRegion ());
db::PropertyMapper pm (region->properties_repository (), properties_repository ());
if (filter.result_must_not_be_merged ()) {
region->set_merged_semantics (false);
@ -162,7 +163,12 @@ AsIfFlatEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &
res_polygons.clear ();
filter.process (*e, res_polygons);
for (std::vector<db::Polygon>::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) {
region->insert (*pr);
db::properties_id_type prop_id = pm (e.prop_id ());
if (prop_id != 0) {
region->insert (db::PolygonWithProperties (*pr, prop_id));
} else {
region->insert (*pr);
}
}
}
@ -173,6 +179,7 @@ EdgesDelegate *
AsIfFlatEdgePairs::processed_to_edges (const EdgePairToEdgeProcessorBase &filter) const
{
std::unique_ptr<FlatEdges> edges (new FlatEdges ());
db::PropertyMapper pm (edges->properties_repository (), properties_repository ());
if (filter.result_must_not_be_merged ()) {
edges->set_merged_semantics (false);
@ -184,7 +191,12 @@ AsIfFlatEdgePairs::processed_to_edges (const EdgePairToEdgeProcessorBase &filter
res_edges.clear ();
filter.process (*e, res_edges);
for (std::vector<db::Edge>::const_iterator pr = res_edges.begin (); pr != res_edges.end (); ++pr) {
edges->insert (*pr);
db::properties_id_type prop_id = pm (e.prop_id ());
if (prop_id != 0) {
edges->insert (db::EdgeWithProperties (*pr, prop_id));
} else {
edges->insert (*pr);
}
}
}
@ -195,10 +207,16 @@ EdgePairsDelegate *
AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const
{
std::unique_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs ());
db::PropertyMapper pm (new_edge_pairs->properties_repository (), properties_repository ());
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
new_edge_pairs->insert (*p);
db::properties_id_type prop_id = pm (p.prop_id ());
if (prop_id != 0) {
new_edge_pairs->insert (db::EdgePairWithProperties (*p, prop_id));
} else {
new_edge_pairs->insert (*p);
}
}
}
@ -209,11 +227,17 @@ RegionDelegate *
AsIfFlatEdgePairs::polygons (db::Coord e) const
{
std::unique_ptr<FlatRegion> output (new FlatRegion ());
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
for (EdgePairsIterator ep (begin ()); ! ep.at_end (); ++ep) {
db::Polygon poly = ep->normalized ().to_polygon (e);
if (poly.vertices () >= 3) {
output->insert (poly);
db::properties_id_type prop_id = pm (ep.prop_id ());
if (prop_id != 0) {
output->insert (db::PolygonWithProperties (poly, prop_id));
} else {
output->insert (poly);
}
}
}
@ -224,10 +248,17 @@ EdgesDelegate *
AsIfFlatEdgePairs::edges () const
{
std::unique_ptr<FlatEdges> output (new FlatEdges ());
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
for (EdgePairsIterator ep (begin ()); ! ep.at_end (); ++ep) {
output->insert (ep->first ());
output->insert (ep->second ());
db::properties_id_type prop_id = pm (ep.prop_id ());
if (prop_id != 0) {
output->insert (db::EdgeWithProperties (ep->first (), prop_id));
output->insert (db::EdgeWithProperties (ep->second (), prop_id));
} else {
output->insert (ep->first ());
output->insert (ep->second ());
}
}
return output.release ();
@ -237,9 +268,15 @@ EdgesDelegate *
AsIfFlatEdgePairs::first_edges () const
{
std::unique_ptr<FlatEdges> output (new FlatEdges ());
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
for (EdgePairsIterator ep (begin ()); ! ep.at_end (); ++ep) {
output->insert (ep->first ());
db::properties_id_type prop_id = pm (ep.prop_id ());
if (prop_id != 0) {
output->insert (db::EdgeWithProperties (ep->first (), prop_id));
} else {
output->insert (ep->first ());
}
}
return output.release ();
@ -249,9 +286,15 @@ EdgesDelegate *
AsIfFlatEdgePairs::second_edges () const
{
std::unique_ptr<FlatEdges> output (new FlatEdges ());
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
for (EdgePairsIterator ep (begin ()); ! ep.at_end (); ++ep) {
output->insert (ep->second ());
db::properties_id_type prop_id = pm (ep.prop_id ());
if (prop_id != 0) {
output->insert (db::EdgeWithProperties (ep->second (), prop_id));
} else {
output->insert (ep->second ());
}
}
return output.release ();
@ -260,18 +303,25 @@ AsIfFlatEdgePairs::second_edges () const
EdgePairsDelegate *
AsIfFlatEdgePairs::add (const EdgePairs &other) const
{
FlatEdgePairs *other_flat = dynamic_cast<FlatEdgePairs *> (other.delegate ());
const FlatEdgePairs *other_flat = dynamic_cast<const FlatEdgePairs *> (other.delegate ());
if (other_flat) {
std::unique_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs (*other_flat));
new_edge_pairs->invalidate_cache ();
db::PropertyMapper pm (new_edge_pairs->properties_repository (), properties_repository ());
size_t n = new_edge_pairs->raw_edge_pairs ().size () + count ();
new_edge_pairs->reserve (n);
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
new_edge_pairs->raw_edge_pairs ().insert (*p);
db::properties_id_type prop_id = pm (p.prop_id ());
if (prop_id) {
new_edge_pairs->raw_edge_pairs ().insert (db::EdgePairWithProperties (*p, prop_id));
} else {
new_edge_pairs->raw_edge_pairs ().insert (*p);
}
}
return new_edge_pairs.release ();
@ -280,15 +330,28 @@ AsIfFlatEdgePairs::add (const EdgePairs &other) const
std::unique_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs ());
db::PropertyMapper pm (new_edge_pairs->properties_repository (), properties_repository ());
db::PropertyMapper pm_other (new_edge_pairs->properties_repository (), &other.properties_repository ());
size_t n = count () + other.count ();
new_edge_pairs->reserve (n);
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
new_edge_pairs->raw_edge_pairs ().insert (*p);
db::properties_id_type prop_id = pm (p.prop_id ());
if (prop_id) {
new_edge_pairs->raw_edge_pairs ().insert (db::EdgePairWithProperties (*p, prop_id));
} else {
new_edge_pairs->raw_edge_pairs ().insert (*p);
}
}
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
new_edge_pairs->raw_edge_pairs ().insert (*p);
db::properties_id_type prop_id = pm_other (p.prop_id ());
if (prop_id) {
new_edge_pairs->raw_edge_pairs ().insert (db::EdgePairWithProperties (*p, prop_id));
} else {
new_edge_pairs->raw_edge_pairs ().insert (*p);
}
}
return new_edge_pairs.release ();
@ -344,9 +407,16 @@ AsIfFlatEdgePairs::insert_into (Layout *layout, db::cell_index_type into_cell, u
// improves performance when inserting an original layout into the same layout
db::LayoutLocker locker (layout);
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
for (EdgePairsIterator e (begin ()); ! e.at_end (); ++e) {
shapes.insert (*e);
db::properties_id_type prop_id = pm (e.prop_id ());
if (prop_id) {
shapes.insert (db::EdgePairWithProperties (*e, prop_id));
} else {
shapes.insert (*e);
}
}
}
@ -356,9 +426,16 @@ AsIfFlatEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type
// improves performance when inserting an original layout into the same layout
db::LayoutLocker locker (layout);
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
for (EdgePairsIterator e (begin ()); ! e.at_end (); ++e) {
shapes.insert (e->normalized ().to_simple_polygon (enl));
db::properties_id_type prop_id = pm (e.prop_id ());
if (prop_id) {
shapes.insert (db::SimplePolygonWithProperties (e->normalized ().to_simple_polygon (enl), prop_id));
} else {
shapes.insert (e->normalized ().to_simple_polygon (enl));
}
}
}

View File

@ -104,7 +104,7 @@ AsIfFlatEdges::selected_interacting_generic (const Region &other, EdgeInteractio
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
AddressableEdgeDelivery e (begin_merged ());
for ( ; ! e.at_end (); ++e) {
scanner.insert1 (e.operator-> (), 0);
@ -150,7 +150,7 @@ AsIfFlatEdges::selected_interacting_generic (const Edges &edges, EdgeInteraction
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
AddressableEdgeDelivery e (begin_merged ());
for ( ; ! e.at_end (); ++e) {
scanner.insert (e.operator-> (), 0);
@ -201,7 +201,7 @@ AsIfFlatEdges::selected_interacting_pair_generic (const Region &region, EdgeInte
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
AddressableEdgeDelivery e (begin_merged ());
for ( ; ! e.at_end (); ++e) {
scanner.insert1 (e.operator-> (), 0);
@ -245,7 +245,7 @@ AsIfFlatEdges::selected_interacting_pair_generic (const Edges &other, EdgeIntera
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
AddressableEdgeDelivery e (begin_merged ());
for ( ; ! e.at_end (); ++e) {
scanner.insert (e.operator-> (), 0);
@ -281,7 +281,7 @@ AsIfFlatEdges::pull_generic (const Edges &edges) const
{
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
AddressableEdgeDelivery e (begin (), has_valid_edges ());
AddressableEdgeDelivery e (begin ());
for ( ; ! e.at_end (); ++e) {
scanner.insert (e.operator-> (), 1);
@ -310,7 +310,7 @@ AsIfFlatEdges::pull_generic (const Region &other) const
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
AddressableEdgeDelivery e (begin (), true);
AddressableEdgeDelivery e (begin ());
for ( ; ! e.at_end (); ++e) {
scanner.insert1 (e.operator-> (), 0);
@ -480,6 +480,8 @@ AsIfFlatEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, c
{
if (join) {
// TODO: property support?
std::unique_ptr<FlatRegion> output (new FlatRegion ());
db::ShapeGenerator sg (output->raw_polygons (), false);
JoinEdgesClusterCollector cluster_collector (&sg, ext_b, ext_e, ext_o, ext_i);
@ -487,7 +489,7 @@ AsIfFlatEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, c
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve (count ());
AddressableEdgeDelivery e (begin (), has_valid_edges ());
AddressableEdgeDelivery e (begin ());
size_t n = 0;
for ( ; ! e.at_end (); ++e) {
@ -502,8 +504,15 @@ AsIfFlatEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, c
} else {
std::unique_ptr<FlatRegion> output (new FlatRegion ());
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
for (EdgesIterator e (begin_merged ()); ! e.at_end (); ++e) {
output->insert (extended_edge (*e, ext_b, ext_e, ext_o, ext_i));
db::properties_id_type prop_id = pm (e.prop_id ());
if (prop_id != 0) {
output->insert (db::PolygonWithProperties (extended_edge (*e, ext_b, ext_e, ext_o, ext_i), prop_id));
} else {
output->insert (extended_edge (*e, ext_b, ext_e, ext_o, ext_i));
}
}
return output.release ();
@ -733,7 +742,7 @@ AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Co
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve (count () + (other ? other->count () : 0));
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
AddressableEdgeDelivery e (begin_merged ());
size_t n = 0;
for ( ; ! e.at_end (); ++e) {
@ -774,7 +783,7 @@ AsIfFlatEdges::boolean (const Edges *other, EdgeBoolOp op) const
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve (count () + (other ? other->count () : 0));
AddressableEdgeDelivery e (begin (), has_valid_edges ());
AddressableEdgeDelivery e (begin ());
for ( ; ! e.at_end (); ++e) {
if (! e->is_degenerate ()) {
@ -808,7 +817,7 @@ AsIfFlatEdges::boolean_andnot (const Edges *other) const
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve (count () + (other ? other->count () : 0));
AddressableEdgeDelivery e (begin (), has_valid_edges ());
AddressableEdgeDelivery e (begin ());
for ( ; ! e.at_end (); ++e) {
if (! e->is_degenerate ()) {
@ -876,7 +885,7 @@ AsIfFlatEdges::edge_region_op (const Region &other, db::EdgePolygonOp::mode_t mo
EdgesDelegate *
AsIfFlatEdges::add (const Edges &other) const
{
FlatEdges *other_flat = dynamic_cast<FlatEdges *> (other.delegate ());
const FlatEdges *other_flat = dynamic_cast<const FlatEdges *> (other.delegate ());
if (other_flat) {
std::unique_ptr<FlatEdges> new_edges (new FlatEdges (*other_flat));
@ -960,10 +969,15 @@ AsIfFlatEdges::insert_into (Layout *layout, db::cell_index_type into_cell, unsig
{
// improves performance when inserting an original layout into the same layout
db::LayoutLocker locker (layout);
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
shapes.insert (*e);
if (e.prop_id () != 0) {
shapes.insert (db::EdgeWithProperties (*e, pm (e.prop_id ())));
} else {
shapes.insert (*e);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -54,9 +54,9 @@ public:
virtual std::string to_string (size_t nmax) const;
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node);
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node);
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node);
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint);
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
EdgePairsDelegate *width_check (db::Coord d, const RegionCheckOptions &options) const;
EdgePairsDelegate *space_check (db::Coord d, const RegionCheckOptions &options) const;
@ -122,11 +122,11 @@ public:
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
virtual RegionDelegate *and_with (const Region &other) const;
virtual RegionDelegate *not_with (const Region &other) const;
virtual RegionDelegate *xor_with (const Region &other) const;
virtual RegionDelegate *or_with (const Region &other) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &) const;
virtual RegionDelegate *and_with (const Region &other, PropertyConstraint property_constraint) const;
virtual RegionDelegate *not_with (const Region &other, PropertyConstraint property_constraint) const;
virtual RegionDelegate *xor_with (const Region &other, PropertyConstraint prop_constraint) const;
virtual RegionDelegate *or_with (const Region &other, PropertyConstraint prop_constraint) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &other, PropertyConstraint property_constraint) const;
virtual RegionDelegate *add_in_place (const Region &other)
{
@ -278,11 +278,15 @@ public:
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
protected:
void update_bbox (const db::Box &box);
void invalidate_bbox ();
void merge_polygons_to (db::Shapes &output, bool min_coherence, unsigned int min_wc, PropertiesRepository *target_rp = 0) const;
RegionDelegate *and_or_not_with (bool is_and, const Region &other, PropertyConstraint property_constraint) const;
virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const;
virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const;
@ -308,7 +312,6 @@ private:
mutable db::Box m_bbox;
virtual db::Box compute_bbox () const;
static RegionDelegate *region_from_box (const db::Box &b);
EdgePairsDelegate *space_or_isolated_check (db::Coord d, const RegionCheckOptions &options, bool isolated) const;
};

View File

@ -179,7 +179,11 @@ AsIfFlatTexts::processed_to_polygons (const TextToPolygonProcessorBase &filter)
res_polygons.clear ();
filter.process (*e, res_polygons);
for (std::vector<db::Polygon>::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) {
region->insert (*pr);
if (e.prop_id () != 0) {
region->insert (db::PolygonWithProperties (*pr, e.prop_id ()));
} else {
region->insert (*pr);
}
}
}
@ -216,7 +220,7 @@ AsIfFlatTexts::edges () const
TextsDelegate *
AsIfFlatTexts::add (const Texts &other) const
{
FlatTexts *other_flat = dynamic_cast<FlatTexts *> (other.delegate ());
const FlatTexts *other_flat = dynamic_cast<const FlatTexts *> (other.delegate ());
if (other_flat) {
std::unique_ptr<FlatTexts> new_texts (new FlatTexts (*other_flat));
@ -330,7 +334,7 @@ AsIfFlatTexts::selected_interacting_generic (const Region &other, bool inverse)
db::box_scanner2<db::Text, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
AddressableTextDelivery e (begin (), has_valid_texts ());
AddressableTextDelivery e (begin ());
for ( ; ! e.at_end (); ++e) {
scanner.insert1 (e.operator-> (), 0);
@ -376,7 +380,7 @@ AsIfFlatTexts::pull_generic (const Region &other) const
db::box_scanner2<db::Text, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
AddressableTextDelivery e (begin (), has_valid_texts ());
AddressableTextDelivery e (begin ());
for ( ; ! e.at_end (); ++e) {
scanner.insert1 (e.operator-> (), 0);

View File

@ -766,7 +766,7 @@ Cell::copy_shapes (const db::Cell &source_cell, const db::LayerMapping &layer_ma
}
if (target_layout != source_layout) {
db::PropertyMapper pm (*target_layout, *source_layout);
db::PropertyMapper pm (target_layout, source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm);
@ -915,7 +915,7 @@ Cell::move_shapes (db::Cell &source_cell, const db::LayerMapping &layer_mapping)
}
if (target_layout != source_layout) {
db::PropertyMapper pm (*target_layout, *source_layout);
db::PropertyMapper pm (target_layout, source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm);
@ -988,7 +988,7 @@ Cell::move_tree (db::Cell &source_cell)
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::PropertyMapper pm (target_layout, source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::CellMapping cm;
@ -1022,7 +1022,7 @@ Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm)
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::PropertyMapper pm (target_layout, source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::LayerMapping lm;
@ -1049,7 +1049,7 @@ Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm, const
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::PropertyMapper pm (target_layout, source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
std::vector <db::cell_index_type> source_cells;

View File

@ -371,7 +371,7 @@ CellMapping::do_create_missing_mapping (db::Layout &layout_a, const db::Layout &
if (! new_cells.empty ()) {
db::PropertyMapper pm (layout_a, layout_b);
db::PropertyMapper pm (&layout_a, &layout_b);
// Note: this avoids frequent cell index table rebuilds if source and target layout are identical
layout_a.start_changes ();

View File

@ -29,7 +29,7 @@ namespace db
ClipboardData::ClipboardData ()
: m_layout (), m_incomplete_cells ()
{
m_prop_id_map.set_target (m_layout);
m_prop_id_map.set_target (&m_layout);
m_container_cell_index = m_layout.add_cell ("");
}
@ -47,7 +47,7 @@ ClipboardData::add (const db::Layout &layout, unsigned int layer, const db::Shap
m_layout.insert_layer (layer, layout.get_properties (layer));
}
m_prop_id_map.set_source (layout);
m_prop_id_map.set_source (&layout);
m_layout.cell (m_container_cell_index).shapes (layer).insert (shape, m_prop_id_map);
}
@ -60,7 +60,7 @@ ClipboardData::add (const db::Layout &layout, unsigned int layer, const db::Shap
m_layout.insert_layer (layer, layout.get_properties (layer));
}
m_prop_id_map.set_source (layout);
m_prop_id_map.set_source (&layout);
db::Shape new_shape = m_layout.cell (m_container_cell_index).shapes (layer).insert (shape, m_prop_id_map);
m_layout.cell (m_container_cell_index).shapes (layer).transform (new_shape, trans);
}
@ -80,7 +80,7 @@ ClipboardData::add (const db::Layout &layout, const db::Instance &inst, unsigned
}
// Insert the instance mapping the cell to the target cell_index and the property ID using the map
m_prop_id_map.set_source (layout);
m_prop_id_map.set_source (&layout);
tl::const_map<db::cell_index_type> im (target_cell_index);
m_layout.cell (m_container_cell_index).insert (inst, im, m_prop_id_map);
}
@ -102,7 +102,7 @@ ClipboardData::add (const db::Layout &layout, const db::Instance &inst, unsigned
}
// Insert the instance mapping the cell to the target cell_index and the property ID using the map
m_prop_id_map.set_source (layout);
m_prop_id_map.set_source (&layout);
tl::const_map<db::cell_index_type> im (target_cell_index);
db::Instance new_inst = m_layout.cell (m_container_cell_index).insert (inst, im, m_prop_id_map);
m_layout.cell (m_container_cell_index).transform (new_inst, trans);
@ -123,7 +123,7 @@ ClipboardData::add (const db::Layout &layout, const db::Cell &cell, unsigned int
m_context_info.erase (target_cell_index);
}
m_prop_id_map.set_source (layout);
m_prop_id_map.set_source (&layout);
// copy the shapes
for (unsigned int l = 0; l < layout.layers (); ++l) {
@ -157,7 +157,7 @@ std::vector<unsigned int>
ClipboardData::do_insert (db::Layout &layout, const db::ICplxTrans *trans, db::Cell *cell, std::vector<db::cell_index_type> *new_tops, ClipboardDataInsertReceiver *insert_receiver) const
{
std::vector <unsigned int> new_layers;
PropertyMapper prop_id_map (layout, m_layout);
PropertyMapper prop_id_map (&layout, &m_layout);
std::map <db::LayerProperties, unsigned int, db::LPLogicalLessFunc> layer_map;
for (unsigned int l = 0; l < layout.layers (); ++l) {

View File

@ -1548,6 +1548,11 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi
{
set_description ("check");
// force different polygons in the different properties case to skip intra-polygon checks
if (pc_always_different (m_options.prop_constraint)) {
m_different_polygons = true;
}
m_check.set_include_zero (false);
m_check.set_whole_edges (options.whole_edges);
m_check.set_ignore_angle (options.ignore_angle);

View File

@ -1618,6 +1618,69 @@ private:
tl::weak_ptr<CompoundRegionOperationNode> mp_node;
};
/**
* @brief The generic local operation with property support
*
* This local operation executes the operation tree within a local processor.
* When put into a local processor, the operation tree will be executed on each interaction.
*/
template <class TS, class TI, class TR>
class DB_PUBLIC compound_local_operation_with_properties
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
{
public:
/**
* @brief Constructor
*
* Creates a local operation which utilizes the operation tree. "node" is the root of the operation tree.
* Ownership of the node is *not* transferred to the local operation.
*/
compound_local_operation_with_properties<TS, TI, TR> (CompoundRegionOperationNode *node, db::PropertyConstraint prop_constraint, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const std::vector<const db::PropertiesRepository *> &intruder_prs)
: mp_node (node), m_prop_constraint (prop_constraint), m_pms (target_pr, subject_pr)
{
m_pmis.reserve (intruder_prs.size ());
for (auto i = intruder_prs.begin (); i != intruder_prs.end (); ++i) {
m_pmis.push_back (db::PropertyMapper (target_pr, *i));
}
}
protected:
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &results, size_t max_vertex_count, double area_ratio) const
{
auto interactions_by_prop_id = separate_interactions_to_interactions_by_properties (interactions, m_prop_constraint, m_pms, m_pmis);
for (auto s2p = interactions_by_prop_id.begin (); s2p != interactions_by_prop_id.end (); ++s2p) {
std::vector<std::unordered_set<TR> > results_wo_props;
results_wo_props.resize (results.size ());
CompoundRegionOperationCache cache;
mp_node->compute_local (&cache, layout, s2p->second, results_wo_props, max_vertex_count, area_ratio);
for (size_t n = 0; n < results.size (); ++n) {
for (auto i = results_wo_props [n].begin (); i != results_wo_props [n].end (); ++i) {
results [n].insert (db::object_with_properties<TR> (*i, pc_norm (m_prop_constraint, s2p->first)));
}
}
}
}
virtual db::Coord dist () const { return mp_node->dist (); }
virtual OnEmptyIntruderHint on_empty_intruder_hint () const { return mp_node->on_empty_intruder_hint (); }
virtual bool requests_single_subjects () const { return true; }
virtual std::string description () const { return mp_node->description (); }
const TransformationReducer *vars () const { return mp_node->vars (); }
bool wants_variants () const { return mp_node->wants_variants (); }
std::vector<db::Region *> inputs () const { return mp_node->inputs (); }
private:
tl::weak_ptr<CompoundRegionOperationNode> mp_node;
db::PropertyConstraint m_prop_constraint;
mutable db::PropertyMapper m_pms;
mutable std::vector<db::PropertyMapper> m_pmis;
};
}
#endif

View File

@ -44,7 +44,7 @@ public:
typedef db::EdgePair value_type;
DeepEdgePairsIterator (const db::RecursiveShapeIterator &iter)
: m_iter (iter)
: m_iter (iter), m_prop_id (0)
{
set ();
}
@ -72,6 +72,11 @@ public:
return &m_edge_pair;
}
virtual db::properties_id_type prop_id () const
{
return m_prop_id;
}
virtual bool equals (const generic_shape_iterator_delegate_base<value_type> *other) const
{
const DeepEdgePairsIterator *o = dynamic_cast<const DeepEdgePairsIterator *> (other);
@ -100,12 +105,14 @@ private:
db::RecursiveShapeIterator m_iter;
mutable value_type m_edge_pair;
mutable db::properties_id_type m_prop_id;
void set () const
{
if (! m_iter.at_end ()) {
m_iter.shape ().edge_pair (m_edge_pair);
m_iter->edge_pair (m_edge_pair);
m_edge_pair.transform (m_iter.trans ());
m_prop_id = m_iter->prop_id ();
}
}
};
@ -307,6 +314,21 @@ const db::RecursiveShapeIterator *DeepEdgePairs::iter () const
return 0;
}
void DeepEdgePairs::apply_property_translator (const db::PropertiesTranslator &pt)
{
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
}
db::PropertiesRepository *DeepEdgePairs::properties_repository ()
{
return &deep_layer ().layout ().properties_repository ();
}
const db::PropertiesRepository *DeepEdgePairs::properties_repository () const
{
return &deep_layer ().layout ().properties_repository ();
}
EdgePairsDelegate *
DeepEdgePairs::add_in_place (const EdgePairs &other)
{
@ -451,7 +473,11 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
db::Polygon poly = s->edge_pair ().normalized ().to_polygon (e);
if (poly.vertices () >= 3) {
output.insert (db::PolygonRef (poly, layout.shape_repository ()));
if (s->prop_id () != 0) {
output.insert (db::PolygonRefWithProperties (db::PolygonRef (poly, layout.shape_repository ()), s->prop_id ()));
} else {
output.insert (db::PolygonRef (poly, layout.shape_repository ()));
}
}
}
}
@ -469,10 +495,18 @@ EdgesDelegate *DeepEdgePairs::generic_edges (bool first, bool second) const
for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
db::EdgePair ep = s->edge_pair ();
if (first) {
output.insert (ep.first ());
if (s->prop_id () != 0) {
output.insert (db::EdgeWithProperties (ep.first (), s->prop_id ()));
} else {
output.insert (ep.first ());
}
}
if (second) {
output.insert (ep.second ());
if (s->prop_id () != 0) {
output.insert (db::EdgeWithProperties (ep.second (), s->prop_id ()));
} else {
output.insert (ep.second ());
}
}
}
}

View File

@ -72,6 +72,9 @@ public:
virtual const db::EdgePair *nth (size_t n) const;
virtual bool has_valid_edge_pairs () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &filter);
virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const;

View File

@ -35,6 +35,7 @@
#include "dbLocalOperation.h"
#include "dbLocalOperationUtils.h"
#include "dbRegionLocalOperations.h" // for db::ContainedEdgesLocalOperation
#include "dbEdgesLocalOperations.h"
#include "dbHierProcessor.h"
#include "dbEmptyEdges.h"
@ -54,7 +55,7 @@ public:
typedef db::Edge value_type;
DeepEdgesIterator (const db::RecursiveShapeIterator &iter)
: m_iter (iter)
: m_iter (iter), m_prop_id (0)
{
set ();
}
@ -82,6 +83,11 @@ public:
return &m_edge;
}
virtual db::properties_id_type prop_id () const
{
return m_prop_id;
}
virtual bool equals (const generic_shape_iterator_delegate_base<value_type> *other) const
{
const DeepEdgesIterator *o = dynamic_cast<const DeepEdgesIterator *> (other);
@ -110,12 +116,14 @@ private:
db::RecursiveShapeIterator m_iter;
mutable value_type m_edge;
mutable db::properties_id_type m_prop_id;
void set () const
{
if (! m_iter.at_end ()) {
m_iter.shape ().edge (m_edge);
m_iter->edge (m_edge);
m_edge.transform (m_iter.trans ());
m_prop_id = m_iter->prop_id ();
}
}
};
@ -212,12 +220,17 @@ void DeepEdges::merged_semantics_changed ()
// .. nothing yet ..
}
void DeepEdges::do_insert (const db::Edge &edge)
void DeepEdges::do_insert (const db::Edge &edge, db::properties_id_type prop_id)
{
db::Layout &layout = deep_layer ().layout ();
if (layout.begin_top_down () != layout.end_top_down ()) {
db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
top_cell.shapes (deep_layer ().layer ()).insert (edge);
db::Shapes &shapes = top_cell.shapes (deep_layer ().layer ());
if (prop_id == 0) {
shapes.insert (edge);
} else {
shapes.insert (db::EdgeWithProperties (edge, prop_id));
}
}
invalidate_bbox ();
@ -441,6 +454,24 @@ DeepEdges::iter () const
return 0;
}
void DeepEdges::apply_property_translator (const db::PropertiesTranslator &pt)
{
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
m_merged_edges_valid = false;
m_merged_edges = db::DeepLayer ();
}
db::PropertiesRepository *DeepEdges::properties_repository ()
{
return &deep_layer ().layout ().properties_repository ();
}
const db::PropertiesRepository *DeepEdges::properties_repository () const
{
return &deep_layer ().layout ().properties_repository ();
}
bool DeepEdges::equals (const Edges &other) const
{
const DeepEdges *other_delegate = dynamic_cast<const DeepEdges *> (other.delegate ());
@ -481,6 +512,60 @@ public:
}
db::Shapes &merged (size_t cid, db::cell_index_type ci, bool initial = true)
{
return compute_merged (cid, ci, initial);
}
void erase (size_t cid, db::cell_index_type ci)
{
m_merged_cluster.erase (std::make_pair (cid, ci));
m_property_id_per_cluster.erase (std::make_pair (cid, ci));
}
private:
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes> m_merged_cluster;
std::map<std::pair<size_t, db::cell_index_type>, db::properties_id_type> m_property_id_per_cluster;
std::set<std::pair<size_t, db::cell_index_type> > m_done;
unsigned int m_layer;
const db::hier_clusters<db::Edge> *mp_hc;
db::box_scanner<db::Edge, size_t> m_scanner;
db::properties_id_type property_id (size_t cid, db::cell_index_type ci, bool initial)
{
std::map<std::pair<size_t, db::cell_index_type>, db::properties_id_type>::iterator s = m_property_id_per_cluster.find (std::make_pair (cid, ci));
// some sanity checks: initial clusters are single-use, are never generated twice and cannot be retrieved again
if (initial) {
tl_assert (s == m_property_id_per_cluster.end ());
}
if (s != m_property_id_per_cluster.end ()) {
return s->second;
}
s = m_property_id_per_cluster.insert (std::make_pair (std::make_pair (cid, ci), db::properties_id_type (0))).first;
const db::connected_clusters<db::Edge> &cc = mp_hc->clusters_per_cell (ci);
const db::local_cluster<db::Edge> &c = cc.cluster_by_id (cid);
if (c.begin_attr () != c.end_attr ()) {
s->second = *c.begin_attr ();
} else {
const db::connected_clusters<db::Edge>::connections_type &conn = cc.connections_for_cluster (cid);
for (db::connected_clusters<db::Edge>::connections_type::const_iterator i = conn.begin (); i != conn.end () && s->second == db::properties_id_type (0); ++i) {
s->second = property_id (i->id (), i->inst_cell_index (), false);
}
}
return s->second;
}
db::Shapes &compute_merged (size_t cid, db::cell_index_type ci, bool initial)
{
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes>::iterator s = m_merged_cluster.find (std::make_pair (cid, ci));
@ -498,6 +583,8 @@ public:
s = m_merged_cluster.insert (std::make_pair (std::make_pair (cid, ci), db::Shapes (false))).first;
db::properties_id_type prop_id = property_id (cid, ci, initial);
const db::connected_clusters<db::Edge> &cc = mp_hc->clusters_per_cell (ci);
const db::local_cluster<db::Edge> &c = cc.cluster_by_id (cid);
@ -505,7 +592,7 @@ public:
const db::connected_clusters<db::Edge>::connections_type &conn = cc.connections_for_cluster (cid);
for (db::connected_clusters<db::Edge>::connections_type::const_iterator i = conn.begin (); i != conn.end (); ++i) {
const db::Shapes &cc_shapes = merged (i->id (), i->inst_cell_index (), false);
const db::Shapes &cc_shapes = compute_merged (i->id (), i->inst_cell_index (), false);
merged_child_clusters.push_back (std::make_pair (&cc_shapes, i->inst_trans ()));
}
@ -531,18 +618,11 @@ public:
// .. and run the merge operation
s->second.clear ();
EdgeBooleanClusterCollectorToShapes cluster_collector (&s->second, EdgeOr);
EdgeBooleanClusterCollectorToShapes cluster_collector (&s->second, EdgeOr, prop_id);
m_scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
return s->second;
}
private:
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes> m_merged_cluster;
std::set<std::pair<size_t, db::cell_index_type> > m_done;
unsigned int m_layer;
const db::hier_clusters<db::Edge> *mp_hc;
db::box_scanner<db::Edge, size_t> m_scanner;
};
}
@ -582,7 +662,7 @@ DeepEdges::ensure_merged_edges_valid () const
hc.set_base_verbosity (base_verbosity() + 10);
hc.build (layout, deep_layer ().initial_cell (), conn);
// collect the clusters and merge them into big polygons
// collect the clusters and merge them into larger edges
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
@ -596,7 +676,7 @@ DeepEdges::ensure_merged_edges_valid () const
if (cc.is_root (*cl)) {
db::Shapes &s = cm.merged (*cl, c->cell_index ());
c->shapes (m_merged_edges.layer ()).insert (s);
s.clear (); // not needed anymore
cm.erase (*cl, c->cell_index ()); // not needed anymore
}
}
}
@ -613,6 +693,7 @@ DeepEdges::set_is_merged (bool f)
{
m_is_merged = f;
m_merged_edges_valid = false;
m_merged_edges = db::DeepLayer ();
}
void
@ -1187,6 +1268,8 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
if (join) {
// TODO: property support
db::hier_clusters<db::Edge> hc;
db::Connectivity conn (db::Connectivity::EdgesConnectByPoints);
conn.connect (edges);
@ -1247,6 +1330,7 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
PolygonRefToShapesGenerator prgen (&layout, out);
for (db::Shapes::shape_iterator si = c->shapes (edges.layer ()).begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
prgen.set_prop_id (si->prop_id ());
prgen.put (extended_edge (si->edge ().transformed (v->first), ext_b, ext_e, ext_o, ext_i).transformed (v->first.inverted ()));
}

View File

@ -62,7 +62,7 @@ public:
virtual void reserve (size_t n);
virtual void do_insert (const db::Edge &edge);
virtual void do_insert (const db::Edge &edge, properties_id_type prop_id);
EdgesDelegate *clone () const;
@ -80,6 +80,9 @@ public:
virtual bool has_valid_merged_edges () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual bool equals (const Edges &other) const;
virtual bool less (const Edges &other) const;

View File

@ -41,6 +41,7 @@
#include "dbRegionLocalOperations.h"
#include "dbLocalOperationUtils.h"
#include "dbCompoundOperation.h"
#include "dbLayoutToNetlist.h"
#include "tlTimer.h"
namespace db
@ -57,7 +58,7 @@ public:
typedef db::Polygon value_type;
DeepRegionIterator (const db::RecursiveShapeIterator &iter)
: m_iter (iter)
: m_iter (iter), m_prop_id (0)
{
set ();
}
@ -85,6 +86,11 @@ public:
return &m_polygon;
}
virtual db::properties_id_type prop_id () const
{
return m_prop_id;
}
virtual bool equals (const generic_shape_iterator_delegate_base<value_type> *other) const
{
const DeepRegionIterator *o = dynamic_cast<const DeepRegionIterator *> (other);
@ -113,12 +119,14 @@ private:
db::RecursiveShapeIterator m_iter;
mutable value_type m_polygon;
mutable db::properties_id_type m_prop_id;
void set () const
{
if (! m_iter.at_end ()) {
m_iter.shape ().polygon (m_polygon);
m_iter->polygon (m_polygon);
m_polygon.transform (m_iter.trans (), false);
m_prop_id = m_iter->prop_id ();
}
}
};
@ -220,12 +228,17 @@ void DeepRegion::min_coherence_changed ()
set_is_merged (false);
}
void DeepRegion::do_insert (const db::Polygon &polygon)
void DeepRegion::do_insert (const db::Polygon &polygon, db::properties_id_type prop_id)
{
db::Layout &layout = deep_layer ().layout ();
if (layout.begin_top_down () != layout.end_top_down ()) {
db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
top_cell.shapes (deep_layer ().layer ()).insert (db::PolygonRef (polygon, layout.shape_repository ()));
db::Shapes &shapes = top_cell.shapes (deep_layer ().layer ());
if (prop_id == 0) {
shapes.insert (db::PolygonRef (polygon, layout.shape_repository ()));
} else {
shapes.insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, layout.shape_repository ()), prop_id));
}
}
invalidate_bbox ();
@ -339,11 +352,16 @@ flatten_layer (db::DeepLayer &deep_layer)
db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
db::Shapes flat_shapes (layout.is_editable ());
for (db::RecursiveShapeIterator iter (layout, top_cell, deep_layer.layer ()); !iter.at_end (); ++iter) {
if (iter->is_polygon ()) {
db::Polygon poly;
iter->polygon (poly);
flat_shapes.insert (db::PolygonRef (poly.transformed (iter.trans ()), layout.shape_repository ()));
if (! iter->prop_id ()) {
flat_shapes.insert (db::PolygonRef (poly.transformed (iter.trans ()), layout.shape_repository ()));
} else {
flat_shapes.insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (iter.trans ()), layout.shape_repository ()), iter->prop_id ()));
}
}
}
@ -439,6 +457,12 @@ DeepRegion::nth (size_t) const
throw tl::Exception (tl::to_string (tr ("Random access to polygons is available only for flat regions")));
}
db::properties_id_type
DeepRegion::nth_prop_id (size_t) const
{
throw tl::Exception (tl::to_string (tr ("Random access to polygons is available only for flat regions")));
}
bool
DeepRegion::has_valid_polygons () const
{
@ -457,6 +481,24 @@ DeepRegion::iter () const
return 0;
}
void DeepRegion::apply_property_translator (const db::PropertiesTranslator &pt)
{
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
m_merged_polygons_valid = false;
m_merged_polygons = db::DeepLayer ();
}
db::PropertiesRepository *DeepRegion::properties_repository ()
{
return &deep_layer ().layout ().properties_repository ();
}
const db::PropertiesRepository *DeepRegion::properties_repository () const
{
return &deep_layer ().layout ().properties_repository ();
}
bool
DeepRegion::equals (const Region &other) const
{
@ -504,16 +546,53 @@ public:
void erase (size_t cid, db::cell_index_type ci)
{
m_merged_cluster.erase (std::make_pair (cid, ci));
m_property_id_per_cluster.erase (std::make_pair (cid, ci));
}
private:
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes> m_merged_cluster;
std::map<std::pair<size_t, db::cell_index_type>, db::properties_id_type> m_property_id_per_cluster;
unsigned int m_layer;
db::Layout *mp_layout;
const db::hier_clusters<db::PolygonRef> *mp_hc;
bool m_min_coherence;
db::EdgeProcessor m_ep;
db::properties_id_type property_id (size_t cid, db::cell_index_type ci, bool initial)
{
std::map<std::pair<size_t, db::cell_index_type>, db::properties_id_type>::iterator s = m_property_id_per_cluster.find (std::make_pair (cid, ci));
// some sanity checks: initial clusters are single-use, are never generated twice and cannot be retrieved again
if (initial) {
tl_assert (s == m_property_id_per_cluster.end ());
}
if (s != m_property_id_per_cluster.end ()) {
return s->second;
}
s = m_property_id_per_cluster.insert (std::make_pair (std::make_pair (cid, ci), db::properties_id_type (0))).first;
const db::connected_clusters<db::PolygonRef> &cc = mp_hc->clusters_per_cell (ci);
const db::local_cluster<db::PolygonRef> &c = cc.cluster_by_id (cid);
if (c.begin_attr () != c.end_attr ()) {
s->second = *c.begin_attr ();
} else {
const db::connected_clusters<db::PolygonRef>::connections_type &conn = cc.connections_for_cluster (cid);
for (db::connected_clusters<db::PolygonRef>::connections_type::const_iterator i = conn.begin (); i != conn.end () && s->second == db::properties_id_type (0); ++i) {
s->second = property_id (i->id (), i->inst_cell_index (), false);
}
}
return s->second;
}
db::Shapes &compute_merged (size_t cid, db::cell_index_type ci, bool initial, unsigned int min_wc)
{
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes>::iterator s = m_merged_cluster.find (std::make_pair (cid, ci));
@ -529,6 +608,8 @@ private:
s = m_merged_cluster.insert (std::make_pair (std::make_pair (cid, ci), db::Shapes (false))).first;
db::properties_id_type prop_id = property_id (cid, ci, initial);
const db::connected_clusters<db::PolygonRef> &cc = mp_hc->clusters_per_cell (ci);
const db::local_cluster<db::PolygonRef> &c = cc.cluster_by_id (cid);
@ -580,7 +661,7 @@ private:
// and run the merge step
db::MergeOp op (min_wc);
db::PolygonRefToShapesGenerator pr (mp_layout, &s->second);
db::PolygonRefToShapesGenerator pr (mp_layout, &s->second, prop_id);
db::PolygonGenerator pg (pr, false /*don't resolve holes*/, m_min_coherence);
m_ep.process (pg, op);
@ -629,7 +710,7 @@ DeepRegion::ensure_merged_polygons_valid () const
db::Connectivity conn;
conn.connect (deep_layer ());
hc.set_base_verbosity (base_verbosity () + 10);
hc.build (layout, deep_layer ().initial_cell (), conn);
hc.build (layout, deep_layer ().initial_cell (), conn, 0, 0, true /*separate_attributes*/);
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
@ -662,6 +743,7 @@ DeepRegion::set_is_merged (bool f)
{
m_is_merged = f;
m_merged_polygons_valid = false;
m_merged_polygons = db::DeepLayer ();
}
void
@ -671,131 +753,194 @@ DeepRegion::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsi
}
RegionDelegate *
DeepRegion::and_with (const Region &other) const
DeepRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *nets) const
{
db::NetBuilder &net_builder = deep_layer ().store_non_const ()->net_builder_for (l2n);
if (&l2n->dss () != deep_layer ().store ()) {
throw tl::Exception (tl::to_string (tr ("Extracted netlist is from different scope as this layer - cannot pull net shapes")));
}
DeepLayer result = deep_layer ().derived ();
std::unique_ptr<db::Region> region_for_layer (l2n->layer_by_original (this));
if (! region_for_layer) {
throw tl::Exception (tl::to_string (tr ("The given layer is not an original layer used in netlist extraction")));
}
std::map<unsigned int, const db::Region *> lmap;
lmap.insert (std::make_pair (result.layer (), region_for_layer.get ()));
net_builder.build_nets (nets, lmap, prop_mode, net_prop_name);
return new db::DeepRegion (result);
}
RegionDelegate *
DeepRegion::and_with (const Region &other, PropertyConstraint property_constraint) const
{
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
if (empty ()) {
return clone ();
return clone ()->remove_properties (pc_remove (property_constraint));
} else if (other.empty ()) {
return other.delegate ()->clone ();
return other.delegate ()->clone ()->remove_properties (pc_remove (property_constraint));
} else if (! other_deep) {
return AsIfFlatRegion::and_with (other);
return AsIfFlatRegion::and_with (other, property_constraint);
} else {
return new DeepRegion (and_or_not_with (other_deep, true));
return new DeepRegion (and_or_not_with (other_deep, true, property_constraint));
}
}
RegionDelegate *
DeepRegion::not_with (const Region &other) const
DeepRegion::not_with (const Region &other, PropertyConstraint property_constraint) const
{
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
if (empty () || other.empty ()) {
return clone ();
return clone ()->remove_properties (pc_remove (property_constraint));
} else if (! other_deep) {
return AsIfFlatRegion::not_with (other);
return AsIfFlatRegion::not_with (other, property_constraint);
} else {
return new DeepRegion (and_or_not_with (other_deep, false));
return new DeepRegion (and_or_not_with (other_deep, false, property_constraint));
}
}
RegionDelegate *
DeepRegion::or_with (const Region &other) const
DeepRegion::or_with (const Region &other, db::PropertyConstraint /*property_constraint*/) const
{
// TODO: implement property_constraint
RegionDelegate *res = add (other);
return res->merged_in_place ();
}
std::pair<RegionDelegate *, RegionDelegate *>
DeepRegion::andnot_with (const Region &other) const
DeepRegion::andnot_with (const Region &other, PropertyConstraint property_constraint) const
{
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
if (empty ()) {
return std::make_pair (clone (), clone ());
return std::make_pair (clone ()->remove_properties (pc_remove (property_constraint)), clone ()->remove_properties (pc_remove (property_constraint)));
} else if (other.empty ()) {
return std::make_pair (other.delegate ()->clone (), clone ());
return std::make_pair (other.delegate ()->clone ()->remove_properties (pc_remove (property_constraint)), clone ()->remove_properties (pc_remove (property_constraint)));
} else if (! other_deep) {
return AsIfFlatRegion::andnot_with (other);
return AsIfFlatRegion::andnot_with (other, property_constraint);
} else {
std::pair<DeepLayer, DeepLayer> res = and_and_not_with (other_deep);
std::pair<DeepLayer, DeepLayer> res = and_and_not_with (other_deep, property_constraint);
return std::make_pair (new DeepRegion (res.first), new DeepRegion (res.second));
}
}
DeepLayer
DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op, db::PropertyConstraint property_constraint) const
{
DeepLayer dl_out (deep_layer ().derived ());
db::BoolAndOrNotLocalOperation op (and_op);
if (pc_skip (property_constraint)) {
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
db::BoolAndOrNotLocalOperation op (and_op);
proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
configure_proc (proc);
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
} else {
db::BoolAndOrNotLocalOperationWithProperties op (and_op, &dl_out.layout ().properties_repository (), &deep_layer ().layout ().properties_repository (), &other->deep_layer ().layout ().properties_repository (), property_constraint);
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
configure_proc (proc);
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
}
return dl_out;
}
std::pair<DeepLayer, DeepLayer>
DeepRegion::and_and_not_with (const DeepRegion *other) const
DeepRegion::and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const
{
DeepLayer dl_out1 (deep_layer ().derived ());
DeepLayer dl_out2 (deep_layer ().derived ());
db::TwoBoolAndNotLocalOperation op;
if (pc_skip (property_constraint)) {
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
db::TwoBoolAndNotLocalOperation op;
std::vector<unsigned int> il;
il.push_back (other->deep_layer ().layer ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
configure_proc (proc);
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
std::vector<unsigned int> ol;
ol.push_back (dl_out1.layer ());
ol.push_back (dl_out2.layer ());
std::vector<unsigned int> il;
il.push_back (other->deep_layer ().layer ());
proc.run (&op, deep_layer ().layer (), il, ol);
std::vector<unsigned int> ol;
ol.push_back (dl_out1.layer ());
ol.push_back (dl_out2.layer ());
proc.run (&op, deep_layer ().layer (), il, ol);
} else {
db::PropertiesRepository *pr_out1 = &dl_out1.layout ().properties_repository ();
db::PropertiesRepository *pr_out2 = &dl_out2.layout ().properties_repository ();
const db::PropertiesRepository *pr = &deep_layer ().layout ().properties_repository ();
db::TwoBoolAndNotLocalOperationWithProperties op (pr_out1, pr_out2, pr, pr, property_constraint);
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
configure_proc (proc);
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
std::vector<unsigned int> il;
il.push_back (other->deep_layer ().layer ());
std::vector<unsigned int> ol;
ol.push_back (dl_out1.layer ());
ol.push_back (dl_out2.layer ());
proc.run (&op, deep_layer ().layer (), il, ol);
}
return std::make_pair (dl_out1, dl_out2);
}
RegionDelegate *
DeepRegion::xor_with (const Region &other) const
DeepRegion::xor_with (const Region &other, db::PropertyConstraint property_constraint) const
{
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
@ -811,14 +956,14 @@ DeepRegion::xor_with (const Region &other) const
} else if (! other_deep) {
return AsIfFlatRegion::xor_with (other);
return AsIfFlatRegion::xor_with (other, property_constraint);
} else {
// Implement XOR as (A-B)+(B-A) - only this implementation
// is compatible with the local processor scheme
DeepLayer n1 (and_or_not_with (other_deep, false));
DeepLayer n2 (other_deep->and_or_not_with (this, false));
DeepLayer n1 (and_or_not_with (other_deep, false, property_constraint));
DeepLayer n2 (other_deep->and_or_not_with (this, false, property_constraint));
n1.add_from (n2);
return new DeepRegion (n1);
@ -1168,89 +1313,13 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy)
return res.release ();
}
namespace
{
class PolygonToEdgeLocalOperation
: public local_operation<db::PolygonRef, db::PolygonRef, db::Edge>
{
public:
PolygonToEdgeLocalOperation ()
: local_operation<db::PolygonRef, db::PolygonRef, db::Edge> ()
{
// .. nothing yet ..
}
virtual db::Coord dist () const { return 1; }
virtual bool requests_single_subjects () const { return true; }
virtual std::string description () const { return std::string ("polygon to edges"); }
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
db::EdgeProcessor ep;
ep.set_base_verbosity (50);
for (shape_interactions<db::PolygonRef, db::PolygonRef>::subject_iterator s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) {
ep.insert (s->second);
}
if (interactions.num_intruders () == 0) {
db::EdgeToEdgeSetGenerator eg (results.front ());
db::MergeOp op (0);
ep.process (eg, op);
} else {
// With intruders: to compute our local contribution we take the edges without and with intruders
// and deliver what is in both sets
db::MergeOp op (0);
std::vector<Edge> edges1;
db::EdgeContainer ec1 (edges1);
ep.process (ec1, op);
ep.clear ();
for (shape_interactions<db::PolygonRef, db::PolygonRef>::subject_iterator s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) {
ep.insert (s->second);
}
for (shape_interactions<db::PolygonRef, db::PolygonRef>::intruder_iterator i = interactions.begin_intruders (); i != interactions.end_intruders (); ++i) {
ep.insert (i->second.second);
}
std::vector<Edge> edges2;
db::EdgeContainer ec2 (edges2);
ep.process (ec2, op);
// Runs the boolean AND between the result with and without intruders
db::box_scanner<db::Edge, size_t> scanner;
scanner.reserve (edges1.size () + edges2.size ());
for (std::vector<Edge>::const_iterator i = edges1.begin (); i != edges1.end (); ++i) {
scanner.insert (i.operator-> (), 0);
}
for (std::vector<Edge>::const_iterator i = edges2.begin (); i != edges2.end (); ++i) {
scanner.insert (i.operator-> (), 1);
}
EdgeBooleanClusterCollector<std::unordered_set<db::Edge> > cluster_collector (&results.front (), EdgeAnd);
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
}
}
};
}
EdgesDelegate *
DeepRegion::edges (const EdgeFilterBase *filter) const
{
std::unique_ptr<db::DeepEdges> res (new db::DeepEdges (deep_layer ().derived ()));
if (empty ()) {
return new db::DeepEdges (deep_layer ().derived ());
return res.release ();
}
if (! filter && merged_semantics () && ! merged_polygons_available ()) {
@ -1259,29 +1328,22 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
const db::DeepLayer &polygons = deep_layer ();
db::PolygonToEdgeLocalOperation op;
db::PolygonToEdgeLocalOperation op (res->properties_repository (), &polygons.layout ().properties_repository ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()),
const_cast<db::Cell *> (&polygons.initial_cell ()),
polygons.breakout_cells ());
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties> proc (&res->deep_layer ().layout (), &res->deep_layer ().initial_cell (), polygons.breakout_cells ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
// a boolean core makes somewhat better hierarchy
proc.set_boolean_core (true);
std::unique_ptr<db::DeepEdges> res (new db::DeepEdges (polygons.derived ()));
proc.run (&op, polygons.layer (), foreign_idlayer (), res->deep_layer ().layer ());
return res.release ();
} else {
const db::DeepLayer &polygons = merged_deep_layer ();
db::PropertyMapper pm (res->properties_repository (), &polygons.layout ().properties_repository ());
std::unique_ptr<VariantsCollectorBase> vars;
@ -1298,7 +1360,6 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
std::unique_ptr<db::DeepEdges> res (new db::DeepEdges (polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
db::ICplxTrans tr;
@ -1318,7 +1379,7 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
if (! filter || filter->selected ((*e).transformed (tr))) {
st.insert (*e);
st.insert (db::EdgeWithProperties (*e, pm (si->prop_id ())));
}
}
@ -1327,9 +1388,10 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
}
res->set_is_merged (merged_semantics () || is_merged ());
return res.release ();
}
return res.release ();
}
RegionDelegate *
@ -1593,6 +1655,7 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
db::SizingPolygonFilter siz (pg2, d_with_mag, d_with_mag, mode);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
pr.set_prop_id (si->prop_id ());
db::Polygon poly;
si->polygon (poly);
siz.put (poly);
@ -1655,6 +1718,7 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
db::SizingPolygonFilter siz (pg2, dx_with_mag, dy_with_mag, mode);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
pr.set_prop_id (si->prop_id ());
db::Polygon poly;
si->polygon (poly);
siz.put (poly);
@ -1683,17 +1747,16 @@ Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &no
}
}
db::local_processor<db::PolygonRef, db::PolygonRef, TR> proc (const_cast<db::Layout *> (&region->deep_layer ().layout ()),
const_cast<db::Cell *> (&region->deep_layer ().initial_cell ()),
region->deep_layer ().breakout_cells ());
const db::DeepLayer &polygons (region->merged_deep_layer ());
std::unique_ptr<Output> res (new Output (polygons.derived ()));
db::local_processor<db::PolygonRef, db::PolygonRef, TR> proc (&res->deep_layer ().layout (), &res->deep_layer ().initial_cell (), region->deep_layer ().breakout_cells ());
proc.set_description (region->progress_desc ());
proc.set_report_progress (region->report_progress ());
proc.set_base_verbosity (region->base_verbosity ());
proc.set_threads (region->deep_layer ().store ()->threads ());
const db::DeepLayer &polygons (region->merged_deep_layer ());
std::vector<unsigned int> other_layers;
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
@ -1714,41 +1777,108 @@ Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &no
}
std::unique_ptr<Output> res (new Output (polygons.derived ()));
compound_local_operation<db::PolygonRef, db::PolygonRef, TR> op (&node);
proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ());
return res.release ();
}
EdgePairsDelegate *
DeepRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node)
template <class TR, class Output>
static
Output *region_cop_with_properties_impl (DeepRegion *region, db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{
DeepEdgePairs *output = region_cop_impl<db::EdgePair, DeepEdgePairs> (this, node);
// Fall back to flat mode if one of the inputs is flat
std::vector<db::Region *> inputs = node.inputs ();
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
if (! is_subject_regionptr (*i) && ! dynamic_cast<const db::DeepRegion *> ((*i)->delegate ())) {
return 0;
}
}
const db::DeepLayer &polygons (region->merged_deep_layer ());
std::unique_ptr<Output> res (new Output (polygons.derived ()));
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::object_with_properties<TR> > proc (&res->deep_layer ().layout (), &res->deep_layer ().initial_cell (), region->deep_layer ().breakout_cells ());
proc.set_description (region->progress_desc ());
proc.set_report_progress (region->report_progress ());
proc.set_base_verbosity (region->base_verbosity ());
proc.set_threads (region->deep_layer ().store ()->threads ());
std::vector<unsigned int> other_layers;
std::vector<const db::PropertiesRepository *> intruder_prs;
const db::PropertiesRepository *subject_pr = &polygons.layout ().properties_repository ();
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
if (is_subject_regionptr (*i)) {
if (*i == subject_regionptr ()) {
other_layers.push_back (subject_idlayer ());
} else {
other_layers.push_back (foreign_idlayer ());
}
intruder_prs.push_back (subject_pr);
} else {
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> ((*i)->delegate ());
tl_assert (other_deep != 0);
if (&other_deep->deep_layer ().layout () != &region->deep_layer ().layout () || &other_deep->deep_layer ().initial_cell () != &region->deep_layer ().initial_cell ()) {
throw tl::Exception (tl::to_string (tr ("Complex DeepRegion operations need to use the same layout and top cell for all inputs")));
}
other_layers.push_back (other_deep->deep_layer ().layer ());
intruder_prs.push_back (other_deep->properties_repository ());
}
}
compound_local_operation_with_properties<db::PolygonRef, db::PolygonRef, TR> op (&node, prop_constraint, res->properties_repository (), subject_pr, intruder_prs);
proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ());
return res.release ();
}
EdgePairsDelegate *
DeepRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{
DeepEdgePairs *output = 0;
if (pc_skip (prop_constraint)) {
output = region_cop_impl<db::EdgePair, DeepEdgePairs> (this, node);
} else {
output = region_cop_with_properties_impl<db::EdgePair, DeepEdgePairs> (this, node, prop_constraint);
}
if (! output) {
return AsIfFlatRegion::cop_to_edge_pairs (node);
return AsIfFlatRegion::cop_to_edge_pairs (node, prop_constraint);
} else {
return output;
}
}
RegionDelegate *
DeepRegion::cop_to_region (db::CompoundRegionOperationNode &node)
DeepRegion::cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{
DeepRegion *output = region_cop_impl<db::PolygonRef, db::DeepRegion> (this, node);
DeepRegion *output = 0;
if (pc_skip (prop_constraint)) {
output = region_cop_impl<db::PolygonRef, db::DeepRegion> (this, node);
} else {
output = region_cop_with_properties_impl<db::PolygonRef, DeepRegion> (this, node, prop_constraint);
}
if (! output) {
return AsIfFlatRegion::cop_to_region (node);
return AsIfFlatRegion::cop_to_region (node, prop_constraint);
} else {
return output;
}
}
EdgesDelegate *
DeepRegion::cop_to_edges (db::CompoundRegionOperationNode &node)
DeepRegion::cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{
DeepEdges *output = region_cop_impl<db::Edge, db::DeepEdges> (this, node);
DeepEdges *output = 0;
if (pc_skip (prop_constraint)) {
output = region_cop_impl<db::Edge, DeepEdges> (this, node);
} else {
output = region_cop_with_properties_impl<db::Edge, DeepEdges> (this, node, prop_constraint);
}
if (! output) {
return AsIfFlatRegion::cop_to_edges (node);
return AsIfFlatRegion::cop_to_edges (node, prop_constraint);
} else {
return output;
}
@ -1763,6 +1893,11 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
return new db::DeepEdgePairs (deep_layer ().derived ());
}
// force different polygons in the different properties case to skip intra-polygon checks
if (pc_always_different (options.prop_constraint)) {
different_polygons = true;
}
const db::DeepRegion *other_deep = 0;
unsigned int other_layer = 0;
bool other_is_merged = true;
@ -1782,6 +1917,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, options);
}
if (! other->merged_semantics ()) {
other_layer = other_deep->deep_layer ().layer ();
other_is_merged = true;
} else if (options.whole_edges) {
// NOTE: whole edges needs both inputs merged
@ -1804,21 +1940,40 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
std::unique_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (polygons.derived ()));
db::CheckLocalOperation op (check, different_polygons, primary_is_merged, other_deep != 0, other_is_merged, options);
db::Layout *subject_layout = &res->deep_layer ().layout ();
db::Cell *subject_top = &res->deep_layer ().initial_cell ();
const db::Layout *intruder_layout = other_deep ? &other_deep->deep_layer ().layout () : &polygons.layout ();
const db::Cell *intruder_top = other_deep ? &other_deep->deep_layer ().initial_cell () : &polygons.initial_cell ();
const std::set<db::cell_index_type> *subject_breakout_cells = deep_layer ().breakout_cells ();
const std::set<db::cell_index_type> *intruder_breakout_cells = other_deep ? other_deep->deep_layer ().breakout_cells () : 0;
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&polygons.layout ()),
const_cast<db::Cell *> (&polygons.initial_cell ()),
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&polygons.layout ()),
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&polygons.initial_cell ()),
deep_layer ().breakout_cells (),
other_deep ? other_deep->deep_layer ().breakout_cells () : 0);
if (options.prop_constraint == db::IgnoreProperties) {
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
db::CheckLocalOperation op (check, different_polygons, primary_is_merged, other_deep != 0, other_is_merged, options);
proc.run (&op, polygons.layer (), other_layer, res->deep_layer ().layer ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (subject_layout, subject_top,
intruder_layout, intruder_top,
subject_breakout_cells, intruder_breakout_cells);
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
proc.run (&op, polygons.layer (), other_layer, res->deep_layer ().layer ());
} else {
db::check_local_operation_with_properties<db::PolygonRef, db::PolygonRef> op (check, different_polygons, primary_is_merged, other_deep != 0, other_is_merged, options, res->properties_repository (), properties_repository (), other_deep ? other_deep->properties_repository () : &polygons.layout ().properties_repository ());
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties> proc (subject_layout, subject_top,
intruder_layout, intruder_top,
subject_breakout_cells, intruder_breakout_cells);
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
proc.run (&op, polygons.layer (), other_layer, res->deep_layer ().layer ());
}
return res.release ();
}
@ -1849,7 +2004,7 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::Polygons); ! s.at_end (); ++s) {
edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result, options.negative, false /*does not require different polygons*/, false /*does not require different layers*/, options.shielded, true /*symmetric edge pairs*/);
edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result, options.negative, false /*does not require different polygons*/, false /*does not require different layers*/, options.shielded, true /*symmetric edge pairs*/, pc_remove (options.prop_constraint) ? 0 : s->prop_id ());
poly2poly_check<db::Polygon> poly_check (edge_check);
db::Polygon poly;
@ -1955,9 +2110,7 @@ DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode outpu
db::ContainedLocalOperation op (output_mode);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
InteractingResultHolder orh (output_mode, merged_semantics (), polygons);
@ -2019,9 +2172,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
db::InteractingLocalOperation op (mode, touching, output_mode, min_count, max_count, true);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
@ -2076,9 +2227,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputM
db::InteractingWithEdgeLocalOperation op (output_mode, min_count, max_count, true);
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
@ -2122,9 +2271,7 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
db::PullLocalOperation op (mode, touching);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
@ -2162,9 +2309,7 @@ DeepRegion::pull_generic (const Edges &other) const
db::PullWithEdgeLocalOperation op;
db::local_processor<db::PolygonRef, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell (), polygons.breakout_cells (), other_edges.breakout_cells ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
proc.run (&op, polygons.layer (), other_edges.layer (), dl_out.layer ());
@ -2197,9 +2342,7 @@ DeepRegion::pull_generic (const Texts &other) const
db::PullWithTextLocalOperation op;
db::local_processor<db::PolygonRef, db::TextRef, db::TextRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_texts.layout (), &other_texts.initial_cell (), polygons.breakout_cells (), other_texts.breakout_cells ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
proc.run (&op, polygons.layer (), other_texts.layer (), dl_out.layer ());
@ -2246,9 +2389,7 @@ DeepRegion::selected_interacting_generic (const Texts &other, InteractingOutputM
db::InteractingWithTextLocalOperation op (output_mode, min_count, max_count);
db::local_processor<db::PolygonRef, db::TextRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
configure_proc (proc);
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
proc.set_area_ratio (polygons.store ()->max_area_ratio ());

View File

@ -53,7 +53,7 @@ public:
RegionDelegate *clone () const;
virtual void do_insert (const db::Polygon &polygon);
virtual void do_insert (const db::Polygon &polygon, db::properties_id_type prop_id);
virtual void do_transform (const db::Trans &t);
virtual void do_transform (const db::ICplxTrans &t);
@ -74,10 +74,14 @@ public:
virtual bool is_merged () const;
virtual const db::Polygon *nth (size_t n) const;
virtual db::properties_id_type nth_prop_id (size_t n) const;
virtual bool has_valid_polygons () const;
virtual bool has_valid_merged_polygons () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
@ -92,15 +96,15 @@ public:
virtual std::string to_string (size_t nmax) const;
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node);
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node);
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node);
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
virtual RegionDelegate *and_with (const Region &other) const;
virtual RegionDelegate *not_with (const Region &other) const;
virtual RegionDelegate *xor_with (const Region &other) const;
virtual RegionDelegate *or_with (const Region &other) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &) const;
virtual RegionDelegate *and_with (const Region &other, db::PropertyConstraint property_constraint) const;
virtual RegionDelegate *not_with (const Region &other, db::PropertyConstraint property_constraint) const;
virtual RegionDelegate *xor_with (const Region &other, db::PropertyConstraint property_constraint) const;
virtual RegionDelegate *or_with (const Region &other, db::PropertyConstraint property_constraint) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &, db::PropertyConstraint property_constraint) const;
virtual RegionDelegate *add_in_place (const Region &other);
virtual RegionDelegate *add (const Region &other) const;
@ -135,6 +139,8 @@ public:
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const Net *> *nets) const;
virtual DeepShapeCollectionDelegateBase *deep ()
{
return this;
@ -171,11 +177,19 @@ private:
void init ();
void ensure_merged_polygons_valid () const;
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op) const;
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other) const;
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op, PropertyConstraint property_constraint) const;
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const;
DeepRegion *apply_filter (const PolygonFilterBase &filter) const;
template <class Result, class OutputContainer> OutputContainer *processed_impl (const polygon_processor<Result> &filter) const;
template <class Proc>
void configure_proc (Proc &proc) const
{
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
}
};
}

View File

@ -33,6 +33,7 @@
#include "dbDeepEdgePairs.h"
#include "dbDeepTexts.h"
#include "dbShapeCollection.h"
#include "dbLayoutToNetlist.h"
#include "tlTimer.h"
@ -50,7 +51,7 @@ DeepLayer::DeepLayer ()
DeepLayer::DeepLayer (const Region &region)
: mp_store (), m_layout (0), m_layer (0)
{
const db::DeepRegion *dr = dynamic_cast<db::DeepRegion *> (region.delegate ());
const db::DeepRegion *dr = dynamic_cast<const db::DeepRegion *> (region.delegate ());
tl_assert (dr != 0);
*this = dr->deep_layer ();
}
@ -58,7 +59,7 @@ DeepLayer::DeepLayer (const Region &region)
DeepLayer::DeepLayer (const Texts &texts)
: mp_store (), m_layout (0), m_layer (0)
{
const db::DeepTexts *dr = dynamic_cast<db::DeepTexts *> (texts.delegate ());
const db::DeepTexts *dr = dynamic_cast<const db::DeepTexts *> (texts.delegate ());
tl_assert (dr != 0);
*this = dr->deep_layer ();
}
@ -66,7 +67,7 @@ DeepLayer::DeepLayer (const Texts &texts)
DeepLayer::DeepLayer (const Edges &edges)
: mp_store (), m_layout (0), m_layer (0)
{
const db::DeepEdges *dr = dynamic_cast<db::DeepEdges *> (edges.delegate ());
const db::DeepEdges *dr = dynamic_cast<const db::DeepEdges *> (edges.delegate ());
tl_assert (dr != 0);
*this = dr->deep_layer ();
}
@ -74,7 +75,7 @@ DeepLayer::DeepLayer (const Edges &edges)
DeepLayer::DeepLayer (const EdgePairs &edge_pairs)
: mp_store (), m_layout (0), m_layer (0)
{
const db::DeepEdgePairs *dr = dynamic_cast<db::DeepEdgePairs *> (edge_pairs.delegate ());
const db::DeepEdgePairs *dr = dynamic_cast<const db::DeepEdgePairs *> (edge_pairs.delegate ());
tl_assert (dr != 0);
*this = dr->deep_layer ();
}
@ -261,10 +262,31 @@ DeepLayer::check_dss () const
}
}
// ----------------------------------------------------------------------------------
struct DeepShapeStore::LayoutHolder
{
class L2NStatusChangedListener
: public tl::Object
{
public:
L2NStatusChangedListener (DeepShapeStore::LayoutHolder *lh, db::LayoutToNetlist *l2n)
: mp_lh (lh), mp_l2n (l2n)
{
mp_l2n->status_changed_event ().add (this, &L2NStatusChangedListener::l2n_destroyed);
}
private:
void l2n_destroyed (gsi::ObjectBase::StatusEventType ev)
{
if (ev == gsi::ObjectBase::ObjectDestroyed) {
// CAUTION: this will eventually delete *this!
mp_lh->remove_l2n (mp_l2n);
}
}
DeepShapeStore::LayoutHolder *mp_lh;
db::LayoutToNetlist *mp_l2n;
};
LayoutHolder (const db::ICplxTrans &trans)
: refs (0), layout (false), builder (&layout, trans)
{
@ -287,16 +309,42 @@ struct DeepShapeStore::LayoutHolder
}
}
bool has_net_builder_for (db::LayoutToNetlist *l2n) const
{
auto l = net_builders.find (l2n);
return (l != net_builders.end ());
}
db::NetBuilder &net_builder_for (db::Cell &top, db::LayoutToNetlist *l2n)
{
auto l = net_builders.find (l2n);
if (l == net_builders.end ()) {
l = net_builders.insert (std::make_pair (l2n, std::make_pair (L2NStatusChangedListener (this, l2n), db::NetBuilder (&layout, l2n->cell_mapping_into (layout, top, false), l2n)))).first;
return l->second.second;
} else {
return l->second.second;
}
}
void remove_l2n (db::LayoutToNetlist *l2n)
{
auto l = net_builders.find (l2n);
if (l != net_builders.end ()) {
net_builders.erase (l);
}
}
int refs;
db::Layout layout;
db::HierarchyBuilder builder;
std::map<db::LayoutToNetlist *, std::pair<L2NStatusChangedListener, db::NetBuilder> > net_builders;
std::map<unsigned int, int> layer_refs;
};
// ----------------------------------------------------------------------------------
DeepShapeStoreState::DeepShapeStoreState ()
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_reject_odd_polygons (false), m_text_property_name (), m_text_enlargement (-1)
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_reject_odd_polygons (false), m_text_property_name (), m_text_enlargement (-1), m_subcircuit_hierarchy_for_nets (false)
{
// .. nothing yet ..
}
@ -403,6 +451,19 @@ DeepShapeStoreState::max_vertex_count () const
return m_max_vertex_count;
}
void
DeepShapeStoreState::set_subcircuit_hierarchy_for_nets (bool f)
{
m_subcircuit_hierarchy_for_nets = f;
}
bool
DeepShapeStoreState::subcircuit_hierarchy_for_nets () const
{
return m_subcircuit_hierarchy_for_nets;
}
// ----------------------------------------------------------------------------------
static size_t s_instance_count = 0;
@ -475,19 +536,20 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Region &region, bool for_n
db::Shapes *shapes = &initial_cell ().shapes (layer);
db::Box world = db::Box::world ();
// The chain of operators for producing clipped and reduced polygon references
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout (), text_enlargement (), text_property_name ());
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count, m_state.reject_odd_polygons ());
// try to maintain the texts on top level - go through shape iterator
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = region.begin_iter ();
db::ICplxTrans ttop = trans * ii.second;
// The chain of operators for producing clipped and reduced polygon references
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout (), ii.first.layout (), text_enlargement (), text_property_name ());
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count, m_state.reject_odd_polygons ());
while (! ii.first.at_end ()) {
if (for_netlist && ii.first->is_text () && ii.first.layout () && ii.first.cell () != ii.first.top_cell ()) {
// Skip texts on levels below top cell. For the reasoning see the description of this method.
} else {
red.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes);
red.push (*ii.first, ii.first.prop_id (), ttop * ii.first.trans (), world, 0, shapes);
}
++ii.first;
@ -515,12 +577,12 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Edges &edges, const db::IC
db::Shapes *shapes = &initial_cell ().shapes (layer);
db::Box world = db::Box::world ();
db::EdgeBuildingHierarchyBuilderShapeReceiver eb (false);
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = edges.begin_iter ();
db::ICplxTrans ttop = trans * ii.second;
db::EdgeBuildingHierarchyBuilderShapeReceiver eb (&layout (), ii.first.layout (), false);
while (! ii.first.at_end ()) {
eb.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes);
eb.push (*ii.first, ii.first.prop_id (), ttop * ii.first.trans (), world, 0, shapes);
++ii.first;
}
@ -545,12 +607,13 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Texts &texts, const db::IC
db::Shapes *shapes = &initial_cell ().shapes (layer);
db::Box world = db::Box::world ();
db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout ());
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = texts.begin_iter ();
db::ICplxTrans ttop = trans * ii.second;
db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout (), ii.first.layout ());
while (! ii.first.at_end ()) {
tb.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes);
tb.push (*ii.first, ii.first.prop_id (), ttop * ii.first.trans (), world, 0, shapes);
++ii.first;
}
@ -621,6 +684,16 @@ const tl::Variant &DeepShapeStore::text_property_name () const
return m_state.text_property_name ();
}
void DeepShapeStore::set_subcircuit_hierarchy_for_nets (bool f)
{
m_state.set_subcircuit_hierarchy_for_nets (f);
}
bool DeepShapeStore::subcircuit_hierarchy_for_nets () const
{
return m_state.subcircuit_hierarchy_for_nets ();
}
const std::set<db::cell_index_type> *
DeepShapeStore::breakout_cells (unsigned int layout_index) const
{
@ -651,6 +724,27 @@ DeepShapeStore::add_breakout_cells (unsigned int layout_index, const std::set<db
m_state.add_breakout_cells (layout_index, cc);
}
bool
DeepShapeStore::has_net_builder_for (unsigned int layout_index, db::LayoutToNetlist *l2n)
{
return m_layouts [layout_index]->has_net_builder_for (l2n);
}
db::NetBuilder &
DeepShapeStore::net_builder_for (unsigned int layout_index, db::LayoutToNetlist *l2n)
{
db::NetBuilder &nb = m_layouts [layout_index]->net_builder_for (initial_cell (layout_index), l2n);
if (subcircuit_hierarchy_for_nets ()) {
nb.set_hier_mode (db::BNH_SubcircuitCells);
nb.set_cell_name_prefix ("X$$"); // TODO: needs to be a configuration option?
} else {
nb.set_hier_mode (db::BNH_Flatten);
}
return nb;
}
void DeepShapeStore::set_threads (int n)
{
m_state.set_threads (n);
@ -836,7 +930,7 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
builder.set_target_layer (layer_index);
// The chain of operators for producing clipped and reduced polygon references
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (& layout, text_enlargement (), text_property_name ());
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout, si.layout (), text_enlargement (), text_property_name ());
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count, m_state.reject_odd_polygons ());
db::ClippingHierarchyBuilderShapeReceiver clip (&red);
@ -905,7 +999,7 @@ DeepLayer DeepShapeStore::create_copy (const DeepLayer &source, HierarchyBuilder
db::Shapes &into = c->shapes (layer_index);
const db::Shapes &from = c->shapes (from_layer_index);
for (db::Shapes::shape_iterator s = from.begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
pipe->push (*s, trans, region, 0, &into);
pipe->push (*s, s->prop_id (), trans, region, 0, &into);
}
}
@ -914,13 +1008,19 @@ DeepLayer DeepShapeStore::create_copy (const DeepLayer &source, HierarchyBuilder
DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &si, bool as_edges, const db::ICplxTrans &trans)
{
db::EdgeBuildingHierarchyBuilderShapeReceiver refs (as_edges);
unsigned int layout_index = layout_for_iter (si, trans);
db::Layout &layout = m_layouts[layout_index]->layout;
db::EdgeBuildingHierarchyBuilderShapeReceiver refs (&layout, si.layout (), as_edges);
return create_custom_layer (si, &refs, trans);
}
DeepLayer DeepShapeStore::create_edge_pair_layer (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
{
db::EdgePairBuildingHierarchyBuilderShapeReceiver refs;
unsigned int layout_index = layout_for_iter (si, trans);
db::Layout &layout = m_layouts[layout_index]->layout;
db::EdgePairBuildingHierarchyBuilderShapeReceiver refs (&layout, si.layout ());
return create_custom_layer (si, &refs, trans);
}
@ -929,7 +1029,7 @@ DeepLayer DeepShapeStore::create_text_layer (const db::RecursiveShapeIterator &s
unsigned int layout_index = layout_for_iter (si, trans);
db::Layout &layout = m_layouts[layout_index]->layout;
db::TextBuildingHierarchyBuilderShapeReceiver refs (&layout);
db::TextBuildingHierarchyBuilderShapeReceiver refs (&layout, si.layout ());
return create_custom_layer (si, &refs, trans);
}
@ -1200,19 +1300,32 @@ DeepShapeStore::insert_as_polygons (const DeepLayer &deep_layer, db::Layout *int
if (s->is_edge_pair ()) {
out.insert (s->edge_pair ().normalized ().to_simple_polygon (enl));
if (s->prop_id () != 0) {
out.insert (db::SimplePolygonWithProperties (s->edge_pair ().normalized ().to_simple_polygon (enl), s->prop_id ()));
} else {
out.insert (s->edge_pair ().normalized ().to_simple_polygon (enl));
}
} else if (s->is_path () || s->is_polygon () || s->is_box ()) {
db::Polygon poly;
s->polygon (poly);
out.insert (poly);
if (s->prop_id () != 0) {
out.insert (db::PolygonWithProperties (poly, s->prop_id ()));
} else {
out.insert (poly);
}
} else if (s->is_text ()) {
db::Text t;
s->text (t);
out.insert (db::SimplePolygon (t.box ().enlarged (db::Vector (enl, enl))));
db::SimplePolygon sp (t.box ().enlarged (db::Vector (enl, enl)));
if (s->prop_id () != 0) {
out.insert (db::SimplePolygonWithProperties (sp, s->prop_id ()));
} else {
out.insert (sp);
}
}

View File

@ -47,6 +47,8 @@ class Edges;
class EdgePairs;
class Texts;
class ShapeCollection;
class NetBuilder;
class LayoutToNetlist;
/**
* @brief Represents a shape collection from the deep shape store
@ -220,6 +222,16 @@ public:
return mp_store.get ();
}
/**
* @brief Gets the non-const shape store object
* This feature is intended for internal purposes.
*/
DeepShapeStore *store_non_const () const
{
check_dss ();
return const_cast<DeepShapeStore *> (mp_store.get ());
}
private:
friend class DeepShapeStore;
@ -262,6 +274,9 @@ public:
void add_breakout_cell (unsigned int layout_index, db::cell_index_type ci);
void add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc);
void set_subcircuit_hierarchy_for_nets (bool f);
bool subcircuit_hierarchy_for_nets () const;
private:
int m_threads;
double m_max_area_ratio;
@ -270,6 +285,7 @@ private:
tl::Variant m_text_property_name;
std::vector<std::set<db::cell_index_type> > m_breakout_cells;
int m_text_enlargement;
bool m_subcircuit_hierarchy_for_nets;
std::set<db::cell_index_type> &ensure_breakout_cells (unsigned int layout_index)
{
@ -668,6 +684,37 @@ public:
*/
bool is_valid_layout_index (unsigned int n) const;
/**
* @brief Gets the net builder object for a given layout index and LayoutToNetlist database
*
* If no net builder is available, one will be created. Use \\has_net_builder to check whether one is
* already created.
*/
db::NetBuilder &net_builder_for (unsigned int layout_index, db::LayoutToNetlist *l2n);
/**
* @brief Gets the net builder object for a given LayoutToNetlist database (requires the DSS to be singular)
*/
db::NetBuilder &net_builder_for (db::LayoutToNetlist *l2n)
{
require_singular ();
return net_builder_for (0, l2n);
}
/**
* @brief Gets a value indicating whether a net building is available
*/
bool has_net_builder_for(unsigned int layout_index, db::LayoutToNetlist *l2n);
/**
* @brief Gets the net builder object for a given LayoutToNetlist database (requires the DSS to be singular)
*/
bool has_net_builder_for (db::LayoutToNetlist *l2n)
{
require_singular ();
return has_net_builder_for (0, l2n);
}
/**
* @brief The deep shape store also keeps the number of threads to allocate for the hierarchical processor
*
@ -752,6 +799,20 @@ public:
*/
int text_enlargement () const;
/**
* @brief Sets a value indicating whether to build a subcircuit hierarchy per net
*
* This flag is used to determine the way, net subcircuit hierarchies are built:
* when true, subcells are created for subcircuits on a net. Otherwise the net
* shapes are produced flat inside the cell they appear on.
*/
void set_subcircuit_hierarchy_for_nets (bool f);
/**
* @brief Gets a value indicating whether to build a subcircuit hierarchy per net
*/
bool subcircuit_hierarchy_for_nets () const;
/**
* @brief Gets the breakout cells for a given layout
* Returns 0 if there are no breakout cells for this layout.

View File

@ -49,7 +49,7 @@ public:
typedef db::Text value_type;
DeepTextsIterator (const db::RecursiveShapeIterator &iter)
: m_iter (iter)
: m_iter (iter), m_prop_id (0)
{
set ();
}
@ -77,6 +77,11 @@ public:
return &m_text;
}
virtual db::properties_id_type prop_id () const
{
return m_prop_id;
}
virtual bool equals (const generic_shape_iterator_delegate_base<value_type> *other) const
{
const DeepTextsIterator *o = dynamic_cast<const DeepTextsIterator *> (other);
@ -105,12 +110,14 @@ private:
db::RecursiveShapeIterator m_iter;
mutable value_type m_text;
mutable db::properties_id_type m_prop_id;
void set () const
{
if (! m_iter.at_end ()) {
m_iter.shape ().text (m_text);
m_iter->text (m_text);
m_text.transform (m_iter.trans ());
m_prop_id = m_iter->prop_id ();
}
}
};
@ -331,6 +338,21 @@ const db::RecursiveShapeIterator *DeepTexts::iter () const
return 0;
}
void DeepTexts::apply_property_translator (const db::PropertiesTranslator &pt)
{
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
}
db::PropertiesRepository *DeepTexts::properties_repository ()
{
return &deep_layer ().layout ().properties_repository ();
}
const db::PropertiesRepository *DeepTexts::properties_repository () const
{
return &deep_layer ().layout ().properties_repository ();
}
TextsDelegate *
DeepTexts::add_in_place (const Texts &other)
{

View File

@ -73,6 +73,9 @@ public:
virtual const db::Text *nth (size_t n) const;
virtual bool has_valid_texts () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual TextsDelegate *filter_in_place (const TextFilterBase &filter);
virtual TextsDelegate *filtered (const TextFilterBase &) const;

View File

@ -409,13 +409,13 @@ public:
typedef Iterator const_iterator;
ShapesToOutputContainerAdaptor ()
: mp_shapes (0)
: mp_shapes (0), m_prop_id (0)
{
// .. nothing yet ..
}
ShapesToOutputContainerAdaptor (db::Shapes &shapes)
: mp_shapes (&shapes)
ShapesToOutputContainerAdaptor (db::Shapes &shapes, db::properties_id_type prop_id = 0)
: mp_shapes (&shapes), m_prop_id (prop_id)
{
// .. nothing yet ..
}
@ -432,11 +432,16 @@ public:
void insert (const db::Edge &edge)
{
mp_shapes->insert (edge);
if (m_prop_id != 0) {
mp_shapes->insert (db::EdgeWithProperties (edge, m_prop_id));
} else {
mp_shapes->insert (edge);
}
}
private:
db::Shapes *mp_shapes;
db::properties_id_type m_prop_id;
};
/**
@ -445,13 +450,13 @@ private:
struct DB_PUBLIC EdgeBooleanClusterCollectorToShapes
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor>
{
EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op)
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor> (&m_adaptor, op), m_adaptor (*output)
EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op, db::properties_id_type prop_id = 0)
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor> (&m_adaptor, op), m_adaptor (*output, prop_id)
{
}
EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op, db::Shapes *output2)
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor> (&m_adaptor, op, &m_adaptor2), m_adaptor (*output), m_adaptor2 (*output2)
EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op, db::Shapes *output2, db::properties_id_type prop_id = 0)
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor> (&m_adaptor, op, &m_adaptor2), m_adaptor (*output, prop_id), m_adaptor2 (*output2, prop_id)
{
}

View File

@ -149,10 +149,26 @@ const db::RecursiveShapeIterator &
EdgePairs::iter () const
{
static db::RecursiveShapeIterator def_iter;
const db::RecursiveShapeIterator *i = mp_delegate->iter ();
const db::RecursiveShapeIterator *i = mp_delegate ? mp_delegate->iter () : 0;
return *(i ? i : &def_iter);
}
const db::PropertiesRepository &
EdgePairs::properties_repository () const
{
static db::PropertiesRepository empty_prop_repo;
const db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
return *(r ? r : &empty_prop_repo);
}
db::PropertiesRepository &
EdgePairs::properties_repository ()
{
db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
tl_assert (r != 0);
return *r;
}
void EdgePairs::processed (Region &output, const EdgePairToPolygonProcessorBase &filter) const
{
output = Region (mp_delegate->processed_to_polygons (filter));

View File

@ -44,63 +44,8 @@ class DeepShapeStore;
class TransformationReducer;
class EdgeFilterBase;
/**
* @brief An edge pair set iterator
*
* The iterator delivers the edge pairs of the edge pair set
*/
class DB_PUBLIC EdgePairsIterator
: public generic_shape_iterator<db::EdgePair>
{
public:
/**
* @brief Default constructor
*/
EdgePairsIterator ()
: generic_shape_iterator<db::EdgePair> ()
{
// .. nothing yet ..
}
/**
* @brief Constructor from a delegate
* The iterator will take ownership over the delegate
*/
EdgePairsIterator (EdgePairsIteratorDelegate *delegate)
: generic_shape_iterator<db::EdgePair> (delegate)
{
// .. nothing yet ..
}
/**
* @brief Copy constructor and assignment
*/
EdgePairsIterator (const EdgePairsIterator &other)
: generic_shape_iterator<db::EdgePair> (static_cast<const generic_shape_iterator<db::EdgePair> &> (other))
{
// .. nothing yet ..
}
/**
* @brief Assignment
*/
EdgePairsIterator &operator= (const EdgePairsIterator &other)
{
generic_shape_iterator<db::EdgePair>::operator= (other);
return *this;
}
/**
* @brief Increment
*/
EdgePairsIterator &operator++ ()
{
generic_shape_iterator<db::EdgePair>::operator++ ();
return *this;
}
};
typedef addressable_shape_delivery_gen<EdgePairsIterator> AddressableEdgePairDelivery;
typedef generic_shape_iterator<EdgePair> EdgePairsIterator;
typedef addressable_shape_delivery<EdgePair> AddressableEdgePairDelivery;
class EdgePairs;
@ -251,7 +196,15 @@ public:
/**
* @brief Gets the underlying delegate object
*/
EdgePairsDelegate *delegate () const
const EdgePairsDelegate *delegate () const
{
return mp_delegate;
}
/**
* @brief Gets the underlying delegate object
*/
EdgePairsDelegate *delegate ()
{
return mp_delegate;
}
@ -488,7 +441,7 @@ public:
*/
AddressableEdgePairDelivery addressable_edge_pairs () const
{
return AddressableEdgePairDelivery (begin (), has_valid_edge_pairs ());
return AddressableEdgePairDelivery (begin ());
}
/**
@ -498,6 +451,20 @@ public:
*/
const db::RecursiveShapeIterator &iter () const;
/**
* @brief Gets the property repository
*
* Use this object to decode property IDs.
*/
const db::PropertiesRepository &properties_repository () const;
/**
* @brief Gets the property repository
*
* Use this object to decode and encode property IDs.
*/
db::PropertiesRepository &properties_repository ();
/**
* @brief Equality
*/

View File

@ -166,6 +166,12 @@ public:
virtual EdgePairsDelegate *clone () const = 0;
EdgePairsDelegate *remove_properties (bool remove = true)
{
ShapeCollectionDelegateBase::remove_properties (remove);
return this;
}
void enable_progress (const std::string &progress_desc);
void disable_progress ();
@ -205,6 +211,9 @@ public:
virtual bool has_valid_edge_pairs () const = 0;
virtual const db::RecursiveShapeIterator *iter () const = 0;
virtual void apply_property_translator (const db::PropertiesTranslator &pt) = 0;
virtual db::PropertiesRepository *properties_repository () = 0;
virtual const db::PropertiesRepository *properties_repository () const = 0;
virtual bool equals (const EdgePairs &other) const = 0;
virtual bool less (const EdgePairs &other) const = 0;

View File

@ -108,10 +108,26 @@ const db::RecursiveShapeIterator &
Edges::iter () const
{
static db::RecursiveShapeIterator def_iter;
const db::RecursiveShapeIterator *i = mp_delegate->iter ();
const db::RecursiveShapeIterator *i = mp_delegate ? mp_delegate->iter () : 0;
return *(i ? i : &def_iter);
}
const db::PropertiesRepository &
Edges::properties_repository () const
{
static db::PropertiesRepository empty_prop_repo;
const db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
return *(r ? r : &empty_prop_repo);
}
db::PropertiesRepository &
Edges::properties_repository ()
{
db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
tl_assert (r != 0);
return *r;
}
void
Edges::set_delegate (EdgesDelegate *delegate, bool keep_attributes)
{

View File

@ -39,63 +39,8 @@ class MutableEdges;
class EmptyEdges;
class DeepShapeStore;
/**
* @brief An edge set iterator
*
* The iterator delivers the edges of the edge set
*/
class DB_PUBLIC EdgesIterator
: public generic_shape_iterator<db::Edge>
{
public:
/**
* @brief Default constructor
*/
EdgesIterator ()
: generic_shape_iterator<db::Edge> ()
{
// .. nothing yet ..
}
/**
* @brief Constructor from a delegate
* The iterator will take ownership over the delegate
*/
EdgesIterator (EdgesIteratorDelegate *delegate)
: generic_shape_iterator<db::Edge> (delegate)
{
// .. nothing yet ..
}
/**
* @brief Copy constructor and assignment
*/
EdgesIterator (const EdgesIterator &other)
: generic_shape_iterator<db::Edge> (static_cast<const generic_shape_iterator<db::Edge> &> (other))
{
// .. nothing yet ..
}
/**
* @brief Assignment
*/
EdgesIterator &operator= (const EdgesIterator &other)
{
generic_shape_iterator<db::Edge>::operator= (other);
return *this;
}
/**
* @brief Increment
*/
EdgesIterator &operator++ ()
{
generic_shape_iterator<db::Edge>::operator++ ();
return *this;
}
};
typedef addressable_shape_delivery_gen<EdgesIterator> AddressableEdgeDelivery;
typedef generic_shape_iterator<db::Edge> EdgesIterator;
typedef addressable_shape_delivery<Edge> AddressableEdgeDelivery;
class Edges;
@ -269,7 +214,15 @@ public:
/**
* @brief Gets the underlying delegate object
*/
EdgesDelegate *delegate () const
const EdgesDelegate *delegate () const
{
return mp_delegate;
}
/**
* @brief Gets the underlying delegate object
*/
EdgesDelegate *delegate ()
{
return mp_delegate;
}
@ -1441,7 +1394,7 @@ public:
*/
AddressableEdgeDelivery addressable_edges () const
{
return AddressableEdgeDelivery (begin (), has_valid_edges ());
return AddressableEdgeDelivery (begin ());
}
/**
@ -1460,7 +1413,7 @@ public:
*/
AddressableEdgeDelivery addressable_merged_edges () const
{
return AddressableEdgeDelivery (begin_merged (), has_valid_merged_edges ());
return AddressableEdgeDelivery (begin_merged ());
}
/**
@ -1470,6 +1423,20 @@ public:
*/
const db::RecursiveShapeIterator &iter () const;
/**
* @brief Gets the property repository
*
* Use this object to decode property IDs.
*/
const db::PropertiesRepository &properties_repository () const;
/**
* @brief Gets the property repository
*
* Use this object to decode and encode property IDs.
*/
db::PropertiesRepository &properties_repository ();
/**
* @brief Equality
*/

View File

@ -239,6 +239,12 @@ public:
virtual EdgesDelegate *clone () const = 0;
EdgesDelegate *remove_properties (bool remove = true)
{
ShapeCollectionDelegateBase::remove_properties (remove);
return this;
}
void set_base_verbosity (int vb);
int base_verbosity () const
{
@ -340,6 +346,9 @@ public:
virtual bool has_valid_merged_edges () const = 0;
virtual const db::RecursiveShapeIterator *iter () const = 0;
virtual void apply_property_translator (const db::PropertiesTranslator &pt) = 0;
virtual db::PropertiesRepository *properties_repository () = 0;
virtual const db::PropertiesRepository *properties_repository () const = 0;
virtual bool equals (const Edges &other) const = 0;
virtual bool less (const Edges &other) const = 0;

View File

@ -0,0 +1,203 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2023 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 "dbEdgesLocalOperations.h"
#include "dbHierProcessor.h"
#include "dbLocalOperationUtils.h"
namespace db
{
// ---------------------------------------------------------------------------------------------
// EdgeBoolAndOrNotLocalOperation implementation
EdgeBoolAndOrNotLocalOperation::EdgeBoolAndOrNotLocalOperation (EdgeBoolOp op)
: m_op (op)
{
// .. nothing yet ..
}
OnEmptyIntruderHint
EdgeBoolAndOrNotLocalOperation::on_empty_intruder_hint () const
{
return (m_op == EdgeAnd || m_op == EdgeIntersections) ? Drop : Copy;
}
std::string
EdgeBoolAndOrNotLocalOperation::description () const
{
if (m_op == EdgeIntersections) {
return tl::to_string (tr ("Edge INTERSECTION operation"));
} else if (m_op == EdgeAnd) {
return tl::to_string (tr ("Edge AND operation"));
} else if (m_op == EdgeNot) {
return tl::to_string (tr ("Edge NOT operation"));
} else {
return std::string ();
}
}
void
EdgeBoolAndOrNotLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
tl_assert (results.size () == size_t (m_op == EdgeAndNot ? 2 : 1));
std::unordered_set<db::Edge> &result = results.front ();
std::unordered_set<db::Edge> *result2 = 0;
if (results.size () > 1) {
result2 = &results[1];
}
EdgeBooleanClusterCollector<std::unordered_set<db::Edge> > cluster_collector (&result, m_op, result2);
db::box_scanner<db::Edge, size_t> scanner;
std::set<db::Edge> others;
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j).second);
}
}
bool any_subject = false;
bool is_and = (m_op == EdgeAnd || m_op == EdgeAndNot || m_op == EdgeIntersections);
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
if (others.find (subject) != others.end ()) {
if (is_and) {
result.insert (subject);
}
} else if (i->second.empty ()) {
// shortcut (not: keep, and: drop)
if (! is_and) {
result.insert (subject);
}
} else {
scanner.insert (&subject, 0);
any_subject = true;
}
}
if (! others.empty () || any_subject) {
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
scanner.insert (o.operator-> (), 1);
}
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
}
}
// ---------------------------------------------------------------------------------------------
// EdgeToPolygonLocalOperation implementation
EdgeToPolygonLocalOperation::EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders)
: m_op (op), m_include_borders (include_borders)
{
// .. nothing yet ..
}
OnEmptyIntruderHint
EdgeToPolygonLocalOperation::on_empty_intruder_hint () const
{
return m_op == EdgePolygonOp::Inside ? Drop : (m_op == EdgePolygonOp::Outside ? Copy : CopyToSecond);
}
std::string
EdgeToPolygonLocalOperation::description () const
{
if (m_op == EdgePolygonOp::Inside) {
return tl::to_string (tr ("Edge to polygon AND/INSIDE"));
} else if (m_op == EdgePolygonOp::Outside) {
return tl::to_string (tr ("Edge to polygon NOT/OUTSIDE"));
} else {
return tl::to_string (tr ("Edge to polygon ANDNOT/INOUTSIDE"));
}
}
void
EdgeToPolygonLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
tl_assert (results.size () == size_t (m_op == EdgePolygonOp::Both ? 2 : 1));
std::unordered_set<db::Edge> &result = results.front ();
std::unordered_set<db::Edge> *result2 = 0;
if (results.size () > 1) {
result2 = &results[1];
}
db::EdgeProcessor ep;
std::set<db::PolygonRef> others;
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (shape_interactions<db::Edge, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j).second);
}
}
bool any_subject = false;
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
if (i->second.empty ()) {
// shortcut (outside: keep, otherwise: drop)
if (m_op == db::EdgePolygonOp::Outside) {
result.insert (subject);
} else if (m_op == db::EdgePolygonOp::Both) {
result2->insert (subject);
}
} else {
ep.insert (subject, 1);
any_subject = true;
}
}
if (! others.empty () || any_subject) {
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end (); ++e) {
ep.insert (*e, 0);
}
}
std::unique_ptr<db::EdgeToEdgeSetGenerator> cc_second;
if (result2) {
cc_second.reset (new db::EdgeToEdgeSetGenerator (*result2, 2 /*second tag*/));
}
db::EdgeToEdgeSetGenerator cc (result, 1 /*first tag*/, cc_second.get ());
db::EdgePolygonOp op (m_op, m_include_borders);
ep.process (cc, op);
}
}
}

View File

@ -0,0 +1,84 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2023 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_dbEdgesLocalOperation
#define HDR_dbEdgesLocalOperation
#include "dbCommon.h"
#include "dbLayout.h"
#include "dbEdgeBoolean.h"
#include "dbEdgeProcessor.h"
#include "dbLocalOperation.h"
namespace db
{
/**
* @brief Implements a boolean AND or NOT operation between edges
*/
class DB_PUBLIC EdgeBoolAndOrNotLocalOperation
: public local_operation<db::Edge, db::Edge, db::Edge>
{
public:
EdgeBoolAndOrNotLocalOperation (db::EdgeBoolOp op);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
// edge interaction distance is 1 to force overlap between edges and edge/boxes
virtual db::Coord dist () const { return 1; }
private:
db::EdgeBoolOp m_op;
};
/**
* @brief Implements a boolean AND or NOT operation between edges and polygons (polygons as intruders)
*
* "AND" is implemented by "outside == false", "NOT" by "outside == true" with "include_borders == true".
* With "include_borders == false" the operations are "INSIDE" and "OUTSIDE".
*/
class DB_PUBLIC EdgeToPolygonLocalOperation
: public local_operation<db::Edge, db::PolygonRef, db::Edge>
{
public:
EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
// edge interaction distance is 1 to force overlap between edges and edge/boxes
virtual db::Coord dist () const { return m_include_borders ? 1 : 0; }
private:
db::EdgePolygonOp::mode_t m_op;
bool m_include_borders;
};
}
#endif

View File

@ -73,6 +73,9 @@ public:
virtual bool has_valid_edge_pairs () const { return true; }
virtual const db::RecursiveShapeIterator *iter () const { return 0; }
virtual void apply_property_translator (const db::PropertiesTranslator &) { }
virtual db::PropertiesRepository *properties_repository () { return 0; }
virtual const db::PropertiesRepository *properties_repository () const { return 0; }
virtual bool equals (const EdgePairs &other) const;
virtual bool less (const EdgePairs &other) const;

View File

@ -122,6 +122,9 @@ public:
virtual bool has_valid_merged_edges () const { return true; }
virtual const db::RecursiveShapeIterator *iter () const { return 0; }
virtual void apply_property_translator (const db::PropertiesTranslator &) { }
virtual db::PropertiesRepository *properties_repository () { return 0; }
virtual const db::PropertiesRepository *properties_repository () const { return 0; }
virtual bool equals (const Edges &other) const;
virtual bool less (const Edges &other) const;

View File

@ -67,19 +67,20 @@ EmptyRegion::add (const Region &other) const
}
RegionDelegate *
EmptyRegion::xor_with (const Region &other) const
EmptyRegion::xor_with (const Region &other, db::PropertyConstraint prop_constraint) const
{
return or_with (other);
return or_with (other, prop_constraint);
}
RegionDelegate *
EmptyRegion::or_with (const Region &other) const
EmptyRegion::or_with (const Region &other, db::PropertyConstraint /*prop_constraint*/) const
{
if (other.empty ()) {
return new EmptyRegion ();
} else if (! other.strict_handling ()) {
return other.delegate ()->clone ();
} else {
// TODO: implement prop_constraint
return other.delegate ()->merged ();
}
}
@ -97,19 +98,19 @@ EmptyRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &) co
}
EdgePairsDelegate *
EmptyRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &)
EmptyRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &, db::PropertyConstraint)
{
return new EmptyEdgePairs ();
}
RegionDelegate *
EmptyRegion::cop_to_region (db::CompoundRegionOperationNode &)
EmptyRegion::cop_to_region (db::CompoundRegionOperationNode &, db::PropertyConstraint)
{
return new EmptyRegion ();
}
EdgesDelegate *
EmptyRegion::cop_to_edges (db::CompoundRegionOperationNode &)
EmptyRegion::cop_to_edges (db::CompoundRegionOperationNode &, db::PropertyConstraint)
{
return new EmptyEdges ();
}

View File

@ -62,9 +62,9 @@ public:
virtual Box bbox () const { return Box (); }
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node);
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node);
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node);
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node, PropertyConstraint);
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node, PropertyConstraint);
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node, PropertyConstraint);
virtual EdgePairsDelegate *width_check (db::Coord, const RegionCheckOptions &) const;
virtual EdgePairsDelegate *space_check (db::Coord, const RegionCheckOptions &) const;
@ -98,11 +98,11 @@ public:
virtual RegionDelegate *sized (coord_type, unsigned int) const { return new EmptyRegion (); }
virtual RegionDelegate *sized (coord_type, coord_type, unsigned int) const { return new EmptyRegion (); }
virtual RegionDelegate *and_with (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *not_with (const Region &) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *xor_with (const Region &other) const;
virtual RegionDelegate *or_with (const Region &other) const;
virtual RegionDelegate *and_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); }
virtual RegionDelegate *not_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &, db::PropertyConstraint) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *xor_with (const Region &other, db::PropertyConstraint prop_constraint) const;
virtual RegionDelegate *or_with (const Region &other, db::PropertyConstraint prop_constraint) const;
virtual RegionDelegate *add_in_place (const Region &other);
virtual RegionDelegate *add (const Region &other) const;
@ -138,14 +138,20 @@ public:
virtual bool has_valid_polygons () const { return true; }
virtual bool has_valid_merged_polygons () const { return true; }
virtual const db::Polygon *nth (size_t) const { tl_assert (false); }
virtual db::properties_id_type nth_prop_id (size_t) const { tl_assert (false); }
virtual const db::RecursiveShapeIterator *iter () const { return 0; }
virtual void apply_property_translator (const db::PropertiesTranslator &) { }
virtual db::PropertiesRepository *properties_repository () { return 0; }
virtual const db::PropertiesRepository *properties_repository () const { return 0; }
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
virtual void insert_into (Layout *, db::cell_index_type, unsigned int) const { }
virtual RegionDelegate *nets (LayoutToNetlist *, NetPropertyMode, const tl::Variant &, const std::vector<const db::Net *> *) const { return new EmptyRegion (); }
private:
EmptyRegion &operator= (const EmptyRegion &other);
};

View File

@ -71,6 +71,9 @@ public:
virtual bool has_valid_texts () const { return true; }
virtual const db::RecursiveShapeIterator *iter () const { return 0; }
virtual void apply_property_translator (const db::PropertiesTranslator &) { }
virtual db::PropertiesRepository *properties_repository () { return 0; }
virtual const db::PropertiesRepository *properties_repository () const { return 0; }
virtual bool equals (const Texts &other) const;
virtual bool less (const Texts &other) const;

View File

@ -32,7 +32,7 @@ namespace db
// FlatEdgePairs implementation
FlatEdgePairs::FlatEdgePairs ()
: MutableEdgePairs (), mp_edge_pairs (new db::Shapes (false))
: MutableEdgePairs (), mp_edge_pairs (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
// .. nothing yet ..
}
@ -43,13 +43,13 @@ FlatEdgePairs::~FlatEdgePairs ()
}
FlatEdgePairs::FlatEdgePairs (const FlatEdgePairs &other)
: MutableEdgePairs (other), mp_edge_pairs (other.mp_edge_pairs)
: MutableEdgePairs (other), mp_edge_pairs (other.mp_edge_pairs), mp_properties_repository (other.mp_properties_repository)
{
// .. nothing yet ..
}
FlatEdgePairs::FlatEdgePairs (const db::Shapes &edge_pairs)
: MutableEdgePairs (), mp_edge_pairs (new db::Shapes (edge_pairs))
: MutableEdgePairs (), mp_edge_pairs (new db::Shapes (edge_pairs)), mp_properties_repository (new db::PropertiesRepository ())
{
// .. nothing yet ..
}
@ -97,6 +97,8 @@ Box FlatEdgePairs::compute_bbox () const
EdgePairsDelegate *
FlatEdgePairs::filter_in_place (const EdgePairFilterBase &filter)
{
// TODO: implement property support
db::Shapes &ep = *mp_edge_pairs;
edge_pair_iterator_type pw = ep.get_layer<db::EdgePair, db::unstable_layer_tag> ().begin ();
@ -121,22 +123,22 @@ EdgePairsDelegate *FlatEdgePairs::add (const EdgePairs &other) const
std::unique_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs (*this));
new_edge_pairs->invalidate_cache ();
FlatEdgePairs *other_flat = dynamic_cast<FlatEdgePairs *> (other.delegate ());
db::PropertyMapper pm (new_edge_pairs->properties_repository (), &other.properties_repository ());
const FlatEdgePairs *other_flat = dynamic_cast<const FlatEdgePairs *> (other.delegate ());
if (other_flat) {
new_edge_pairs->raw_edge_pairs ().insert (other_flat->raw_edge_pairs ().get_layer<db::EdgePair, db::unstable_layer_tag> ().begin (), other_flat->raw_edge_pairs ().get_layer<db::EdgePair, db::unstable_layer_tag> ().end ());
new_edge_pairs->raw_edge_pairs ().insert (other_flat->raw_edge_pairs (), pm);
} else {
size_t n = new_edge_pairs->raw_edge_pairs ().size ();
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
++n;
}
new_edge_pairs->raw_edge_pairs ().reserve (db::EdgePair::tag (), n);
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
new_edge_pairs->raw_edge_pairs ().insert (*p);
db::properties_id_type prop_id = pm (p.prop_id ());
if (prop_id != 0) {
new_edge_pairs->raw_edge_pairs ().insert (db::EdgePairWithProperties (*p, prop_id));
} else {
new_edge_pairs->raw_edge_pairs ().insert (*p);
}
}
}
@ -150,22 +152,22 @@ EdgePairsDelegate *FlatEdgePairs::add_in_place (const EdgePairs &other)
db::Shapes &ep = *mp_edge_pairs;
FlatEdgePairs *other_flat = dynamic_cast<FlatEdgePairs *> (other.delegate ());
db::PropertyMapper pm (properties_repository (), &other.properties_repository ());
const FlatEdgePairs *other_flat = dynamic_cast<const FlatEdgePairs *> (other.delegate ());
if (other_flat) {
ep.insert (other_flat->raw_edge_pairs ().get_layer<db::EdgePair, db::unstable_layer_tag> ().begin (), other_flat->raw_edge_pairs ().get_layer<db::EdgePair, db::unstable_layer_tag> ().end ());
ep.insert (other_flat->raw_edge_pairs (), pm);
} else {
size_t n = ep.size ();
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
++n;
}
ep.reserve (db::EdgePair::tag (), n);
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
ep.insert (*p);
db::properties_id_type prop_id = pm (p.prop_id ());
if (prop_id != 0) {
ep.insert (db::EdgePairWithProperties (*p, prop_id));
} else {
ep.insert (*p);
}
}
}
@ -188,19 +190,50 @@ const db::RecursiveShapeIterator *FlatEdgePairs::iter () const
return 0;
}
void FlatEdgePairs::apply_property_translator (const db::PropertiesTranslator &pt)
{
if ((mp_edge_pairs->type_mask () & db::ShapeIterator::Properties) != 0) {
db::Shapes new_edge_pairs (mp_edge_pairs->is_editable ());
new_edge_pairs.assign (*mp_edge_pairs, pt);
mp_edge_pairs->swap (new_edge_pairs);
invalidate_cache ();
}
}
db::PropertiesRepository *FlatEdgePairs::properties_repository ()
{
return mp_properties_repository.get_non_const ();
}
const db::PropertiesRepository *FlatEdgePairs::properties_repository () const
{
return mp_properties_repository.get_const ();
}
void
FlatEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
{
db::Shapes &out = layout->cell (into_cell).shapes (into_layer);
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
out.insert (p->normalized ().to_simple_polygon (enl));
db::properties_id_type prop_id = pm (p.prop_id ());
if (prop_id != 0) {
out.insert (db::SimplePolygonWithProperties (p->normalized ().to_simple_polygon (enl), prop_id));
} else {
out.insert (p->normalized ().to_simple_polygon (enl));
}
}
}
void
FlatEdgePairs::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
layout->cell (into_cell).shapes (into_layer).insert (*mp_edge_pairs);
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
layout->cell (into_cell).shapes (into_layer).insert (*mp_edge_pairs, pm);
}
void

View File

@ -78,6 +78,9 @@ public:
virtual bool has_valid_edge_pairs () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
@ -119,6 +122,7 @@ private:
FlatEdgePairs &operator= (const FlatEdgePairs &other);
mutable tl::copy_on_write_ptr<db::Shapes> mp_edge_pairs;
mutable tl::copy_on_write_ptr<db::PropertiesRepository> mp_properties_repository;
template <class Trans>
void transform_generic (const Trans &trans)

View File

@ -33,7 +33,7 @@ namespace db
// FlatEdges implementation
FlatEdges::FlatEdges ()
: MutableEdges (), mp_edges (new db::Shapes (false)), mp_merged_edges (new db::Shapes (false))
: MutableEdges (), mp_edges (new db::Shapes (false)), mp_merged_edges (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
init ();
}
@ -44,7 +44,7 @@ FlatEdges::~FlatEdges ()
}
FlatEdges::FlatEdges (const FlatEdges &other)
: MutableEdges (other), mp_edges (other.mp_edges), mp_merged_edges (other.mp_merged_edges)
: MutableEdges (other), mp_edges (other.mp_edges), mp_merged_edges (other.mp_merged_edges), mp_properties_repository (other.mp_properties_repository)
{
init ();
@ -53,7 +53,7 @@ FlatEdges::FlatEdges (const FlatEdges &other)
}
FlatEdges::FlatEdges (const db::Shapes &edges, bool is_merged)
: MutableEdges (), mp_edges (new db::Shapes (edges)), mp_merged_edges (new db::Shapes (false))
: MutableEdges (), mp_edges (new db::Shapes (edges)), mp_merged_edges (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
init ();
@ -61,7 +61,7 @@ FlatEdges::FlatEdges (const db::Shapes &edges, bool is_merged)
}
FlatEdges::FlatEdges (bool is_merged)
: MutableEdges (), mp_edges (new db::Shapes (false)), mp_merged_edges (new db::Shapes (false))
: MutableEdges (), mp_edges (new db::Shapes (false)), mp_merged_edges (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
init ();
@ -88,7 +88,8 @@ void FlatEdges::init ()
void FlatEdges::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
layout->cell (into_cell).shapes (into_layer).insert (*mp_edges);
db::PropertyMapper pm (&layout->properties_repository (), mp_properties_repository.get_const ());
layout->cell (into_cell).shapes (into_layer).insert (*mp_edges, pm);
}
void FlatEdges::merged_semantics_changed ()
@ -109,19 +110,62 @@ FlatEdges::ensure_merged_edges_valid () const
mp_merged_edges->clear ();
db::Shapes tmp (false);
EdgeBooleanClusterCollectorToShapes cluster_collector (&tmp, EdgeOr);
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve (mp_edges->size ());
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
if (! e->is_degenerate ()) {
scanner.insert (&*e, 0);
// count edges and reserve memory
size_t n = 0;
db::properties_id_type prop_id = 0;
bool need_split_props = false;
for (EdgesIterator s (begin ()); ! s.at_end (); ++s, ++n) {
if (n == 0) {
prop_id = s.prop_id ();
} else if (! need_split_props && prop_id != s.prop_id ()) {
need_split_props = true;
}
}
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
db::Shapes tmp (false);
if (! need_split_props) {
EdgeBooleanClusterCollectorToShapes cluster_collector (&tmp, EdgeOr);
scanner.reserve (mp_edges->size ());
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
if (! e->is_degenerate ()) {
scanner.insert (&*e, 0);
}
}
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
} else {
std::map<db::properties_id_type, std::vector<const db::Edge *> > edges_by_props;
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
if (! e->is_degenerate ()) {
edges_by_props [e.prop_id ()].push_back (e.operator-> ());
}
}
for (auto s2p = edges_by_props.begin (); s2p != edges_by_props.end (); ++s2p) {
EdgeBooleanClusterCollectorToShapes cluster_collector (&tmp, EdgeOr, s2p->first);
scanner.clear ();
scanner.reserve (s2p->second.size ());
for (auto s = s2p->second.begin (); s != s2p->second.end (); ++s) {
scanner.insert (*s, 0);
}
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
}
}
mp_merged_edges->swap (tmp);
m_merged_edges_valid = true;
@ -192,23 +236,36 @@ FlatEdges::processed_in_place (const EdgeProcessorBase &filter)
db::Shapes &e = *mp_edges;
edge_iterator_type pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().begin ();
edge_iterator_wp_type pw_wp = e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().begin ();
for (EdgesIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
edge_res.clear ();
filter.process (*p, edge_res);
for (std::vector<db::Edge>::const_iterator pr = edge_res.begin (); pr != edge_res.end (); ++pr) {
if (pw == e.get_layer<db::Edge, db::unstable_layer_tag> ().end ()) {
e.get_layer<db::Edge, db::unstable_layer_tag> ().insert (*pr);
pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().end ();
if (p.prop_id () != 0) {
if (pw_wp == e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ()) {
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().insert (db::EdgeWithProperties (*pr, p.prop_id ()));
pw_wp = e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ();
} else {
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().replace (pw_wp++, db::EdgeWithProperties (*pr, p.prop_id ()));
}
} else {
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (pw++, *pr);
if (pw == e.get_layer<db::Edge, db::unstable_layer_tag> ().end ()) {
e.get_layer<db::Edge, db::unstable_layer_tag> ().insert (*pr);
pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().end ();
} else {
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (pw++, *pr);
}
}
}
}
e.get_layer<db::Edge, db::unstable_layer_tag> ().erase (pw, e.get_layer<db::Edge, db::unstable_layer_tag> ().end ());
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().erase (pw_wp, e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ());
mp_merged_edges->clear ();
m_is_merged = filter.result_is_merged () && merged_semantics ();
@ -221,18 +278,31 @@ FlatEdges::filter_in_place (const EdgeFilterBase &filter)
db::Shapes &e = *mp_edges;
edge_iterator_type pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().begin ();
edge_iterator_wp_type pw_wp = e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().begin ();
for (EdgesIterator p (begin_merged ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
if (pw == e.get_layer<db::Edge, db::unstable_layer_tag> ().end ()) {
e.get_layer<db::Edge, db::unstable_layer_tag> ().insert (*p);
pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().end ();
if (p.prop_id () != 0) {
if (pw_wp == e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ()) {
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().insert (db::EdgeWithProperties (*p, p.prop_id ()));
pw_wp = e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ();
} else {
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().replace (pw_wp++, db::EdgeWithProperties (*p, p.prop_id ()));
}
} else {
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (pw++, *p);
if (pw == e.get_layer<db::Edge, db::unstable_layer_tag> ().end ()) {
e.get_layer<db::Edge, db::unstable_layer_tag> ().insert (*p);
pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().end ();
} else {
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (pw++, *p);
}
}
}
}
e.get_layer<db::Edge, db::unstable_layer_tag> ().erase (pw, e.get_layer<db::Edge, db::unstable_layer_tag> ().end ());
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().erase (pw_wp, e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ());
mp_merged_edges->clear ();
m_is_merged = merged_semantics ();
@ -245,7 +315,7 @@ EdgesDelegate *FlatEdges::add (const Edges &other) const
new_region->invalidate_cache ();
new_region->set_is_merged (false);
FlatEdges *other_flat = dynamic_cast<FlatEdges *> (other.delegate ());
const FlatEdges *other_flat = dynamic_cast<const FlatEdges *> (other.delegate ());
if (other_flat) {
new_region->raw_edges ().insert (other_flat->raw_edges ().get_layer<db::Edge, db::unstable_layer_tag> ().begin (), other_flat->raw_edges ().get_layer<db::Edge, db::unstable_layer_tag> ().end ());
@ -275,7 +345,7 @@ EdgesDelegate *FlatEdges::add_in_place (const Edges &other)
db::Shapes &e = *mp_edges;
FlatEdges *other_flat = dynamic_cast<FlatEdges *> (other.delegate ());
const FlatEdges *other_flat = dynamic_cast<const FlatEdges *> (other.delegate ());
if (other_flat) {
e.insert (other_flat->raw_edges ().get_layer<db::Edge, db::unstable_layer_tag> ().begin (), other_flat->raw_edges ().get_layer<db::Edge, db::unstable_layer_tag> ().end ());
@ -318,12 +388,40 @@ const db::RecursiveShapeIterator *FlatEdges::iter () const
return 0;
}
void FlatEdges::apply_property_translator (const db::PropertiesTranslator &pt)
{
if ((mp_edges->type_mask () & db::ShapeIterator::Properties) != 0) {
db::Shapes new_edges (mp_edges->is_editable ());
new_edges.assign (*mp_edges, pt);
mp_edges->swap (new_edges);
invalidate_cache ();
}
}
db::PropertiesRepository *FlatEdges::properties_repository ()
{
return mp_properties_repository.get_non_const ();
}
const db::PropertiesRepository *FlatEdges::properties_repository () const
{
return mp_properties_repository.get_const ();
}
void
FlatEdges::do_insert (const db::Edge &edge)
FlatEdges::do_insert (const db::Edge &edge, db::properties_id_type prop_id)
{
m_is_merged = empty ();
mp_edges->insert (edge);
if (prop_id == 0) {
mp_edges->insert (edge);
} else {
mp_edges->insert (db::EdgeWithProperties (edge, prop_id));
}
invalidate_cache ();
}

View File

@ -50,6 +50,8 @@ public:
typedef db::layer<db::Edge, db::unstable_layer_tag> edge_layer_type;
typedef edge_layer_type::iterator edge_iterator_type;
typedef db::layer<db::EdgeWithProperties, db::unstable_layer_tag> edge_layer_wp_type;
typedef edge_layer_wp_type::iterator edge_iterator_wp_type;
FlatEdges ();
FlatEdges (const db::Shapes &edges, bool is_merged);
@ -91,8 +93,11 @@ public:
virtual bool has_valid_merged_edges () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
void do_insert (const db::Edge &edge);
void do_insert (const db::Edge &edge, properties_id_type prop_id);
void do_transform (const db::Trans &t)
{
@ -132,6 +137,7 @@ private:
mutable tl::copy_on_write_ptr<db::Shapes> mp_edges;
mutable tl::copy_on_write_ptr<db::Shapes> mp_merged_edges;
mutable bool m_merged_edges_valid;
mutable tl::copy_on_write_ptr<db::PropertiesRepository> mp_properties_repository;
void init ();
void ensure_merged_edges_valid () const;
@ -144,6 +150,9 @@ private:
for (edge_iterator_type p = e.template get_layer<db::Edge, db::unstable_layer_tag> ().begin (); p != e.get_layer<db::Edge, db::unstable_layer_tag> ().end (); ++p) {
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (p, p->transformed (trans));
}
for (edge_iterator_wp_type p = e.template get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().begin (); p != e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end (); ++p) {
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().replace (p, p->transformed (trans));
}
invalidate_cache ();
}
}

View File

@ -25,6 +25,7 @@
#include "dbEmptyRegion.h"
#include "dbRegion.h"
#include "dbShapeProcessor.h"
#include "tlSList.h"
namespace db
{
@ -33,18 +34,13 @@ namespace db
// FlatRegion implementation
FlatRegion::FlatRegion ()
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false))
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
init ();
}
FlatRegion::~FlatRegion ()
{
// .. nothing yet ..
}
FlatRegion::FlatRegion (const FlatRegion &other)
: MutableRegion (other), mp_polygons (other.mp_polygons), mp_merged_polygons (other.mp_merged_polygons)
: MutableRegion (other), mp_polygons (other.mp_polygons), mp_merged_polygons (other.mp_merged_polygons), mp_properties_repository (other.mp_properties_repository)
{
init ();
@ -53,7 +49,7 @@ FlatRegion::FlatRegion (const FlatRegion &other)
}
FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged)
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false))
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
init ();
@ -61,13 +57,18 @@ FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged)
}
FlatRegion::FlatRegion (bool is_merged)
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false))
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
init ();
m_is_merged = is_merged;
}
FlatRegion::~FlatRegion ()
{
// .. nothing yet ..
}
void FlatRegion::set_is_merged (bool m)
{
m_is_merged = m;
@ -108,33 +109,8 @@ void
FlatRegion::ensure_merged_polygons_valid () const
{
if (! m_merged_polygons_valid) {
mp_merged_polygons->clear ();
db::EdgeProcessor ep (report_progress (), progress_desc ());
ep.set_base_verbosity (base_verbosity ());
// count edges and reserve memory
size_t n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
n += p->vertices ();
}
ep.reserve (n);
// insert the polygons into the processor
n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p, ++n) {
ep.insert (*p, n);
}
// and run the merge step
db::MergeOp op (0);
db::ShapeGenerator pc (*mp_merged_polygons);
db::PolygonGenerator pg (pc, false /*don't resolve holes*/, min_coherence ());
ep.process (pg, op);
merge_polygons_to (*mp_merged_polygons, min_coherence (), 0);
m_merged_polygons_valid = true;
}
}
@ -196,20 +172,33 @@ Box FlatRegion::compute_bbox () const
RegionDelegate *FlatRegion::filter_in_place (const PolygonFilterBase &filter)
{
db::layer<db::Polygon, db::unstable_layer_tag> &poly_layer = mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ();
db::layer<db::PolygonWithProperties, db::unstable_layer_tag> &poly_layer_wp = mp_polygons->get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ();
polygon_iterator_type pw = poly_layer.begin ();
polygon_iterator_wp_type pw_wp = poly_layer_wp.begin ();
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
if (pw == poly_layer.end ()) {
poly_layer.insert (*p);
poly_layer.end ();
if (p.prop_id () != 0) {
if (pw_wp == poly_layer_wp.end ()) {
poly_layer_wp.insert (db::PolygonWithProperties (*p, p.prop_id ()));
pw_wp = poly_layer_wp.end ();
} else {
poly_layer_wp.replace (pw_wp++, db::PolygonWithProperties (*p, p.prop_id ()));
}
} else {
poly_layer.replace (pw++, *p);
if (pw == poly_layer.end ()) {
poly_layer.insert (*p);
pw = poly_layer.end ();
} else {
poly_layer.replace (pw++, *p);
}
}
}
}
poly_layer.erase (pw, poly_layer.end ());
poly_layer_wp.erase (pw_wp, poly_layer_wp.end ());
mp_merged_polygons->clear ();
m_is_merged = filter.requires_raw_input () ? false : merged_semantics ();
@ -221,15 +210,24 @@ RegionDelegate *FlatRegion::process_in_place (const PolygonProcessorBase &filter
{
db::layer<db::Polygon, db::unstable_layer_tag> &poly_layer = mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ();
db::layer<db::Polygon, db::unstable_layer_tag> out;
db::layer<db::PolygonWithProperties, db::unstable_layer_tag> &poly_layer_wp = mp_polygons->get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ();
db::layer<db::PolygonWithProperties, db::unstable_layer_tag> out_wp;
std::vector<db::Polygon> poly_res;
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
poly_res.clear ();
filter.process (*p, poly_res);
out.insert (poly_res.begin (), poly_res.end ());
if (p.prop_id () != 0) {
for (auto r = poly_res.begin (); r != poly_res.end (); ++r) {
out_wp.insert (db::PolygonWithProperties (*r, p.prop_id ()));
}
} else {
out.insert (poly_res.begin (), poly_res.end ());
}
}
poly_layer.swap (out);
poly_layer_wp.swap (out_wp);
mp_merged_polygons->clear ();
m_is_merged = filter.result_is_merged () && merged_semantics ();
@ -279,28 +277,7 @@ RegionDelegate *FlatRegion::merged_in_place (bool min_coherence, unsigned int mi
} else {
invalidate_cache ();
db::EdgeProcessor ep (report_progress (), progress_desc ());
ep.set_base_verbosity (base_verbosity ());
// count edges and reserve memory
size_t n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
n += p->vertices ();
}
ep.reserve (n);
// insert the polygons into the processor
n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p, ++n) {
ep.insert (*p, n);
}
// and run the merge step
db::MergeOp op (min_wc);
db::ShapeGenerator pc (*mp_polygons, true /*clear*/);
db::PolygonGenerator pg (pc, false /*don't resolve holes*/, min_coherence);
ep.process (pg, op);
merge_polygons_to (*mp_polygons, min_coherence, min_wc);
m_is_merged = true;
@ -330,7 +307,7 @@ RegionDelegate *FlatRegion::add (const Region &other) const
new_region->invalidate_cache ();
new_region->set_is_merged (false);
FlatRegion *other_flat = dynamic_cast<FlatRegion *> (other.delegate ());
const FlatRegion *other_flat = dynamic_cast<const FlatRegion *> (other.delegate ());
if (other_flat) {
new_region->raw_polygons ().insert (other_flat->raw_polygons ().get_layer<db::Polygon, db::unstable_layer_tag> ().begin (), other_flat->raw_polygons ().get_layer<db::Polygon, db::unstable_layer_tag> ().end ());
@ -360,7 +337,7 @@ RegionDelegate *FlatRegion::add_in_place (const Region &other)
db::Shapes &polygons = *mp_polygons;
FlatRegion *other_flat = dynamic_cast<FlatRegion *> (other.delegate ());
const FlatRegion *other_flat = dynamic_cast<const FlatRegion *> (other.delegate ());
if (other_flat) {
polygons.insert (other_flat->raw_polygons ().get_layer<db::Polygon, db::unstable_layer_tag> ().begin (), other_flat->raw_polygons ().get_layer<db::Polygon, db::unstable_layer_tag> ().end ());
@ -385,7 +362,46 @@ RegionDelegate *FlatRegion::add_in_place (const Region &other)
const db::Polygon *FlatRegion::nth (size_t n) const
{
return n < mp_polygons->size () ? &mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ().begin () [n] : 0;
// NOTE: this assumes that we iterate over non-property polygons first and then over polygons with properties
if (n >= mp_polygons->size ()) {
return 0;
}
const db::layer<db::Polygon, db::unstable_layer_tag> &l = mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ();
if (n < l.size ()) {
return &l.begin () [n];
}
n -= l.size ();
const db::layer<db::PolygonWithProperties, db::unstable_layer_tag> &lp = mp_polygons->get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ();
if (n < lp.size ()) {
return &lp.begin () [n];
}
return 0;
}
db::properties_id_type FlatRegion::nth_prop_id (size_t n) const
{
// NOTE: this assumes that we iterate over non-property polygons first and then over polygons with properties
if (n >= mp_polygons->size ()) {
return 0;
}
const db::layer<db::Polygon, db::unstable_layer_tag> &l = mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ();
if (n < l.size ()) {
return 0;
}
n -= l.size ();
const db::layer<db::PolygonWithProperties, db::unstable_layer_tag> &lp = mp_polygons->get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ();
if (n < lp.size ()) {
return lp.begin () [n].properties_id ();
}
return 0;
}
bool FlatRegion::has_valid_polygons () const
@ -403,19 +419,47 @@ const db::RecursiveShapeIterator *FlatRegion::iter () const
return 0;
}
void FlatRegion::apply_property_translator (const db::PropertiesTranslator &pt)
{
if ((mp_polygons->type_mask () & db::ShapeIterator::Properties) != 0) {
db::Shapes new_polygons (mp_polygons->is_editable ());
new_polygons.assign (*mp_polygons, pt);
mp_polygons->swap (new_polygons);
invalidate_cache ();
}
}
db::PropertiesRepository *FlatRegion::properties_repository ()
{
return mp_properties_repository.get_non_const ();
}
const db::PropertiesRepository *FlatRegion::properties_repository () const
{
return mp_properties_repository.get_const ();
}
void FlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
layout->cell (into_cell).shapes (into_layer).insert (*mp_polygons);
db::PropertyMapper pm (&layout->properties_repository (), mp_properties_repository.get_const ());
layout->cell (into_cell).shapes (into_layer).insert (*mp_polygons, pm);
}
void
FlatRegion::do_insert (const db::Polygon &polygon)
FlatRegion::do_insert (const db::Polygon &polygon, properties_id_type prop_id)
{
if (polygon.holes () > 0 || polygon.vertices () > 0) {
bool is_box = (empty () && polygon.is_box ());
mp_polygons->insert (polygon);
if (prop_id != 0) {
mp_polygons->insert (db::PolygonWithProperties (polygon, prop_id));
} else {
mp_polygons->insert (polygon);
}
set_is_merged (is_box);
invalidate_cache ();

View File

@ -48,6 +48,8 @@ public:
typedef db::Polygon value_type;
typedef db::layer<db::Polygon, db::unstable_layer_tag> polygon_layer_type;
typedef polygon_layer_type::iterator polygon_iterator_type;
typedef db::layer<db::PolygonWithProperties, db::unstable_layer_tag> polygon_layer_wp_type;
typedef polygon_layer_wp_type::iterator polygon_iterator_wp_type;
FlatRegion ();
FlatRegion (const db::Shapes &polygons, bool is_merged);
@ -92,12 +94,16 @@ public:
virtual RegionDelegate *add (const Region &other) const;
virtual const db::Polygon *nth (size_t n) const;
virtual db::properties_id_type nth_prop_id (size_t) const;
virtual bool has_valid_polygons () const;
virtual bool has_valid_merged_polygons () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
void do_insert (const db::Polygon &polygon);
void do_insert (const db::Polygon &polygon, db::properties_id_type prop_id);
void do_transform (const db::Trans &t)
{
@ -141,6 +147,7 @@ private:
mutable tl::copy_on_write_ptr<db::Shapes> mp_polygons;
mutable tl::copy_on_write_ptr<db::Shapes> mp_merged_polygons;
mutable bool m_merged_polygons_valid;
mutable tl::copy_on_write_ptr<db::PropertiesRepository> mp_properties_repository;
void init ();
void ensure_merged_polygons_valid () const;
@ -153,6 +160,9 @@ private:
for (polygon_iterator_type p = polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().begin (); p != polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().end (); ++p) {
polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().replace (p, p->transformed (trans));
}
for (polygon_iterator_wp_type p = polygons.get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ().begin (); p != polygons.get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ().end (); ++p) {
polygons.get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ().replace (p, p->transformed (trans));
}
invalidate_cache ();
}
}

View File

@ -32,7 +32,7 @@ namespace db
// FlatTexts implementation
FlatTexts::FlatTexts ()
: MutableTexts (), mp_texts (new db::Shapes (false))
: MutableTexts (), mp_texts (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
{
// .. nothing yet ..
}
@ -43,13 +43,13 @@ FlatTexts::~FlatTexts ()
}
FlatTexts::FlatTexts (const FlatTexts &other)
: MutableTexts (other), mp_texts (other.mp_texts)
: MutableTexts (other), mp_texts (other.mp_texts), mp_properties_repository (other.mp_properties_repository)
{
// .. nothing yet ..
}
FlatTexts::FlatTexts (const db::Shapes &texts)
: MutableTexts (), mp_texts (new db::Shapes (texts))
: MutableTexts (), mp_texts (new db::Shapes (texts)), mp_properties_repository (new db::PropertiesRepository ())
{
// .. nothing yet ..
}
@ -121,7 +121,7 @@ TextsDelegate *FlatTexts::add (const Texts &other) const
std::unique_ptr<FlatTexts> new_texts (new FlatTexts (*this));
new_texts->invalidate_cache ();
FlatTexts *other_flat = dynamic_cast<FlatTexts *> (other.delegate ());
const FlatTexts *other_flat = dynamic_cast<const FlatTexts *> (other.delegate ());
if (other_flat) {
new_texts->raw_texts ().insert (other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().begin (), other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().end ());
@ -150,7 +150,7 @@ TextsDelegate *FlatTexts::add_in_place (const Texts &other)
db::Shapes &texts = *mp_texts;
FlatTexts *other_flat = dynamic_cast<FlatTexts *> (other.delegate ());
const FlatTexts *other_flat = dynamic_cast<const FlatTexts *> (other.delegate ());
if (other_flat) {
texts.insert (other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().begin (), other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().end ());
@ -188,6 +188,29 @@ const db::RecursiveShapeIterator *FlatTexts::iter () const
return 0;
}
void FlatTexts::apply_property_translator (const db::PropertiesTranslator &pt)
{
if ((mp_texts->type_mask () & db::ShapeIterator::Properties) != 0) {
db::Shapes new_texts (mp_texts->is_editable ());
new_texts.assign (*mp_texts, pt);
mp_texts->swap (new_texts);
invalidate_cache ();
}
}
db::PropertiesRepository *FlatTexts::properties_repository ()
{
return mp_properties_repository.get_non_const ();
}
const db::PropertiesRepository *FlatTexts::properties_repository () const
{
return mp_properties_repository.get_const ();
}
void
FlatTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
{

View File

@ -79,6 +79,9 @@ public:
virtual bool has_valid_texts () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
@ -120,6 +123,7 @@ private:
FlatTexts &operator= (const FlatTexts &other);
mutable tl::copy_on_write_ptr<db::Shapes> mp_texts;
mutable tl::copy_on_write_ptr<db::PropertiesRepository> mp_properties_repository;
template <class Trans>
void transform_generic (const Trans &trans)

View File

@ -46,6 +46,7 @@ public:
virtual bool at_end () const = 0;
virtual void increment () = 0;
virtual const T *get () const = 0;
virtual db::properties_id_type prop_id () const = 0;
virtual generic_shape_iterator_delegate_base<T> *clone () const = 0;
virtual bool equals (const generic_shape_iterator_delegate_base<T> *other) const = 0;
};
@ -86,6 +87,11 @@ public:
return m_iter.operator-> ();
}
virtual db::properties_id_type prop_id () const
{
return 0;
}
generic_shape_iterator_delegate_base<value_type> *clone () const
{
return new generic_shape_iterator_delegate2<Iter> (*this);
@ -141,6 +147,11 @@ public:
return m_iter.operator-> ();
}
virtual db::properties_id_type prop_id () const
{
return 0;
}
generic_shape_iterator_delegate_base<value_type> *clone () const
{
return new generic_shape_iterator_delegate1<Iter> (*this);
@ -170,7 +181,7 @@ public:
const_cast<db::Shapes *> (mp_shapes)->update ();
}
m_iter = mp_shapes->begin (shape_flags<T> ());
m_is_addressable = shape_flags<T> () == shape_flags_pure<T> () || mp_shapes->begin (shape_flags<T> () - shape_flags_pure<T> ()).at_end ();
m_is_addressable = ! shape_flags_with_props<T> () && (shape_flags<T> () == shape_flags_pure<T> () || mp_shapes->begin (shape_flags<T> () - shape_flags_pure<T> ()).at_end ());
set ();
}
@ -217,6 +228,11 @@ public:
}
}
virtual db::properties_id_type prop_id () const
{
return m_iter->prop_id ();
}
generic_shape_iterator_delegate_base<T> *clone () const
{
return new generic_shapes_iterator_delegate<T> (*this);
@ -289,9 +305,23 @@ public:
: mp_delegate (other.mp_delegate ? other.mp_delegate->clone () : 0)
{ }
generic_shape_iterator (generic_shape_iterator &&other)
: mp_delegate (0)
{
std::swap (mp_delegate, other.mp_delegate);
}
~generic_shape_iterator ()
{
delete mp_delegate;
mp_delegate = 0;
}
generic_shape_iterator &set_delegate (generic_shape_iterator_delegate_base<T> *delegate)
{
delete mp_delegate;
mp_delegate = delegate;
return *this;
}
generic_shape_iterator &operator= (const generic_shape_iterator &other)
@ -319,6 +349,11 @@ public:
return ! mp_delegate || mp_delegate->is_addressable ();
}
db::properties_id_type prop_id () const
{
return mp_delegate ? mp_delegate->prop_id () : 0;
}
reference operator* () const
{
return *mp_delegate->get ();
@ -372,12 +407,108 @@ public:
};
/**
* @brief A helper class allowing delivery of addressable edges
* @brief Wraps a generic shape iterator to provide a property-enabled one
*/
template <class T>
class DB_PUBLIC generic_shape_iterator_with_properties_delegate
: public generic_shape_iterator_delegate_base<db::object_with_properties<T> >
{
public:
generic_shape_iterator_with_properties_delegate (generic_shape_iterator<T> &&basic)
: m_basic (basic)
{
set ();
}
generic_shape_iterator_with_properties_delegate (generic_shape_iterator_delegate_base<T> *delegate)
: m_basic (delegate)
{
set ();
}
generic_shape_iterator_with_properties_delegate (const generic_shape_iterator<T> &basic)
: m_basic (basic)
{
set ();
}
generic_shape_iterator_with_properties_delegate *clone () const
{
return new generic_shape_iterator_with_properties_delegate (m_basic);
}
virtual void do_reset (const db::Box &region, bool overlapping)
{
m_basic.reset (region, overlapping);
}
virtual db::Box bbox () const
{
return m_basic.bbox ();
}
virtual bool is_addressable () const
{
return false;
}
virtual bool at_end () const
{
return m_basic.at_end ();
}
virtual void increment ()
{
++m_basic;
set ();
}
virtual const db::object_with_properties<T> *get () const
{
return &m_object;
}
virtual db::properties_id_type prop_id () const
{
return m_object.properties_id ();
}
virtual bool equals (const generic_shape_iterator_delegate_base<db::object_with_properties<T> > *other) const
{
const generic_shape_iterator_with_properties_delegate<T> *other_cast = dynamic_cast<const generic_shape_iterator_with_properties_delegate<T> *> (other);
return other_cast && m_basic == other_cast->m_basic;
}
private:
db::generic_shape_iterator<T> m_basic;
db::object_with_properties<T> m_object;
void set ()
{
m_object = db::object_with_properties<T> (*m_basic, m_basic.prop_id ());
}
};
template <class T>
generic_shape_iterator<db::object_with_properties<T> > make_wp_iter (generic_shape_iterator<T> &&basic)
{
return generic_shape_iterator<db::object_with_properties<T> > ().set_delegate (new generic_shape_iterator_with_properties_delegate<T> (basic));
}
template <class T>
generic_shape_iterator<db::object_with_properties<T> > make_wp_iter (db::generic_shape_iterator_delegate_base<T> *delegate)
{
return generic_shape_iterator<db::object_with_properties<T> > ().set_delegate (new generic_shape_iterator_with_properties_delegate<T> (delegate));
}
/**
* @brief A helper class allowing delivery of addressable objects
*
* In some applications (i.e. box scanner), shapes need to be taken
* by address. An iterator cannot always deliver addressable objects.
* This class help providing this ability by keeping a temporary copy
* if required.
* The addressable_shape_delivery class help providing this ability by keeping temporary copies
* if required on a heap.
*/
template <class Iter>
@ -422,32 +553,22 @@ public:
}
}
const value_type &operator* () const
{
return *operator-> ();
}
db::properties_id_type prop_id () const
{
return m_iter.prop_id ();
}
private:
Iter m_iter;
bool m_iterator_is_addressable;
std::list<value_type> m_heap;
};
template <class Iter>
class DB_PUBLIC addressable_shape_delivery_gen
: public addressable_shape_delivery_impl<Iter>
{
public:
addressable_shape_delivery_gen ()
: addressable_shape_delivery_impl<Iter> ()
{ }
explicit addressable_shape_delivery_gen (const Iter &iter, bool iterator_is_addressable)
: addressable_shape_delivery_impl<Iter> (iter, iterator_is_addressable)
{ }
addressable_shape_delivery_gen &operator++ ()
{
addressable_shape_delivery_impl<Iter>::inc ();
return *this;
}
};
template <class T>
class DB_PUBLIC addressable_shape_delivery
: public addressable_shape_delivery_impl<db::generic_shape_iterator<T> >
@ -470,6 +591,29 @@ public:
}
};
template <class T>
class DB_PUBLIC unaddressable_shape_delivery
: public addressable_shape_delivery_impl<db::generic_shape_iterator<T> >
{
public:
typedef db::generic_shape_iterator<T> iter_type;
unaddressable_shape_delivery ()
: addressable_shape_delivery_impl<iter_type> ()
{ }
explicit unaddressable_shape_delivery (const iter_type &iter)
: addressable_shape_delivery_impl<iter_type> (iter, true)
{ }
unaddressable_shape_delivery &operator++ ()
{
addressable_shape_delivery_impl<iter_type>::inc ();
return *this;
}
};
}
#endif

View File

@ -872,8 +872,8 @@ struct cluster_building_receiver
typedef std::set<size_t> global_nets;
typedef std::pair<shape_vector, global_nets> cluster_value;
cluster_building_receiver (const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence)
: mp_conn (&conn), mp_attr_equivalence (attr_equivalence)
cluster_building_receiver (const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool separate_attributes)
: mp_conn (&conn), mp_attr_equivalence (attr_equivalence), m_separate_attributes (separate_attributes)
{
if (mp_attr_equivalence) {
// cache the global nets per attribute equivalence cluster
@ -930,6 +930,9 @@ struct cluster_building_receiver
void add (const T *s1, std::pair<unsigned int, size_t> p1, const T *s2, std::pair<unsigned int, size_t> p2)
{
if (m_separate_attributes && p1.second != p2.second) {
return;
}
if (! mp_conn->interacts (*s1, p1.first, *s2, p2.first)) {
return;
}
@ -1021,6 +1024,7 @@ private:
std::list<cluster_value> m_clusters;
std::map<size_t, std::set<size_t> > m_global_nets_by_attribute_cluster;
const tl::equivalence_clusters<size_t> *mp_attr_equivalence;
bool m_separate_attributes;
void join (typename std::list<cluster_value>::iterator ic1, typename std::list<cluster_value>::iterator ic2)
{
@ -1038,36 +1042,6 @@ private:
}
};
template <class T>
struct addressable_object_from_shape
{
const T *operator () (const db::Shape &shape)
{
typename T::tag object_tag;
return shape.basic_ptr (object_tag);
}
};
template <>
struct addressable_object_from_shape<db::NetShape>
{
const NetShape *operator () (const db::Shape &shape)
{
if (shape.type () == db::Shape::TextRef) {
m_heap.push_back (db::NetShape (shape.text_ref ()));
return &m_heap.back ();
} else if (shape.type () == db::Shape::PolygonRef) {
m_heap.push_back (db::NetShape (shape.polygon_ref ()));
return &m_heap.back ();
} else {
tl_assert (false);
}
}
private:
std::list<NetShape> m_heap;
};
template <class T>
struct attr_accessor
{
@ -1126,7 +1100,7 @@ struct get_shape_flags<db::NetShape>
template <class T>
void
local_clusters<T>::build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool report_progress)
local_clusters<T>::build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool report_progress, bool separate_attributes)
{
static std::string desc = tl::to_string (tr ("Building local clusters"));
@ -1143,7 +1117,7 @@ local_clusters<T>::build_clusters (const db::Cell &cell, const db::Connectivity
}
}
cluster_building_receiver<T, box_type> rec (conn, attr_equivalence);
cluster_building_receiver<T, box_type> rec (conn, attr_equivalence, separate_attributes);
bs.process (rec, 1 /*==touching*/, bc);
rec.generate_clusters (*this);
@ -1391,11 +1365,11 @@ hier_clusters<T>::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpos
template <class T>
void
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells, bool separate_attributes)
{
clear ();
cell_clusters_box_converter<T> cbc (layout, *this);
do_build (cbc, layout, cell, conn, attr_equivalence, breakout_cells);
do_build (cbc, layout, cell, conn, attr_equivalence, breakout_cells, separate_attributes);
}
namespace
@ -1437,9 +1411,18 @@ public:
/**
* @brief Constructor
*/
hc_receiver (const db::Layout &layout, const db::Cell &cell, db::connected_clusters<T> &cell_clusters, hier_clusters<T> &tree, const cell_clusters_box_converter<T> &cbc, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, typename hier_clusters<T>::instance_interaction_cache_type *instance_interaction_cache)
: mp_layout (&layout), mp_cell (&cell), mp_tree (&tree), mp_cbc (&cbc), mp_conn (&conn), mp_breakout_cells (breakout_cells), m_cluster_cache_misses (0), m_cluster_cache_hits (0), mp_instance_interaction_cache (instance_interaction_cache)
hc_receiver (const db::Layout &layout, const db::Cell &cell, db::connected_clusters<T> &cell_clusters, hier_clusters<T> &tree, const cell_clusters_box_converter<T> &cbc, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, typename hier_clusters<T>::instance_interaction_cache_type *instance_interaction_cache, bool separate_attributes)
{
mp_layout = &layout;
mp_cell = &cell;
mp_tree = &tree;
mp_cbc = &cbc;
mp_conn = &conn;
mp_breakout_cells = breakout_cells;
m_cluster_cache_misses = 0;
m_cluster_cache_hits = 0;
mp_instance_interaction_cache = instance_interaction_cache;
m_separate_attributes = separate_attributes;
mp_cell_clusters = &cell_clusters;
}
@ -1568,6 +1551,7 @@ private:
instance_interaction_cache<interaction_key_for_clusters<box_type>, std::list<std::pair<size_t, size_t> > > m_interaction_cache_for_clusters;
size_t m_cluster_cache_misses, m_cluster_cache_hits;
typename hier_clusters<T>::instance_interaction_cache_type *mp_instance_interaction_cache;
bool m_separate_attributes;
/**
* @brief Investigate a pair of instances
@ -1838,7 +1822,7 @@ private:
box_type bc2 = (common2 & i->bbox ().transformed (t12));
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (bc2); ! j.at_end (); ++j) {
if (i->interacts (*j, t21, *mp_conn)) {
if ((! m_separate_attributes || i->same_attrs (*j)) && i->interacts (*j, t21, *mp_conn)) {
new_interactions.push_back (std::make_pair (i->id (), j->id ()));
}
@ -2010,7 +1994,7 @@ private:
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (c1.bbox ().transformed (t2.inverted ())); ! j.at_end (); ++j) {
if (c1.interacts (*j, t2, *mp_conn)) {
if ((! m_separate_attributes || c1.same_attrs (*j)) && c1.interacts (*j, t2, *mp_conn)) {
interactions.push_back (std::make_pair (c1.id (), j->id ()));
}
@ -2249,7 +2233,7 @@ hier_clusters<T>::propagate_cluster_inst (const db::Layout &layout, const db::Ce
template <class T>
void
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells, bool separate_attributes)
{
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity, tl::to_string (tr ("Computing shape clusters")));
@ -2284,7 +2268,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
}
}
build_local_cluster (layout, layout.cell (*c), conn, ec);
build_local_cluster (layout, layout.cell (*c), conn, ec, separate_attributes);
++progress;
@ -2315,7 +2299,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
todo.push_back (*c);
} else {
tl_assert (! todo.empty ());
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache);
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache, separate_attributes);
done.insert (todo.begin (), todo.end ());
todo.clear ();
todo.push_back (*c);
@ -2325,7 +2309,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
}
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache);
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache, separate_attributes);
}
if (tl::verbosity () >= m_base_verbosity + 20) {
@ -2335,7 +2319,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
template <class T>
void
hier_clusters<T>::build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence)
hier_clusters<T>::build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool separate_attributes)
{
std::string msg = tl::to_string (tr ("Computing local clusters for cell: ")) + std::string (layout.cell_name (cell.cell_index ()));
if (tl::verbosity () >= m_base_verbosity + 20) {
@ -2344,15 +2328,15 @@ hier_clusters<T>::build_local_cluster (const db::Layout &layout, const db::Cell
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity + 20, msg);
connected_clusters<T> &local = m_per_cell_clusters [cell.cell_index ()];
local.build_clusters (cell, conn, attr_equivalence, true);
local.build_clusters (cell, conn, attr_equivalence, true, separate_attributes);
}
template <class T>
void
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache)
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache, bool separate_attributes)
{
for (std::vector<db::cell_index_type>::const_iterator c = cells.begin (); c != cells.end (); ++c) {
build_hier_connections (cbc, layout, layout.cell (*c), conn, breakout_cells, instance_interaction_cache);
build_hier_connections (cbc, layout, layout.cell (*c), conn, breakout_cells, instance_interaction_cache, separate_attributes);
++progress;
}
}
@ -2436,7 +2420,7 @@ private:
template <class T>
void
hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache)
hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache, bool separate_attributes)
{
std::string msg = tl::to_string (tr ("Computing hierarchical clusters for cell: ")) + std::string (layout.cell_name (cell.cell_index ()));
if (tl::verbosity () >= m_base_verbosity + 20) {
@ -2448,7 +2432,7 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
// NOTE: this is a receiver for both the child-to-child and
// local to child interactions.
std::unique_ptr<hc_receiver<T> > rec (new hc_receiver<T> (layout, cell, local, *this, cbc, conn, breakout_cells, &instance_interaction_cache));
std::unique_ptr<hc_receiver<T> > rec (new hc_receiver<T> (layout, cell, local, *this, cbc, conn, breakout_cells, &instance_interaction_cache, separate_attributes));
cell_inst_clusters_box_converter<T> cibc (cbc);
// The box scanner needs pointers so we have to first store the instances

View File

@ -337,6 +337,14 @@ public:
*/
void add_attr (attr_id a);
/**
* @brief Gets a value indicating whether the attributes of the clusters are identical
*/
bool same_attrs (const local_cluster<T> &other) const
{
return m_attrs == other.m_attrs;
}
/**
* @brief Gets the attribute iterator (begin)
*/
@ -537,7 +545,7 @@ public:
* cluster joining may happen in this case, because multi-attribute
* assignment might create connections too.
*/
void build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence = 0, bool report_progress = false);
void build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence = 0, bool report_progress = false, bool separate_attributes = false);
/**
* @brief Creates and inserts a new clusters
@ -1212,7 +1220,7 @@ public:
/**
* @brief Builds a hierarchy of clusters from a cell hierarchy and given connectivity
*/
void build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence = 0, const std::set<cell_index_type> *breakout_cells = 0);
void build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence = 0, const std::set<cell_index_type> *breakout_cells = 0, bool separate_attributes = false);
/**
* @brief Gets the connected clusters for a given cell
@ -1255,10 +1263,10 @@ public:
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const;
private:
void build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence);
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache);
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache);
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<cell_index_type> *breakout_cells);
void build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool separate_attributes);
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache, bool separate_attributes);
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache, bool separate_attributes);
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<cell_index_type> *breakout_cells, bool separate_attributes);
std::map<db::cell_index_type, connected_clusters<T> > m_per_cell_clusters;
int m_base_verbosity;

View File

@ -26,6 +26,7 @@
#include "dbRecursiveShapeIterator.h"
#include "dbBoxConvert.h"
#include "dbEdgeProcessor.h"
#include "dbEdgeBoolean.h"
#include "dbPolygonGenerators.h"
#include "dbLocalOperationUtils.h"
#include "dbShapeFlags.h"
@ -182,6 +183,31 @@ public:
shape_reference_translator (db::Layout * /*target_layout*/) { }
};
template<class Basic>
class shape_reference_translator<db::object_with_properties<Basic> >
: public shape_reference_translator<Basic>
{
public:
typedef db::object_with_properties<Basic> shape_type;
shape_reference_translator (db::Layout *target_layout)
: shape_reference_translator<Basic> (target_layout)
{
// .. nothing yet ..
}
shape_type operator() (const shape_type &s) const
{
return shape_type (shape_reference_translator<Basic>::operator () (s), s.properties_id ());
}
template <class Trans>
shape_type operator() (const shape_type &s, const Trans &tr) const
{
return shape_type (shape_reference_translator<Basic>::operator () (s, tr), s.properties_id ());
}
};
template <class Ref, class Trans>
class shape_reference_translator_with_trans_from_shape_ref
{
@ -273,6 +299,26 @@ private:
Trans m_trans;
};
template <class Basic, class Trans>
class shape_reference_translator_with_trans<db::object_with_properties<Basic>, Trans>
: public shape_reference_translator_with_trans<Basic, Trans>
{
public:
typedef db::object_with_properties<Basic> shape_type;
shape_reference_translator_with_trans (db::Layout *target_layout)
: shape_reference_translator_with_trans<Basic, Trans> (target_layout)
{
// .. nothing yet ..
}
shape_type operator() (const shape_type &s) const
{
// CAUTION: no property ID translation happens here (reasoning: the main use case is fake ID for net tagging)
return shape_type (shape_reference_translator_with_trans<Basic, Trans>::operator () (s), s.properties_id ());
}
};
// ---------------------------------------------------------------------------------------------
/**
@ -309,6 +355,8 @@ db::Box safe_box_enlarged (const db::Box &box, db::Coord dx, db::Coord dy)
{
if (box.empty ()) {
return box;
} else if (box == db::Box::world ()) {
return box;
} else {
db::Coord w2 = db::Coord (box.width () / 2);
db::Coord h2 = db::Coord (box.height () / 2);
@ -392,20 +440,6 @@ local_processor_cell_context<TS, TI, TR>::propagate (unsigned int output_layer,
}
}
// explicit instantiations
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Polygon, db::Edge>;
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::EdgePair>;
// ---------------------------------------------------------------------------------------------
// LocalProcessorCellContexts implementation
@ -493,6 +527,62 @@ subtract (std::unordered_set<db::PolygonRef> &res, const std::unordered_set<db::
ep.process (pg, op);
}
template <class TS, class TI>
static void
subtract (std::unordered_set<db::PolygonRefWithProperties> &res, const std::unordered_set<db::PolygonRefWithProperties> &other, db::Layout *layout, const db::local_processor<TS, TI, db::PolygonRefWithProperties> *proc)
{
if (other.empty ()) {
return;
}
if (! proc->boolean_core ()) {
subtract_set (res, other);
return;
}
size_t max_vertex_count = proc->max_vertex_count ();
double area_ratio = proc->area_ratio ();
std::unordered_set<db::PolygonRefWithProperties> first;
first.swap (res);
std::map<db::properties_id_type, std::pair<std::vector<const db::PolygonRefWithProperties *>, std::vector<const db::PolygonRefWithProperties *> > > by_prop_id;
for (auto i = first.begin (); i != first.end (); ++i) {
by_prop_id [i->properties_id ()].first.push_back (i.operator-> ());
}
for (auto i = other.begin (); i != other.end (); ++i) {
by_prop_id [i->properties_id ()].second.push_back (i.operator-> ());
}
db::EdgeProcessor ep;
ep.set_base_verbosity (proc->base_verbosity () + 30);
for (auto s2p = by_prop_id.begin (); s2p != by_prop_id.end (); ++s2p) {
db::properties_id_type prop_id = s2p->first;
size_t p1 = 0, p2 = 1;
ep.clear ();
for (auto i = s2p->second.first.begin (); i != s2p->second.first.end (); ++i) {
ep.insert (**i, p1);
p1 += 2;
}
for (auto i = s2p->second.second.begin (); i != s2p->second.second.end (); ++i) {
ep.insert (**i, p2);
p2 += 2;
}
db::BooleanOp op (db::BooleanOp::ANotB);
db::polygon_ref_generator_with_properties<db::PolygonRefWithProperties> pr (layout, res, prop_id);
db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count);
db::PolygonGenerator pg (splitter, true, true);
ep.process (pg, op);
}
}
template <class TS, class TI>
static void
subtract (std::unordered_set<db::Edge> &res, const std::unordered_set<db::Edge> &other, db::Layout * /*layout*/, const db::local_processor<TS, TI, db::Edge> *proc)
@ -523,6 +613,59 @@ subtract (std::unordered_set<db::Edge> &res, const std::unordered_set<db::Edge>
res.swap (result);
}
template <class TS, class TI>
static void
subtract (std::unordered_set<db::EdgeWithProperties> &res, const std::unordered_set<db::EdgeWithProperties> &other, db::Layout * /*layout*/, const db::local_processor<TS, TI, db::EdgeWithProperties> *proc)
{
if (other.empty ()) {
return;
}
if (! proc->boolean_core ()) {
subtract_set (res, other);
return;
}
std::unordered_set<db::EdgeWithProperties> first;
first.swap (res);
std::map<db::properties_id_type, std::pair<std::vector<const db::EdgeWithProperties *>, std::vector<const db::EdgeWithProperties *> > > by_prop_id;
for (auto i = first.begin (); i != first.end (); ++i) {
by_prop_id [i->properties_id ()].first.push_back (i.operator-> ());
}
for (auto i = other.begin (); i != other.end (); ++i) {
by_prop_id [i->properties_id ()].second.push_back (i.operator-> ());
}
for (auto s2p = by_prop_id.begin (); s2p != by_prop_id.end (); ++s2p) {
if (s2p->second.second.empty ()) {
for (auto i = s2p->second.first.begin (); i != s2p->second.first.end (); ++i) {
res.insert (**i);
}
} else {
db::box_scanner<db::Edge, size_t> scanner;
scanner.reserve (s2p->second.first.size () + s2p->second.second.size ());
for (auto i = s2p->second.first.begin (); i != s2p->second.first.end (); ++i) {
scanner.insert (*i, 0);
}
for (auto i = s2p->second.second.begin (); i != s2p->second.second.end (); ++i) {
scanner.insert (*i, 1);
}
db::property_injector<db::Edge, std::unordered_set<db::EdgeWithProperties> > prop_inject (&res, s2p->first);
EdgeBooleanClusterCollector<db::property_injector<db::Edge, std::unordered_set<db::EdgeWithProperties> > > cluster_collector (&prop_inject, EdgeNot);
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
}
}
}
template <class TS, class TI, class TR>
static void
subtract (std::unordered_set<TR> &res, const std::unordered_set<TR> &other, db::Layout * /*layout*/, const db::local_processor<TS, TI, TR> * /*proc*/)
@ -705,20 +848,6 @@ local_processor_cell_contexts<TS, TI, TR>::compute_results (const local_processo
}
}
// explicit instantiations
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::EdgePair>;
// ---------------------------------------------------------------------------------------------
template <class TS, class TI>
@ -810,20 +939,6 @@ shape_interactions<TS, TI>::intruder_shape (unsigned int id) const
}
}
// explicit instantiations
template class DB_PUBLIC shape_interactions<db::Polygon, db::Polygon>;
template class DB_PUBLIC shape_interactions<db::Polygon, db::Text>;
template class DB_PUBLIC shape_interactions<db::Polygon, db::TextRef>;
template class DB_PUBLIC shape_interactions<db::Polygon, db::Edge>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::TextRef>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Text>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Edge>;
template class DB_PUBLIC shape_interactions<db::Edge, db::Edge>;
template class DB_PUBLIC shape_interactions<db::Edge, db::PolygonRef>;
template class DB_PUBLIC shape_interactions<db::TextRef, db::TextRef>;
template class DB_PUBLIC shape_interactions<db::TextRef, db::PolygonRef>;
// ---------------------------------------------------------------------------------------------
// Helper classes for the LocalProcessor
@ -1014,6 +1129,7 @@ private:
void add_shapes_from_intruder_inst (unsigned int id1, const db::Cell &intruder_cell, const db::ICplxTrans &tn, unsigned int /*inst_id*/, const db::Box &region)
{
db::shape_reference_translator<TI> rt (mp_subject_layout);
db::shape_to_object<TI> s2o;
// Look up all shapes from the intruder instance which interact with the subject shape
// (given through region)
@ -1024,7 +1140,7 @@ private:
// NOTE: we intentionally rewrite to the *subject* layout - this way polygon refs in the context come from the
// subject, not from the intruder.
TI ref2 = rt (*si.shape ().basic_ptr (typename TI::tag ()), tn * si.trans ());
TI ref2 = rt (s2o (si.shape ()), tn * si.trans ());
// reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on
// the intruder side.
@ -1279,28 +1395,6 @@ local_processor_context_computation_task<TS, TI, TR>::perform ()
mp_proc->compute_contexts (*mp_contexts, mp_parent_context, mp_subject_parent, mp_subject_cell, m_subject_cell_inst, mp_intruder_cell, m_intruders, m_dist);
}
// explicit instantiations
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::TextRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::TextRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::PolygonRef>;
// ---------------------------------------------------------------------------------------------
// LocalProcessorResultComputationTask implementation
@ -1341,20 +1435,6 @@ local_processor_result_computation_task<TS, TI, TR>::perform ()
}
}
// explicit instantiations
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::EdgePair>;
// ---------------------------------------------------------------------------------------------
// LocalProcessor implementation
@ -1660,6 +1740,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
// TODO: can we shortcut this if interactions is empty?
{
db::box_scanner2<db::CellInstArray, int, TI, int> scanner;
db::addressable_object_from_shape<TI> heap;
interaction_registration_inst2shape<TS, TI, TR> rec (mp_subject_layout, contexts.subject_layer (), dist, &interactions);
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
@ -1676,7 +1757,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
for (std::map<unsigned int, const db::Shapes *>::const_iterator im = intruder_shapes.begin (); im != intruder_shapes.end (); ++im) {
for (db::Shapes::shape_iterator i = im->second->begin (shape_flags<TI> ()); !i.at_end (); ++i) {
scanner.insert2 (i->basic_ptr (typename TI::tag ()), im->first);
scanner.insert2 (heap (*i), im->first);
}
}
@ -1828,11 +1909,12 @@ struct scan_shape2shape_same_layer
operator () (const db::Shapes *subject_shapes, unsigned int subject_id0, const std::set<TI> &intruders, unsigned int intruder_layer_index, shape_interactions<TS, TI> &interactions, db::Coord dist) const
{
db::box_scanner2<TS, int, TI, int> scanner;
db::addressable_object_from_shape<TS> heap;
interaction_registration_shape1<TS, TI> rec (&interactions, intruder_layer_index);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
const TS *ref = i->basic_ptr (typename TS::tag ());
const TS *ref = heap (*i);
scanner.insert1 (ref, id++);
}
@ -1852,12 +1934,12 @@ struct scan_shape2shape_same_layer<T, T>
operator () (const db::Shapes *subject_shapes, unsigned int subject_id0, const std::set<T> &intruders, unsigned int intruder_layer, shape_interactions<T, T> &interactions, db::Coord dist) const
{
db::box_scanner<T, int> scanner;
db::addressable_object_from_shape<T> heap;
interaction_registration_shape1<T, T> rec (&interactions, intruder_layer);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<T> ()); !i.at_end (); ++i) {
const T *ref = i->basic_ptr (typename T::tag ());
scanner.insert (ref, id++);
scanner.insert (heap (*i), id++);
}
// TODO: can we confine this search to the subject's (sized) bounding box?
@ -1876,12 +1958,13 @@ struct scan_shape2shape_different_layers
operator () (db::Layout *layout, const db::Shapes *subject_shapes, const db::Shapes *intruder_shapes, unsigned int subject_id0, const std::set<TI> *intruders, unsigned int intruder_layer_index, shape_interactions<TS, TI> &interactions, db::Coord dist) const
{
db::box_scanner2<TS, int, TI, int> scanner;
db::addressable_object_from_shape<TS> sheap;
db::addressable_object_from_shape<TI> iheap;
interaction_registration_shape2shape<TS, TI> rec (layout, &interactions, intruder_layer_index);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i, ++id) {
const TS *ref = i->basic_ptr (typename TS::tag ());
scanner.insert1 (ref, id);
scanner.insert1 (sheap (*i), id);
}
// TODO: can we confine this search to the subject's (sized) bounding box?
@ -1900,7 +1983,7 @@ struct scan_shape2shape_different_layers
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = intruder_shapes->begin (shape_flags<TI> ()); !i.at_end (); ++i, ++id) {
unsigned int iid = interactions.next_id ();
scanner.insert2 (i->basic_ptr (typename TI::tag ()), iid);
scanner.insert2 (iheap (*i), iid);
rec.same (id, iid);
}
@ -1908,7 +1991,7 @@ struct scan_shape2shape_different_layers
// TODO: can we confine this search to the subject's (sized) bounding box?
for (db::Shapes::shape_iterator i = intruder_shapes->begin (shape_flags<TI> ()); !i.at_end (); ++i) {
scanner.insert2 (i->basic_ptr (typename TI::tag ()), interactions.next_id ());
scanner.insert2 (iheap (*i), interactions.next_id ());
}
}
@ -1924,6 +2007,7 @@ void
local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_contexts<TS, TI, TR> &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation<TS, TI, TR> *op, const typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, std::vector<std::unordered_set<TR> > &result) const
{
const db::Shapes *subject_shapes = &subject_cell->shapes (contexts.subject_layer ());
db::shape_to_object<TS> s2o;
shape_interactions<TS, TI> interactions;
@ -1938,8 +2022,7 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
}
if (op->on_empty_intruder_hint () != OnEmptyIntruderHint::Drop) {
const TS *ref = i->basic_ptr (typename TS::tag ());
interactions.add_subject (id, *ref);
interactions.add_subject (id, s2o (*i));
}
}
@ -1983,11 +2066,12 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
if (! subject_shapes->empty () && ! ((! intruder_cell || intruder_cell->begin ().at_end ()) && intruders.first.empty ())) {
db::box_scanner2<TS, int, db::CellInstArray, int> scanner;
db::addressable_object_from_shape<TS> heap;
interaction_registration_shape2inst<TS, TI> rec (mp_subject_layout, mp_intruder_layout, ail, il_index, op->dist (), &interactions);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
scanner.insert1 (i->basic_ptr (typename TS::tag ()), id++);
scanner.insert1 (heap (*i), id++);
}
unsigned int inst_id = 0;
@ -2167,21 +2251,16 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
db::Coord dist = op->dist ();
db::Box subjects_box = subjects.bbox ();
if (subjects_box != db::Box::world ()) {
subjects_box.enlarge (db::Vector (dist, dist));
}
db::Box subjects_box = safe_box_enlarged (subjects.bbox (), dist, dist);
db::Box intruders_box;
for (typename std::vector<generic_shape_iterator<TI> >::const_iterator il = intruders.begin (); il != intruders.end (); ++il) {
intruders_box += il->bbox ();
}
if (intruders_box != db::Box::world ()) {
intruders_box.enlarge (db::Vector (dist, dist));
}
intruders_box = safe_box_enlarged (intruders_box, dist, dist);
db::Box common_box = intruders_box & subjects_box;
if (common_box.empty ()) {
if (common_box.empty () || common_box.width () == 0 || common_box.height () == 0) {
if (needs_isolated_subjects) {
for (generic_shape_iterator<TS> is = subjects; ! is.at_end (); ++is) {
@ -2192,13 +2271,14 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
} else {
common_box = safe_box_enlarged (common_box, -1, -1);
if (needs_isolated_subjects) {
addressable_shape_delivery<TS> is (subjects);
unaddressable_shape_delivery<TS> is (subjects);
for ( ; !is.at_end (); ++is) {
const TS *shape = is.operator-> ();
unsigned int id = interactions.next_id ();
interactions.add_subject (id, *shape);
interactions.add_subject (id, *is);
}
unsigned int il_index = 0;
@ -2240,7 +2320,7 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
} else {
addressable_shape_delivery<TI> ii ((*il).confined (common_box, true));
addressable_shape_delivery<TI> ii ((*il).confined (common_box, false));
for (; !ii.at_end (); ++ii) {
scanner.insert2 (ii.operator-> (), interactions.next_id ());
}
@ -2276,7 +2356,7 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
interaction_registration_shape1_scanner_combo<TS, TI> scanner (&interactions, il_index, m_report_progress, scan_description);
addressable_shape_delivery<TS> is (subjects.confined (common_box, true));
addressable_shape_delivery<TS> is (subjects.confined (common_box, false));
unsigned int id = id_first;
for ( ; ! is.at_end (); ++is, ++id) {
@ -2295,7 +2375,7 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
// this is the case of intra-layer interactions ("foreign"): we pretend we have two layers and
// reject shape self-interactions by registering them as "same"
addressable_shape_delivery<TS> is (subjects.confined (common_box, true));
addressable_shape_delivery<TS> is (subjects.confined (common_box, false));
unsigned int id = id_first;
for ( ; ! is.at_end (); ++is, ++id) {
@ -2309,8 +2389,8 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
} else {
addressable_shape_delivery<TS> is (subjects.confined (common_box, true));
addressable_shape_delivery<TI> ii ((*il).confined (common_box, true));
addressable_shape_delivery<TS> is (subjects.confined (common_box, false));
addressable_shape_delivery<TI> ii ((*il).confined (common_box, false));
unsigned int id = id_first;
for ( ; ! is.at_end (); ++is, ++id) {
@ -2356,12 +2436,136 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
}
}
// ---------------------------------------------------------------------------------------------
// NOTE: don't forget to update the explicit instantiations in dbLocalOperation.cc
// explicit instantiations
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Polygon, db::Edge>;
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::EdgePair>;
// explicit instantiations
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::EdgePair>;
// explicit instantiations
template class DB_PUBLIC shape_interactions<db::Polygon, db::Polygon>;
template class DB_PUBLIC shape_interactions<db::Polygon, db::Text>;
template class DB_PUBLIC shape_interactions<db::Polygon, db::TextRef>;
template class DB_PUBLIC shape_interactions<db::Polygon, db::Edge>;
template class DB_PUBLIC shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
template class DB_PUBLIC shape_interactions<db::PolygonWithProperties, db::PolygonWithProperties>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::TextRef>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Text>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Edge>;
template class DB_PUBLIC shape_interactions<db::Edge, db::Edge>;
template class DB_PUBLIC shape_interactions<db::Edge, db::PolygonRef>;
template class DB_PUBLIC shape_interactions<db::TextRef, db::TextRef>;
template class DB_PUBLIC shape_interactions<db::TextRef, db::PolygonRef>;
// explicit instantiations
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::TextRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::TextRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::EdgePair>;
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::PolygonRef>;
// explicit instantiations
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::EdgePair>;
// explicit instantiations
template class DB_PUBLIC local_processor<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_processor<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
template class DB_PUBLIC local_processor<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_processor<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
template class DB_PUBLIC local_processor<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::Edge>;

View File

@ -407,11 +407,11 @@ HierarchyBuilder::new_inst_member (const RecursiveShapeIterator *iter, const db:
}
void
HierarchyBuilder::shape (const RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans &apply_always, const db::ICplxTrans & /*trans*/, const db::Box &region, const box_tree_type *complex_region)
HierarchyBuilder::shape (const RecursiveShapeIterator *iter, const db::Shape &shape, const db::ICplxTrans &apply_always, const db::ICplxTrans & /*trans*/, const db::Box &region, const box_tree_type *complex_region)
{
for (std::vector<db::Cell *>::const_iterator c = m_cell_stack.back ().second.begin (); c != m_cell_stack.back ().second.end (); ++c) {
db::Shapes &shapes = (*c)->shapes (m_target_layer);
mp_pipe->push (shape, m_trans * apply_always, region, complex_region, &shapes);
mp_pipe->push (shape, iter->prop_id (), m_trans * apply_always, region, complex_region, &shapes);
}
}
@ -424,54 +424,54 @@ ClippingHierarchyBuilderShapeReceiver::ClippingHierarchyBuilderShapeReceiver (Hi
}
void
ClippingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
ClippingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
static db::Box world = db::Box::world ();
if (region == world || is_inside (shape.bbox (), region, complex_region)) {
mp_pipe->push (shape, trans, world, 0, target);
mp_pipe->push (shape, prop_id, trans, world, 0, target);
} else if (! is_outside (shape.bbox (), region, complex_region)) {
// clip the shape if required
if (shape.is_text () || shape.is_edge () || shape.is_edge_pair ()) {
mp_pipe->push (shape, trans, world, 0, target);
mp_pipe->push (shape, prop_id, trans, world, 0, target);
} else if (shape.is_box ()) {
insert_clipped (shape.box (), trans, region, complex_region, target);
insert_clipped (shape.box (), prop_id, trans, region, complex_region, target);
} else if (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
db::Polygon poly;
shape.polygon (poly);
insert_clipped (poly, trans, region, complex_region, target);
insert_clipped (poly, prop_id, trans, region, complex_region, target);
}
}
}
void
ClippingHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
ClippingHierarchyBuilderShapeReceiver::push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
static db::Box world = db::Box::world ();
if (! complex_region) {
db::Box r = shape & region;
if (! r.empty()) {
mp_pipe->push (r, trans, world, 0, target);
mp_pipe->push (r, prop_id, trans, world, 0, target);
}
} else {
insert_clipped (shape, trans, region, complex_region, target);
insert_clipped (shape, prop_id, trans, region, complex_region, target);
}
}
void
ClippingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
ClippingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
static db::Box world = db::Box::world ();
if (region == world || (shape.box ().inside (region) && ! complex_region)) {
mp_pipe->push (shape, trans, world, 0, target);
mp_pipe->push (shape, prop_id, trans, world, 0, target);
} else {
insert_clipped (shape, trans, region, complex_region, target);
insert_clipped (shape, prop_id, trans, region, complex_region, target);
}
}
@ -529,7 +529,7 @@ ClippingHierarchyBuilderShapeReceiver::is_outside (const db::Box &box, const db:
}
void
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Box &box, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Box &box, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
db::Box bb = box & region;
static db::Box world = db::Box::world ();
@ -538,16 +538,16 @@ ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Box &box, const
for (db::RecursiveShapeReceiver::box_tree_type::overlapping_iterator cr = complex_region->begin_overlapping (bb, db::box_convert<db::Box> ()); ! cr.at_end (); ++cr) {
db::Box bc = *cr & bb;
if (! bc.empty ()) {
mp_pipe->push (bc, trans, world, 0, target);
mp_pipe->push (bc, prop_id, trans, world, 0, target);
}
}
} else if (! bb.empty ()) {
mp_pipe->push (bb, trans, world, 0, target);
mp_pipe->push (bb, prop_id, trans, world, 0, target);
}
}
void
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
std::vector<db::Polygon> clipped_poly;
static db::Box world = db::Box::world ();
@ -562,7 +562,7 @@ ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Polygon &poly,
}
for (std::vector<db::Polygon>::const_iterator p = clipped_poly.begin (); p != clipped_poly.end (); ++p) {
mp_pipe->push (*p, trans, world, 0, target);
mp_pipe->push (*p, prop_id, trans, world, 0, target);
}
}
@ -575,33 +575,33 @@ ReducingHierarchyBuilderShapeReceiver::ReducingHierarchyBuilderShapeReceiver (Hi
}
void
ReducingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
ReducingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
if (shape.is_text () || shape.is_edge () || shape.is_edge_pair ()) {
mp_pipe->push (shape, trans, region, complex_region, target);
mp_pipe->push (shape, prop_id, trans, region, complex_region, target);
} else if (shape.is_box ()) {
mp_pipe->push (shape.box (), trans, region, complex_region, target);
mp_pipe->push (shape.box (), prop_id, trans, region, complex_region, target);
} else if (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
db::Polygon poly;
shape.polygon (poly);
reduce (poly, trans, region, complex_region, target);
reduce (poly, prop_id, trans, region, complex_region, target);
}
}
void
ReducingHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
ReducingHierarchyBuilderShapeReceiver::push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
mp_pipe->push (shape, trans, region, complex_region, target);
mp_pipe->push (shape, prop_id, trans, region, complex_region, target);
}
void
ReducingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
ReducingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
reduce (shape, trans, region, complex_region, target);
reduce (shape, prop_id, trans, region, complex_region, target);
}
void
ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check)
ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check)
{
if (check && m_reject_odd_polygons && is_non_orientable_polygon (poly)) {
// non-orientable polygons generate an error
@ -620,26 +620,41 @@ ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, const db
db::split_polygon (poly, split_polygons);
for (std::vector <db::Polygon>::const_iterator sp = split_polygons.begin (); sp != split_polygons.end (); ++sp) {
reduce (*sp, trans, region, complex_region, target, false);
reduce (*sp, prop_id, trans, region, complex_region, target, false);
}
} else {
mp_pipe->push (poly, trans, region, complex_region, target);
mp_pipe->push (poly, prop_id, trans, region, complex_region, target);
}
}
// ---------------------------------------------------------------------------------------------
PolygonReferenceHierarchyBuilderShapeReceiver::PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, int text_enlargement, const tl::Variant &text_prop_name)
PolygonReferenceHierarchyBuilderShapeReceiver::PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, const db::Layout *source_layout, int text_enlargement, const tl::Variant &text_prop_name)
: mp_layout (layout), m_text_enlargement (text_enlargement), m_make_text_prop (false), m_text_prop_id (0)
{
if (! text_prop_name.is_nil ()) {
m_text_prop_id = layout->properties_repository ().prop_name_id (text_prop_name);
m_make_text_prop = true;
}
if (source_layout && source_layout != layout) {
m_pm.set_source (source_layout);
m_pm.set_target (layout);
}
}
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
void PolygonReferenceHierarchyBuilderShapeReceiver::make_pref (db::Shapes *target, const db::Polygon &poly, db::properties_id_type prop_id)
{
prop_id = m_pm (prop_id);
if (prop_id != 0) {
target->insert (db::PolygonRefWithProperties (db::PolygonRef (poly, mp_layout->shape_repository ()), prop_id));
} else {
target->insert (db::PolygonRef (poly, mp_layout->shape_repository ()));
}
}
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{
if (shape.is_box () || shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
@ -652,25 +667,35 @@ void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape
// NOTE: as this is a specialized receiver for the purpose of building region
// representations we don't need empty polygons here
if (poly.area2 () > 0) {
target->insert (db::PolygonRef (poly, mp_layout->shape_repository ()));
make_pref (target, poly, prop_id);
}
} else if (shape.is_text () && m_text_enlargement >= 0) {
// Texts generate small marker shapes with text_enlargement defining the box
db::Polygon poly (shape.text_trans () * db::Box (-m_text_enlargement, -m_text_enlargement, m_text_enlargement, m_text_enlargement));
if (! trans.is_unity ()) {
poly.transform (trans);
}
db::PolygonRef pref (poly, mp_layout->shape_repository ());
db::properties_id_type pid;
if (m_make_text_prop) {
// NOTE: text properties override the prop_id passed down from the hierarchy builder when generating the
// text marker shape
db::PropertiesRepository::properties_set ps;
ps.insert (std::make_pair (m_text_prop_id, tl::Variant (shape.text_string ())));
db::properties_id_type pid = mp_layout->properties_repository ().properties_id (ps);
pid = mp_layout->properties_repository ().properties_id (ps);
} else {
pid = m_pm (prop_id);
}
if (pid != 0) {
target->insert (db::PolygonRefWithProperties (pref, pid));
} else {
target->insert (pref);
}
@ -678,89 +703,126 @@ void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape
}
}
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{
if (shape.area () > 0) {
target->insert (db::PolygonRef (db::Polygon (shape.transformed (trans)), mp_layout->shape_repository ()));
make_pref (target, db::Polygon (shape).transformed (trans), prop_id);
}
}
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{
if (shape.area2 () > 0) {
target->insert (db::PolygonRef (shape.transformed (trans), mp_layout->shape_repository ()));
make_pref (target, shape.transformed (trans), prop_id);
}
}
// ---------------------------------------------------------------------------------------------
EdgeBuildingHierarchyBuilderShapeReceiver::EdgeBuildingHierarchyBuilderShapeReceiver (bool as_edges)
EdgeBuildingHierarchyBuilderShapeReceiver::EdgeBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const db::Layout *source_layout, bool as_edges)
: m_as_edges (as_edges)
{
// .. nothing yet ..
if (source_layout && source_layout != layout) {
m_pm.set_source (source_layout);
m_pm.set_target (layout);
}
}
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
if (m_as_edges && (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ())) {
db::Polygon poly;
shape.polygon (poly);
push (poly, trans, region, complex_region, target);
push (poly, prop_id, trans, region, complex_region, target);
} else if (m_as_edges && shape.is_box ()) {
push (shape.box (), trans, region, complex_region, target);
push (shape.box (), prop_id, trans, region, complex_region, target);
} else if (shape.is_edge ()) {
target->insert (shape.edge ());
prop_id = m_pm (prop_id);
if (prop_id != 0) {
target->insert (db::EdgeWithProperties (shape.edge (), shape.prop_id ()));
} else {
target->insert (shape.edge ());
}
}
}
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Box &box, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Box &box, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{
if (m_as_edges && ! box.empty ()) {
target->insert (db::Edge (box.p1 (), box.upper_left ()).transformed (trans));
target->insert (db::Edge (box.upper_left (), box.p2 ()).transformed (trans));
target->insert (db::Edge (box.p2 (), box.lower_right ()).transformed (trans));
target->insert (db::Edge (box.lower_right (), box.p1 ()).transformed (trans));
prop_id = m_pm (prop_id);
if (prop_id != 0) {
target->insert (db::EdgeWithProperties (db::Edge (box.p1 (), box.upper_left ()).transformed (trans), prop_id));
target->insert (db::EdgeWithProperties (db::Edge (box.upper_left (), box.p2 ()).transformed (trans), prop_id));
target->insert (db::EdgeWithProperties (db::Edge (box.p2 (), box.lower_right ()).transformed (trans), prop_id));
target->insert (db::EdgeWithProperties (db::Edge (box.lower_right (), box.p1 ()).transformed (trans), prop_id));
} else {
target->insert (db::Edge (box.p1 (), box.upper_left ()).transformed (trans));
target->insert (db::Edge (box.upper_left (), box.p2 ()).transformed (trans));
target->insert (db::Edge (box.p2 (), box.lower_right ()).transformed (trans));
target->insert (db::Edge (box.lower_right (), box.p1 ()).transformed (trans));
}
}
}
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{
if (m_as_edges) {
prop_id = m_pm (prop_id);
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
target->insert ((*e).transformed (trans));
if (prop_id != 0) {
target->insert (db::EdgeWithProperties ((*e).transformed (trans), prop_id));
} else {
target->insert ((*e).transformed (trans));
}
}
}
}
// ---------------------------------------------------------------------------------------------
EdgePairBuildingHierarchyBuilderShapeReceiver::EdgePairBuildingHierarchyBuilderShapeReceiver ()
EdgePairBuildingHierarchyBuilderShapeReceiver::EdgePairBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const db::Layout *source_layout)
{
// .. nothing yet ..
if (source_layout && source_layout != layout) {
m_pm.set_source (source_layout);
m_pm.set_target (layout);
}
}
void EdgePairBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
void EdgePairBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
{
if (shape.is_edge_pair ()) {
target->insert (shape.edge_pair ().transformed (trans));
prop_id = m_pm (prop_id);
if (prop_id != 0) {
target->insert (db::EdgePairWithProperties (shape.edge_pair ().transformed (trans), prop_id));
} else {
target->insert (shape.edge_pair ().transformed (trans));
}
}
}
// ---------------------------------------------------------------------------------------------
TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout)
TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const db::Layout *source_layout)
: mp_layout (layout)
{
// .. nothing yet ..
if (source_layout && source_layout != layout) {
m_pm.set_source (source_layout);
m_pm.set_target (layout);
}
}
void TextBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
void TextBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
{
if (shape.is_text ()) {
// NOTE: we intentionally skip all the text attributes (font etc.) here because in the context
// of a text collections we're only interested in the locations.
db::Text t (shape.text_string (), shape.text_trans ());
target->insert (db::TextRef (t.transformed (trans), mp_layout->shape_repository ()));
prop_id = m_pm (prop_id);
if (prop_id != 0) {
target->insert (db::TextRefWithProperties (db::TextRef (t.transformed (trans), mp_layout->shape_repository ()), prop_id));
} else {
target->insert (db::TextRef (t.transformed (trans), mp_layout->shape_repository ()));
}
}
}

View File

@ -27,6 +27,7 @@
#include "dbRecursiveShapeIterator.h"
#include "dbLayout.h"
#include "dbLayoutUtils.h"
#include <map>
#include <vector>
@ -55,9 +56,9 @@ public:
HierarchyBuilderShapeReceiver () { }
virtual ~HierarchyBuilderShapeReceiver () { }
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
};
/**
@ -69,28 +70,45 @@ class DB_PUBLIC HierarchyBuilderShapeInserter
public:
HierarchyBuilderShapeInserter () { }
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{
tl::ident_map<db::Layout::properties_id_type> pm;
tl::const_map<db::Layout::properties_id_type> pm (prop_id);
target->insert (shape, trans, pm);
}
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{
if (trans.is_ortho ()) {
target->insert (shape.transformed (trans));
if (prop_id != 0) {
target->insert (db::BoxWithProperties (shape.transformed (trans), prop_id));
} else {
target->insert (shape.transformed (trans));
}
} else {
db::Polygon poly (shape);
target->insert (poly.transformed (trans));
if (prop_id != 0) {
db::PolygonWithProperties poly (db::Polygon (shape), prop_id);
target->insert (poly.transformed (trans));
} else {
db::Polygon poly (shape);
target->insert (poly.transformed (trans));
}
}
}
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{
if (trans.is_unity ()) {
target->insert (shape);
if (prop_id != 0) {
target->insert (db::PolygonWithProperties (shape, prop_id));
} else {
target->insert (shape);
}
} else {
target->insert (shape.transformed (trans));
if (prop_id != 0) {
target->insert (db::PolygonWithProperties (shape.transformed (trans), prop_id));
} else {
target->insert (shape.transformed (trans));
}
}
}
};
@ -104,13 +122,13 @@ class DB_PUBLIC ClippingHierarchyBuilderShapeReceiver
public:
ClippingHierarchyBuilderShapeReceiver (HierarchyBuilderShapeReceiver *pipe = 0);
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
private:
void insert_clipped (const db::Box &box, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
void insert_clipped (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
void insert_clipped (const db::Box &box, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
void insert_clipped (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
static bool is_inside (const db::Box &box, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region);
static bool is_outside (const db::Box &box, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region);
@ -126,12 +144,12 @@ class DB_PUBLIC ReducingHierarchyBuilderShapeReceiver
public:
ReducingHierarchyBuilderShapeReceiver (HierarchyBuilderShapeReceiver *pipe = 0, double area_ratio = 3.0, size_t max_vertex_count = 16, bool reject_odd_polygons = false);
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
private:
void reduce (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check = true);
void reduce (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check = true);
HierarchyBuilderShapeReceiver *mp_pipe;
double m_area_ratio;
@ -146,17 +164,20 @@ class DB_PUBLIC PolygonReferenceHierarchyBuilderShapeReceiver
: public HierarchyBuilderShapeReceiver
{
public:
PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, int text_enlargement = -1, const tl::Variant &text_prop_name = tl::Variant ());
PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, const Layout *source_layout, int text_enlargement = -1, const tl::Variant &text_prop_name = tl::Variant ());
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
private:
void make_pref (db::Shapes *target, const db::Polygon &polygon, db::properties_id_type prop_id);
db::Layout *mp_layout;
int m_text_enlargement;
bool m_make_text_prop;
db::property_names_id_type m_text_prop_id;
db::PropertyMapper m_pm;
};
/**
@ -166,14 +187,15 @@ class DB_PUBLIC EdgeBuildingHierarchyBuilderShapeReceiver
: public HierarchyBuilderShapeReceiver
{
public:
EdgeBuildingHierarchyBuilderShapeReceiver (bool as_edges);
EdgeBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const Layout *source_layout, bool as_edges);
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
private:
bool m_as_edges;
db::PropertyMapper m_pm;
};
/**
@ -183,11 +205,14 @@ class DB_PUBLIC EdgePairBuildingHierarchyBuilderShapeReceiver
: public HierarchyBuilderShapeReceiver
{
public:
EdgePairBuildingHierarchyBuilderShapeReceiver ();
EdgePairBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const Layout *source_layout);
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Polygon &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
private:
db::PropertyMapper m_pm;
};
/**
@ -197,14 +222,15 @@ class DB_PUBLIC TextBuildingHierarchyBuilderShapeReceiver
: public HierarchyBuilderShapeReceiver
{
public:
TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout);
TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const Layout *source_layout);
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Polygon &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
private:
db::Layout *mp_layout;
db::PropertyMapper m_pm;
};
/**

View File

@ -670,11 +670,11 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
na.properties_repository () = a.properties_repository ();
nb.properties_repository () = b.properties_repository ();
db::PropertyMapper prop_normalize_a (n, a);
db::PropertyMapper prop_normalize_b (n, b);
db::PropertyMapper prop_normalize_a (&n, &a);
db::PropertyMapper prop_normalize_b (&n, &b);
db::PropertyMapper prop_remap_to_a (na, n);
db::PropertyMapper prop_remap_to_b (nb, n);
db::PropertyMapper prop_remap_to_a (&na, &n);
db::PropertyMapper prop_remap_to_b (&nb, &n);
// compare layers

View File

@ -38,7 +38,10 @@
namespace db
{
// the iterator provides the hierarchical selection (enabling/disabling cells etc.)
// -----------------------------------------------------------------------------------------------
// LayoutToNetlist implementation
// Note: the iterator provides the hierarchical selection (enabling/disabling cells etc.)
LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter)
: m_iter (iter), m_layout_index (0), m_netlist_extracted (false), m_is_flat (false), m_device_scaling (1.0), m_include_floating_subcircuits (false)
@ -155,9 +158,7 @@ db::Region *LayoutToNetlist::make_layer (const std::string &n)
si.shape_flags (db::ShapeIterator::Nothing);
std::unique_ptr <db::Region> region (new db::Region (si, dss ()));
if (! n.empty ()) {
register_layer (*region, n);
}
register_layer (*region, n);
return region.release ();
}
@ -168,9 +169,7 @@ db::Region *LayoutToNetlist::make_layer (unsigned int layer_index, const std::st
si.shape_flags (db::ShapeIterator::All);
std::unique_ptr <db::Region> region (new db::Region (si, dss ()));
if (! n.empty ()) {
register_layer (*region, n);
}
register_layer (*region, n);
return region.release ();
}
@ -181,9 +180,7 @@ db::Texts *LayoutToNetlist::make_text_layer (unsigned int layer_index, const std
si.shape_flags (db::ShapeIterator::Texts);
std::unique_ptr <db::Texts> texts (new db::Texts (si, dss ()));
if (! n.empty ()) {
register_layer (*texts, n);
}
register_layer (*texts, n);
return texts.release ();
}
@ -194,9 +191,7 @@ db::Region *LayoutToNetlist::make_polygon_layer (unsigned int layer_index, const
si.shape_flags (db::ShapeIterator::Paths | db::ShapeIterator::Polygons | db::ShapeIterator::Boxes);
std::unique_ptr <db::Region> region (new db::Region (si, dss ()));
if (! n.empty ()) {
register_layer (*region, n);
}
register_layer (*region, n);
return region.release ();
}
@ -264,7 +259,7 @@ void LayoutToNetlist::connect (const db::Region &l)
reset_extracted ();
if (! is_persisted (l)) {
register_layer (l, make_new_name ());
register_layer (l);
}
// we need to keep a reference, so we can safely delete the region
@ -279,10 +274,10 @@ void LayoutToNetlist::connect_impl (const db::ShapeCollection &a, const db::Shap
reset_extracted ();
if (! is_persisted (a)) {
register_layer (a, make_new_name ());
register_layer (a);
}
if (! is_persisted (b)) {
register_layer (b, make_new_name ());
register_layer (b);
}
// we need to keep a reference, so we can safely delete the region
@ -299,7 +294,7 @@ size_t LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const
reset_extracted ();
if (! is_persisted (l)) {
register_layer (l, make_new_name ());
register_layer (l);
}
// we need to keep a reference, so we can safely delete the region
@ -430,6 +425,8 @@ void LayoutToNetlist::mem_stat (MemStatistics *stat, MemStatistics::purpose_t pu
db::mem_stat (stat, purpose, cat, m_dlrefs, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_named_regions, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_name_of_layer, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_region_by_original, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_region_of_layer, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_joined_net_names, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_joined_net_names_per_cell, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_joined_nets, true, (void *) this);
@ -534,11 +531,29 @@ db::Region *LayoutToNetlist::layer_by_name (const std::string &name)
db::Region *LayoutToNetlist::layer_by_index (unsigned int index)
{
std::map<unsigned int, std::string>::const_iterator n = m_name_of_layer.find (index);
if (n == m_name_of_layer.end ()) {
auto n = m_region_of_layer.find (index);
if (n == m_region_of_layer.end ()) {
return 0;
} else {
return layer_by_name (n->second);
return new db::Region (new db::DeepRegion (n->second));
}
}
db::Region *LayoutToNetlist::layer_by_original (const ShapeCollectionDelegateBase *original_delegate)
{
auto n = m_region_by_original.find (tl::id_of (original_delegate));
if (n == m_region_by_original.end ()) {
DeepShapeCollectionDelegateBase *dl = const_cast<ShapeCollectionDelegateBase *> (original_delegate)->deep ();
if (dl && dl->deep_layer ().store () == mp_dss.get ()) {
// implicitly original because the collection is inside our DSS
return new db::Region (new db::DeepRegion (dl->deep_layer ()));
} else {
return 0;
}
} else {
return new db::Region (new db::DeepRegion (n->second));
}
}
@ -565,12 +580,19 @@ std::string LayoutToNetlist::name (const ShapeCollection &coll) const
}
}
void LayoutToNetlist::register_layer (const ShapeCollection &collection, const std::string &n)
void LayoutToNetlist::register_layer (const ShapeCollection &collection, const std::string &n_in)
{
if (m_named_regions.find (n) != m_named_regions.end ()) {
throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n);
if (m_region_by_original.find (tl::id_of (collection.get_delegate ())) != m_region_by_original.end ()) {
throw tl::Exception (tl::to_string (tr ("The layer is already registered")));
}
if (! n_in.empty () && m_named_regions.find (n_in) != m_named_regions.end ()) {
throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n_in);
}
// Caution: this make create names which clash with future explicit names. Hopefully, the generated names are unique enough.
std::string n = n_in.empty () ? make_new_name () : n_in;
db::DeepLayer dl;
if (m_is_flat) {
@ -586,17 +608,14 @@ void LayoutToNetlist::register_layer (const ShapeCollection &collection, const s
} else {
if (is_persisted (collection)) {
std::string prev_name = name (collection);
m_named_regions.erase (prev_name);
}
dl = delegate->deep_layer ();
}
}
m_region_by_original [tl::id_of (collection.get_delegate ())] = dl;
m_region_of_layer [dl.layer ()] = dl;
m_named_regions [n] = dl;
m_name_of_layer [dl.layer ()] = n;
}
@ -618,6 +637,17 @@ db::DeepLayer LayoutToNetlist::deep_layer_of (const db::ShapeCollection &coll) c
}
}
bool LayoutToNetlist::is_persisted_impl (const db::ShapeCollection &coll) const
{
if (coll.get_delegate ()->deep () && coll.get_delegate ()->deep ()->deep_layer ().store () == mp_dss.get ()) {
// implicitly persisted because the collection is inside our DSS
return true;
} else {
// explicitly persisted through "register"
return m_region_by_original.find (tl::id_of (coll.get_delegate ())) != m_region_by_original.end ();
}
}
db::CellMapping LayoutToNetlist::make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells)
{
std::set<db::cell_index_type> device_cells;
@ -742,28 +772,28 @@ static bool deliver_shape (const db::NetShape &s, db::Shapes &shapes, const Tr &
db::PolygonRef pr = s.polygon_ref ();
if (pr.obj ().is_box ()) {
db::Layout *layout = shapes.layout ();
if (layout) {
// NOTE: by maintaining the PolygonRefs we can directly use the output of "build_nets" as input
// for a hierarchical processor.
db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ());
if (propid) {
shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid));
} else {
shapes.insert (polygon_ref);
}
} else if (pr.obj ().is_box ()) {
if (propid) {
shapes.insert (db::BoxWithProperties (pr.obj ().box ().transformed (pr.trans ()).transformed (tr), propid));
} else {
shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
}
} else {
db::Layout *layout = shapes.layout ();
if (layout) {
db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ());
if (propid) {
shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid));
} else {
shapes.insert (polygon_ref);
}
db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr));
if (propid) {
shapes.insert (db::PolygonWithProperties (polygon, propid));
} else {
db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr));
if (propid) {
shapes.insert (db::PolygonWithProperties (polygon, propid));
} else {
shapes.insert (polygon);
}
shapes.insert (polygon);
}
}
@ -850,7 +880,7 @@ static bool deliver_shapes_of_net (bool recursive, const db::Netlist *nl, const
return true;
}
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid) const
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid, const ICplxTrans &trans) const
{
unsigned int lid = layer_of (of_layer);
const db::Circuit *circuit = net.circuit ();
@ -859,10 +889,10 @@ void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_la
std::map<unsigned int, db::Shapes *> lmap;
lmap [lid] = &to;
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), propid);
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, trans, propid);
}
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, const db::ICplxTrans &trans) const
{
unsigned int lid = layer_of (of_layer);
const db::Circuit *circuit = net.circuit ();
@ -872,268 +902,44 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region
std::map<unsigned int, db::Region *> lmap;
lmap [lid] = res.get ();
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), 0);
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, trans, 0);
return res.release ();
}
void
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const db::ICplxTrans &tr) const
LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const
{
const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0);
NetBuilder builder (&target, this);
builder.set_hier_mode (hier_mode);
builder.set_cell_name_prefix (cell_name_prefix);
builder.set_device_cell_name_prefix (device_cell_name_prefix);
build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, &net, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, tr);
builder.build_net (target_cell, net, lmap, net_prop_mode, netname_prop);
}
void
LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &tc, const std::map<unsigned int, const db::Region *> &lmap, const db::Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const db::ICplxTrans &tr) const
LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
{
db::Cell *target_cell = &tc;
NetBuilder builder (&target, cmap, this);
builder.set_hier_mode (hier_mode);
builder.set_net_cell_name_prefix (net_cell_name_prefix);
builder.set_cell_name_prefix (circuit_cell_name_prefix);
builder.set_device_cell_name_prefix (device_cell_name_prefix);
if (net_cell_name_prefix) {
const db::connected_clusters<db::NetShape> &ccl = m_net_clusters.clusters_per_cell (ci);
bool any_connections = circuit_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty ();
if (! any_connections) {
StopOnFirst sof;
std::map<unsigned int, StopOnFirst *> sof_lmap;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
sof_lmap.insert (std::make_pair (layer_of (*l->second), &sof));
}
}
bool consider_cell = ! deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, sof_lmap, tr, 0);
if (! consider_cell) {
// shortcut if cell is empty -> no net cell will be produced
return;
}
}
// make a specific cell for the net if requested
target_cell = &target.cell (target.add_cell ((std::string (net_cell_name_prefix) + net->expanded_name ()).c_str ()));
tc.insert (db::CellInstArray (db::CellInst (target_cell->cell_index ()), db::Trans ()));
}
std::map<unsigned int, db::Shapes *> target_lmap;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
target_lmap.insert (std::make_pair (layer_of (*l->second), &target_cell->shapes (l->first)));
}
}
deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, target_lmap, tr, netname_propid);
if (hier_mode != BNH_SubcircuitCells && ! device_cell_name_prefix) {
return;
}
// NOTE: we propagate the magnification part of tr down, but keep the rotation/translation part in the instance
// (we want to avoid magnified instances)
db::ICplxTrans tr_wo_mag = tr * db::ICplxTrans (1.0 / tr.mag ());
db::ICplxTrans tr_mag (tr.mag ());
const db::connected_clusters<db::NetShape> &clusters = m_net_clusters.clusters_per_cell (ci);
typedef db::connected_clusters<db::NetShape>::connections_type connections_type;
const connections_type &connections = clusters.connections_for_cluster (cid);
for (connections_type::const_iterator c = connections.begin (); c != connections.end (); ++c) {
db::cell_index_type subci = c->inst_cell_index ();
size_t subcid = c->id ();
CellReuseTableKey cmap_key (subci, netname_propid, subcid);
cell_reuse_table_type::const_iterator cm = reuse_table.find (cmap_key);
if (cm == reuse_table.end ()) {
const char *name_prefix = 0;
if (mp_netlist->device_abstract_by_cell_index (subci)) {
name_prefix = device_cell_name_prefix;
} else {
name_prefix = circuit_cell_name_prefix;
}
if (name_prefix) {
std::string cell_name = internal_layout ()->cell_name (subci);
db::cell_index_type target_ci = target.add_cell ((std::string (name_prefix) + cell_name).c_str ());
cm = reuse_table.insert (std::make_pair (cmap_key, target_ci)).first;
build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, 0, 0, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, reuse_table, tr_mag);
} else {
cm = reuse_table.insert (std::make_pair (cmap_key, std::numeric_limits<db::cell_index_type>::max ())).first;
}
}
if (cm->second != std::numeric_limits<db::cell_index_type>::max ()) {
db::CellInstArray ci (db::CellInst (cm->second), tr_wo_mag * c->inst_trans ());
ci.transform_into (tr_mag);
target_cell->insert (ci);
}
}
}
db::properties_id_type
LayoutToNetlist::make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const
{
if (! netname_prop.is_nil () || net.begin_properties () != net.end_properties ()) {
db::PropertiesRepository::properties_set propset;
// add the user properties too (TODO: make this configurable?)
for (db::Net::property_iterator p = net.begin_properties (); p != net.end_properties (); ++p) {
db::property_names_id_type key_propnameid = ly.properties_repository ().prop_name_id (p->first);
propset.insert (std::make_pair (key_propnameid, p->second));
}
if (! netname_prop.is_nil ()) {
db::property_names_id_type name_propnameid = ly.properties_repository ().prop_name_id (netname_prop);
propset.insert (std::make_pair (name_propnameid, tl::Variant (net.expanded_name ())));
}
return ly.properties_repository ().properties_id (propset);
} else {
return 0;
}
builder.build_nets (0, lmap, net_prop_mode, netname_prop);
}
void
LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const
LayoutToNetlist::build_nets (const std::vector<const db::Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
{
if (! m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
NetBuilder builder (&target, cmap, this);
builder.set_hier_mode (hier_mode);
builder.set_net_cell_name_prefix (net_cell_name_prefix);
builder.set_cell_name_prefix (circuit_cell_name_prefix);
builder.set_device_cell_name_prefix (device_cell_name_prefix);
cell_reuse_table_type cell_reuse_table;
double mag = internal_layout ()->dbu () / target.dbu ();
db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, net);
build_net_rec (net, target, target_cell, lmap, 0, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, cell_reuse_table, db::ICplxTrans (mag));
}
void
LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
{
build_nets (0, cmap, target, lmap, net_cell_name_prefix, netname_prop, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix);
}
void
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const
{
if (! cmap.has_mapping (circuit_cell)) {
const db::Cell &cc = internal_layout ()->cell (circuit_cell);
for (db::Cell::parent_inst_iterator p = cc.begin_parent_insts (); ! p.at_end (); ++p) {
db::CellInstArray ci = p->child_inst ().cell_inst ();
for (db::CellInstArray::iterator ia = ci.begin (); ! ia.at_end(); ++ia) {
db::ICplxTrans tr_parent = ci.complex_trans (*ia) * tr;
build_net_rec (net, target, p->parent_cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, tr_parent);
}
}
} else {
double mag = internal_layout ()->dbu () / target.dbu ();
db::cell_index_type target_ci = cmap.cell_mapping (circuit_cell);
build_net_rec (net, target, target.cell (target_ci), lmap, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, db::ICplxTrans (mag) * tr);
}
}
void
LayoutToNetlist::build_nets (const std::vector<const db::Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
{
if (! m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
std::set<const db::Net *> net_set;
if (nets) {
net_set.insert (nets->begin (), nets->end ());
}
cell_reuse_table_type cell_reuse_table;
const db::Netlist *netlist = mp_netlist.get ();
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
bool is_top_circuit = c->begin_parents () == c->end_parents ();
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
// exclude local nets in recursive mode except if they are explicitly selected
if (! nets && hier_mode != BNH_Disconnected && ! is_top_circuit && n->pin_count () > 0) {
continue;
}
if (! nets || net_set.find (n.operator-> ()) != net_set.end ()) {
db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n);
build_net_rec (*n, target, c->cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, db::ICplxTrans ());
}
}
if (hier_mode != BNH_Disconnected && ! nets) {
// With recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
// get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from
// subcircuits as part of the circuit which calls the subcircuit - but NOT in a subcircuit cell, because
// this will just apply to nets from certain instances. But the net cell name will be formed as "subcircuit:net"
//
// In explicit selection mode we don't care about this as nets are explicitly taken or not.
const db::Circuit &circuit = *c;
for (db::Circuit::const_subcircuit_iterator sc = circuit.begin_subcircuits (); sc != circuit.end_subcircuits (); ++sc) {
const db::SubCircuit &subcircuit = *sc;
for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p) {
if (! subcircuit.net_for_pin (p->id ())) {
const db::Net *n = subcircuit.circuit_ref ()->net_for_pin (p->id ());
if (n) {
double dbu = target.dbu ();
db::ICplxTrans tr = db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu);
db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n);
if (net_cell_name_prefix) {
std::string ncn = std::string (net_cell_name_prefix) + subcircuit.expanded_name () + ":";
build_net_rec (*n, target, c->cell_index (), cmap, lmap, ncn.c_str (), netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr);
} else {
build_net_rec (*n, target, c->cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr);
}
}
}
}
}
}
}
builder.build_nets (nets, lmap, net_prop_mode, netname_prop);
}
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point, std::vector<db::SubCircuit *> *sc_path_out, db::Circuit *initial_circuit)
@ -1692,4 +1498,400 @@ void LayoutToNetlist::set_generator (const std::string &g)
m_generator = g;
}
// -----------------------------------------------------------------------------------------------
// NetBuilder implementation
NetBuilder::NetBuilder ()
: m_hier_mode (BNH_Flatten), m_has_net_cell_name_prefix (false), m_has_cell_name_prefix (false), m_has_device_cell_name_prefix (false)
{
// .. nothing yet ..
}
NetBuilder::NetBuilder (db::Layout *target, const db::CellMapping &cmap, const db::LayoutToNetlist *source)
: mp_target (target), m_cmap (cmap), mp_source (const_cast <db::LayoutToNetlist *> (source)),
m_hier_mode (BNH_Flatten), m_has_net_cell_name_prefix (false), m_has_cell_name_prefix (false), m_has_device_cell_name_prefix (false)
{
// .. nothing yet ..
}
NetBuilder::NetBuilder (db::Layout *target, const db::LayoutToNetlist *source)
: mp_target (target), mp_source (const_cast <db::LayoutToNetlist *> (source)),
m_hier_mode (BNH_Flatten), m_has_net_cell_name_prefix (false), m_has_cell_name_prefix (false), m_has_device_cell_name_prefix (false)
{
// .. nothing yet ..
}
NetBuilder::NetBuilder (const db::NetBuilder &other)
{
operator=(other);
}
NetBuilder::NetBuilder (db::NetBuilder &&other)
{
operator=(other);
}
NetBuilder &
NetBuilder::operator= (const db::NetBuilder &other)
{
if (this != &other) {
mp_target = other.mp_target;
mp_source = other.mp_source;
m_cmap = other.m_cmap;
m_reuse_table = other.m_reuse_table;
m_hier_mode = other.m_hier_mode;
m_has_net_cell_name_prefix = other.m_has_net_cell_name_prefix;
m_net_cell_name_prefix = other.m_net_cell_name_prefix;
m_has_cell_name_prefix = other.m_has_cell_name_prefix;
m_cell_name_prefix = other.m_cell_name_prefix;
m_has_device_cell_name_prefix = other.m_has_device_cell_name_prefix;
m_device_cell_name_prefix = other.m_device_cell_name_prefix;
}
return *this;
}
NetBuilder &
NetBuilder::operator= (db::NetBuilder &&other)
{
if (this != &other) {
mp_target = other.mp_target;
other.mp_target.reset (0);
mp_source = other.mp_source;
other.mp_source.reset (0);
m_cmap.swap (other.m_cmap);
m_reuse_table.swap (other.m_reuse_table);
std::swap (m_hier_mode, other.m_hier_mode);
std::swap (m_has_net_cell_name_prefix, other.m_has_net_cell_name_prefix);
m_net_cell_name_prefix.swap (other.m_net_cell_name_prefix);
std::swap (m_has_cell_name_prefix, other.m_has_cell_name_prefix);
m_cell_name_prefix.swap (other.m_cell_name_prefix);
std::swap (m_has_device_cell_name_prefix, other.m_has_device_cell_name_prefix);
m_device_cell_name_prefix.swap (other.m_device_cell_name_prefix);
}
return *this;
}
void
NetBuilder::set_net_cell_name_prefix (const char *s)
{
m_has_net_cell_name_prefix = (s != 0);
m_net_cell_name_prefix = std::string (s ? s : "");
}
void
NetBuilder::set_cell_name_prefix (const char *s)
{
bool has_cell_name_prefix = (s != 0);
std::string cell_name_prefix (s ? s : "");
if (has_cell_name_prefix != m_has_cell_name_prefix || cell_name_prefix != m_cell_name_prefix) {
m_reuse_table.clear ();
m_has_cell_name_prefix = has_cell_name_prefix;
m_cell_name_prefix = cell_name_prefix;
}
}
void
NetBuilder::set_device_cell_name_prefix (const char *s)
{
bool has_device_cell_name_prefix = (s != 0);
std::string device_cell_name_prefix (s ? s : "");
if (has_device_cell_name_prefix != m_has_device_cell_name_prefix || device_cell_name_prefix != m_device_cell_name_prefix) {
m_reuse_table.clear ();
m_has_device_cell_name_prefix = has_device_cell_name_prefix;
m_device_cell_name_prefix = device_cell_name_prefix;
}
}
void
NetBuilder::prepare_build_nets () const
{
tl_assert (mp_target.get ());
tl_assert (mp_source.get ());
if (! mp_source->is_netlist_extracted ()) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
// Resets the "initialized" flag so existing cells are reused but freshly filled
for (auto i = m_reuse_table.begin (); i != m_reuse_table.end (); ++i) {
i->second.second = false;
}
}
void
NetBuilder::build_net (db::Cell &target_cell, const db::Net &net, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop) const
{
prepare_build_nets ();
double mag = mp_source->internal_layout ()->dbu () / mp_target->dbu ();
db::properties_id_type netname_propid = make_netname_propid (target ().properties_repository (), net_prop_mode, netname_prop, net);
build_net_rec (net, target_cell, lmap, std::string (), netname_propid, db::ICplxTrans (mag));
}
void
NetBuilder::build_all_nets (const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop) const
{
build_nets (0, lmap, net_prop_mode, netname_prop);
}
void
NetBuilder::build_nets (const std::vector<const Net *> *nets, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const
{
prepare_build_nets ();
std::set<const db::Net *> net_set;
if (nets) {
net_set.insert (nets->begin (), nets->end ());
}
const db::Netlist *netlist = mp_source->netlist ();
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
bool is_top_circuit = c->begin_parents () == c->end_parents ();
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
// exclude local nets in recursive mode except if they are explicitly selected
if (! nets && m_hier_mode != BNH_Disconnected && ! is_top_circuit && n->pin_count () > 0) {
continue;
}
if (! nets || net_set.find (n.operator-> ()) != net_set.end ()) {
db::properties_id_type netname_propid = make_netname_propid (target ().properties_repository (), prop_mode, netname_prop, *n);
build_net_rec (*n, c->cell_index (), lmap, std::string (), netname_propid, db::ICplxTrans ());
}
}
if (m_hier_mode != BNH_Disconnected && ! nets) {
// With recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
// get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from
// subcircuits as part of the circuit which calls the subcircuit - but NOT in a subcircuit cell, because
// this will just apply to nets from certain instances. But the net cell name will be formed as "subcircuit:net"
//
// In explicit selection mode we don't care about this as nets are explicitly taken or not.
const db::Circuit &circuit = *c;
for (db::Circuit::const_subcircuit_iterator sc = circuit.begin_subcircuits (); sc != circuit.end_subcircuits (); ++sc) {
const db::SubCircuit &subcircuit = *sc;
for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p) {
if (! subcircuit.net_for_pin (p->id ())) {
const db::Net *n = subcircuit.circuit_ref ()->net_for_pin (p->id ());
if (n) {
double dbu = mp_target->dbu ();
db::ICplxTrans tr = db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu);
std::string net_name_prefix = subcircuit.expanded_name () + ":";
db::properties_id_type netname_propid = make_netname_propid (target ().properties_repository (), prop_mode, netname_prop, *n, net_name_prefix);
build_net_rec (*n, c->cell_index (), lmap, net_name_prefix, netname_propid, tr);
}
}
}
}
}
}
}
void
NetBuilder::build_net_rec (const db::Net &net, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const db::ICplxTrans &tr) const
{
const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0);
build_net_rec (circuit->cell_index (), net.cluster_id (), target_cell, lmap, &net, add_net_cell_name_prefix, netname_propid, tr);
}
void
NetBuilder::build_net_rec (db::cell_index_type ci, size_t cid, db::Cell &tc, const std::map<unsigned int, const db::Region *> &lmap, const db::Net *net, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const db::ICplxTrans &tr) const
{
db::Cell *target_cell = &tc;
if (net && m_has_net_cell_name_prefix) {
const db::connected_clusters<db::NetShape> &ccl = mp_source->net_clusters ().clusters_per_cell (ci);
bool any_connections = m_has_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty ();
if (! any_connections) {
StopOnFirst sof;
std::map<unsigned int, StopOnFirst *> sof_lmap;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
sof_lmap.insert (std::make_pair (mp_source->layer_of (*l->second), &sof));
}
}
bool consider_cell = ! deliver_shapes_of_net (m_hier_mode == BNH_Flatten, mp_source->netlist (), mp_source->net_clusters (), ci, cid, sof_lmap, tr, 0);
if (! consider_cell) {
// shortcut if cell is empty -> no net cell will be produced
return;
}
}
// make a specific cell for the net if requested
target_cell = &target ().cell (target ().add_cell ((m_net_cell_name_prefix + add_net_cell_name_prefix + net->expanded_name ()).c_str ()));
tc.insert (db::CellInstArray (db::CellInst (target_cell->cell_index ()), db::Trans ()));
}
std::map<unsigned int, db::Shapes *> target_lmap;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
target_lmap.insert (std::make_pair (mp_source->layer_of (*l->second), &target_cell->shapes (l->first)));
}
}
deliver_shapes_of_net (m_hier_mode == BNH_Flatten, mp_source->netlist (), mp_source->net_clusters (), ci, cid, target_lmap, tr, netname_propid);
if (m_hier_mode != BNH_SubcircuitCells && ! m_has_device_cell_name_prefix) {
return;
}
// NOTE: we propagate the magnification part of tr down, but keep the rotation/translation part in the instance
// (we want to avoid magnified instances)
db::ICplxTrans tr_wo_mag = tr * db::ICplxTrans (1.0 / tr.mag ());
db::ICplxTrans tr_mag (tr.mag ());
const db::connected_clusters<db::NetShape> &clusters = mp_source->net_clusters ().clusters_per_cell (ci);
typedef db::connected_clusters<db::NetShape>::connections_type connections_type;
const connections_type &connections = clusters.connections_for_cluster (cid);
for (connections_type::const_iterator c = connections.begin (); c != connections.end (); ++c) {
db::cell_index_type subci = c->inst_cell_index ();
size_t subcid = c->id ();
CellReuseTableKey cmap_key (subci, netname_propid, subcid);
cell_reuse_table_type::iterator cm = m_reuse_table.find (cmap_key);
if (cm == m_reuse_table.end ()) {
bool has_name_prefix = false;
std::string name_prefix;
if (mp_source->netlist ()->device_abstract_by_cell_index (subci)) {
name_prefix = m_device_cell_name_prefix;
has_name_prefix = m_has_device_cell_name_prefix;
} else {
name_prefix = m_cell_name_prefix;
has_name_prefix = m_has_cell_name_prefix;
}
if (has_name_prefix) {
std::string cell_name = mp_source->internal_layout ()->cell_name (subci);
db::cell_index_type target_ci = target ().add_cell ((name_prefix + cell_name).c_str ());
cm = m_reuse_table.insert (std::make_pair (cmap_key, std::make_pair (target_ci, true))).first;
build_net_rec (subci, subcid, target ().cell (target_ci), lmap, 0, std::string (), netname_propid, tr_mag);
} else {
cm = m_reuse_table.insert (std::make_pair (cmap_key, std::make_pair (std::numeric_limits<db::cell_index_type>::max (), false))).first;
}
} else if (!cm->second.second && cm->second.first != std::numeric_limits<db::cell_index_type>::max ()) {
// initialize cell (after reuse of the net builder)
build_net_rec (subci, subcid, target ().cell (cm->second.first), lmap, 0, std::string (), netname_propid, tr_mag);
cm->second.second = true;
}
if (cm->second.first != std::numeric_limits<db::cell_index_type>::max ()) {
db::CellInstArray ci (db::CellInst (cm->second.first), tr_wo_mag * c->inst_trans ());
ci.transform_into (tr_mag);
target_cell->insert (ci);
}
}
}
void
NetBuilder::build_net_rec (const db::Net &net, db::cell_index_type circuit_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const
{
if (! m_cmap.has_mapping (circuit_cell)) {
const db::Cell &cc = mp_source->internal_layout ()->cell (circuit_cell);
for (db::Cell::parent_inst_iterator p = cc.begin_parent_insts (); ! p.at_end (); ++p) {
db::CellInstArray ci = p->child_inst ().cell_inst ();
for (db::CellInstArray::iterator ia = ci.begin (); ! ia.at_end(); ++ia) {
db::ICplxTrans tr_parent = ci.complex_trans (*ia) * tr;
build_net_rec (net, p->parent_cell_index (), lmap, add_net_cell_name_prefix, netname_propid, tr_parent);
}
}
} else {
double mag = mp_source->internal_layout ()->dbu () / mp_target->dbu ();
db::cell_index_type target_ci = m_cmap.cell_mapping (circuit_cell);
build_net_rec (net, target ().cell (target_ci), lmap, add_net_cell_name_prefix, netname_propid, db::ICplxTrans (mag) * tr);
}
}
db::properties_id_type
NetBuilder::make_netname_propid (db::PropertiesRepository &pr, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, const db::Net &net, const std::string &net_name_prefix)
{
if (net_prop_mode == NPM_NoProperties) {
return 0;
} else if (! netname_prop.is_nil () || (net_prop_mode == NPM_AllProperties && net.begin_properties () != net.end_properties ())) {
db::PropertiesRepository::properties_set propset;
// add the user properties too (TODO: make this configurable?)
for (db::Net::property_iterator p = net.begin_properties (); p != net.end_properties (); ++p) {
db::property_names_id_type key_propnameid = pr.prop_name_id (p->first);
propset.insert (std::make_pair (key_propnameid, p->second));
}
if (! netname_prop.is_nil ()) {
db::property_names_id_type name_propnameid = pr.prop_name_id (netname_prop);
if (net_prop_mode == NPM_NetQualifiedNameOnly) {
std::vector<tl::Variant> l;
l.reserve (2);
l.push_back (tl::Variant (net_name_prefix + net.expanded_name ()));
l.push_back (tl::Variant (net.circuit ()->name ()));
propset.insert (std::make_pair (name_propnameid, tl::Variant (l)));
} else if (net_prop_mode == NPM_NetIDOnly) {
propset.insert (std::make_pair (name_propnameid, tl::Variant (reinterpret_cast <size_t> (&net))));
} else {
propset.insert (std::make_pair (name_propnameid, tl::Variant (net_name_prefix + net.expanded_name ())));
}
}
return pr.properties_id (propset);
} else {
return 0;
}
}
}

View File

@ -27,11 +27,14 @@
#include "dbCellMapping.h"
#include "dbNetlistExtractor.h"
#include "dbNetlistDeviceExtractor.h"
#include "dbLayoutToNetlistEnums.h"
#include "tlGlobPattern.h"
namespace db
{
class NetlistBuilder;
/**
* @brief A generic framework for extracting netlists from layouts
*
@ -234,14 +237,22 @@ public:
double device_scaling () const;
/**
* @brief Register a layer under the given name
* This is a formal name for the layer. Using a name or layer properties
* (see below) enhances readability of backannotated information
* @brief Register a layer, optionally under the given name
* Using a name or layer properties (see below) enhances readability of backannotated information
* if layers are involved. Use this method to attach a name to a region
* derived by boolean operations for example.
* Named regions are persisted inside the LayoutToNetlist object.
*
* Registered regions are persisted inside the LayoutToNetlist object
* if they are flat or original layer regions.
* This allows passing flat or original layer collections.
*
* If no name is given, the region will not be registered under a name.
* Still the collection will be persisted if required.
*
* In addition to regions, text collections can be registered too.
* Including texts in "connect" makes net names begin assigned from the text strings.
*/
void register_layer (const ShapeCollection &collection, const std::string &name);
void register_layer (const ShapeCollection &collection, const std::string &name = std::string ());
/**
* @brief Gets the name of the given collection
@ -276,7 +287,7 @@ public:
template <class Collection>
bool is_persisted (const Collection &coll) const
{
return m_name_of_layer.find (layer_of (coll)) != m_name_of_layer.end ();
return is_persisted_impl (coll);
}
/**
@ -297,6 +308,20 @@ public:
*/
db::Region *layer_by_index (unsigned int index);
/**
* @brief Gets the internal layer from the original layer
*/
db::Region *layer_by_original (const ShapeCollection &original_layer)
{
return layer_by_original (original_layer.get_delegate ());
}
/**
* @brief Gets the layer from the original layer's delegate
* Returns 0 if the original layer was not registered as an input_layer.
*/
db::Region *layer_by_original (const ShapeCollectionDelegateBase *original_delegate);
/**
* @brief Iterates over the layer indexes and names managed by this object (begin)
*/
@ -688,7 +713,7 @@ public:
* This methods returns a new'd Region. It's the responsibility of the caller
* to delete this object.
*/
db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const;
db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, const db::ICplxTrans &trans = db::ICplxTrans ()) const;
/**
* @brief Delivers all shapes of a specific net and layer to the given Shapes container.
@ -701,30 +726,7 @@ public:
*
* propid is an optional properties ID which is attached to the shapes if not 0.
*/
void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0) const;
/**
* @brief An enum describing the way the net hierarchy is mapped
*/
enum BuildNetHierarchyMode
{
/**
* @brief Flatten the net
* Collects all shapes of a net and puts that into the net cell or circuit cell
*/
BNH_Flatten = 0,
/**
* @brief Build a net hierarchy adding cells for each subcircuit on the net
* Uses the circuit_cell_prefix to build the subcircuit cell names
*/
BNH_SubcircuitCells = 1,
/**
* @brief No hierarchy
* Just output the shapes of the net belonging to the circuit cell.
* Connections are not indicated!
*/
BNH_Disconnected = 2
};
void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0, const db::ICplxTrans &trans = db::ICplxTrans ()) const;
/**
* @brief Builds a net representation in the given layout and cell
@ -747,15 +749,17 @@ public:
* using a name like device_cell_name_prefix + device name. Otherwise the device shapes are
* treated as part of the net.
*
* @param net The net to build
* @param target The target layout
* @param target_cell The target cell
* @param lmap Target layer indexes (keys) and net regions (values)
* @param hier_mode See description of this method
* @param net_prop_mode How to attach properties to shapes
* @param netname_prop An (optional) property name to which to attach the net name
* @param cell_name_prefix Chooses recursive mode if non-null
* @param device_cell_name_prefix See above
*/
void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const;
void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const;
/**
* @brief Builds a full hierarchical representation of the nets
@ -788,18 +792,19 @@ public:
* @param cmap The mapping of internal layout to target layout for the circuit mapping
* @param target The target layout
* @param lmap Target layer indexes (keys) and net regions (values)
* @param hier_mode See description of this method
* @param netname_prop An (optional) property name to which to attach the net name
* @param circuit_cell_name_prefix See method description
* @param net_cell_name_prefix See method description
* @param net_prop_mode How to attach properties to shapes
* @param netname_prop The property key to use for the net name or "nil" for no netname properties
* @param hier_mode See description of this method
* @param circuit_cell_name_prefix See method description
* @param device_cell_name_prefix See above
*/
void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
/**
* @brief Like build_all_nets, but with the ability to select some nets
*/
void build_nets (const std::vector<const Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
void build_nets (const std::vector<const Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
/**
* @brief Finds the net by probing a specific location on the given layer
@ -935,6 +940,8 @@ private:
std::set<db::DeepLayer> m_dlrefs;
std::map<std::string, db::DeepLayer> m_named_regions;
std::map<unsigned int, std::string> m_name_of_layer;
std::map<tl::id_type, db::DeepLayer> m_region_by_original;
std::map<unsigned int, db::DeepLayer> m_region_of_layer;
bool m_netlist_extracted;
bool m_is_flat;
double m_device_scaling;
@ -946,6 +953,127 @@ private:
std::list<std::set<std::string> > m_joined_nets;
std::list<std::pair<tl::GlobPattern, std::set<std::string> > > m_joined_nets_per_cell;
void init ();
void ensure_netlist ();
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<NetShape> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
db::DeepLayer deep_layer_of (const ShapeCollection &coll) const;
void ensure_layout () const;
std::string make_new_name (const std::string &stem = std::string ());
db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells);
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
bool is_persisted_impl (const db::ShapeCollection &coll) const;
// implementation of NetlistManipulationCallbacks
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);
virtual void link_nets (const db::Net *net, const db::Net *with);
};
/**
* @brief An object building nets (net-to-layout)
*
* This object can be used to persist netlist builder information - e.g. reusing net cells when building individual
* layers from nets. In this case, build nets with a layer selection and call the build_net function many times.
*/
class DB_PUBLIC NetBuilder
{
public:
/**
* @brief Default constructor
*/
NetBuilder ();
/**
* @brief Constructs a net builder with a target layout, a cell mapping table and a LayoutToNetlist source
*
* @param target The target layout
* @param cmap The cell mapping from the internal layout (inside LayoutToNetlist) to the target - use LayoutInfo::cell_mapping_into to generate this map
* @param source The LayoutToNetlist source.
*
* A cell map needs to be supplied only if intending to build many nets in hierarchical mode from multiple circuits.
*/
NetBuilder (db::Layout *target, const db::CellMapping &cmap, const db::LayoutToNetlist *source);
/**
* @brief Constructs a net builder with a source only
*
* @param source The LayoutToNetlist source.
*
* This net builder can be used to build single nets into dedicated target cells.
*/
NetBuilder (db::Layout *target, const db::LayoutToNetlist *source);
/**
* @brief Copy constructor
*/
NetBuilder (const db::NetBuilder &other);
/**
* @brief Move constructor
*/
NetBuilder (db::NetBuilder &&other);
/**
* @brief Assignment
*/
NetBuilder &operator= (const db::NetBuilder &other);
/**
* @brief Move
*/
NetBuilder &operator= (db::NetBuilder &&other);
/**
* @brief Sets the net-to-hierarchy generation mode
*/
void set_hier_mode (BuildNetHierarchyMode hm)
{
m_hier_mode = hm;
}
/**
* @brief Sets or resets the net cell name prefix
*
* Pass 0 to this string value to reset it.
*/
void set_net_cell_name_prefix (const char *s);
/**
* @brief Sets or resets the circuit cell name prefix
*
* Pass 0 to this string value to reset it.
*/
void set_cell_name_prefix (const char *s);
/**
* @brief Sets or resets the device cell name prefix
*
* Pass 0 to this string value to reset it.
*/
void set_device_cell_name_prefix (const char *s);
/**
* @brief See \LayoutToNetlist for details of this function
*/
void build_net (db::Cell &target_cell, const db::Net &net, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const;
/**
* @brief See \LayoutToNetlist for details of this function
*/
void build_all_nets (const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const;
/**
* @brief See \LayoutToNetlist for details of this function
*/
void build_nets (const std::vector<const Net *> *nets, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const;
/**
* @brief A helper function to create a property ID for a given net, net property name and net property mode
*/
static db::properties_id_type make_netname_propid (db::PropertiesRepository &pr, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, const db::Net &net, const std::string &net_name_prefix = std::string ());
private:
struct CellReuseTableKey
{
CellReuseTableKey (db::cell_index_type _cell_index, db::properties_id_type _netname_propid, size_t _cluster_id)
@ -973,25 +1101,29 @@ private:
size_t cluster_id;
};
typedef std::map<CellReuseTableKey, db::cell_index_type> cell_reuse_table_type;
typedef std::map<CellReuseTableKey, std::pair<db::cell_index_type, bool> > cell_reuse_table_type;
void init ();
void ensure_netlist ();
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<NetShape> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
void build_net_rec (const db::Net &net, db::Layout &target, cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
db::DeepLayer deep_layer_of (const ShapeCollection &coll) const;
void ensure_layout () const;
std::string make_new_name (const std::string &stem = std::string ());
db::properties_id_type make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const;
db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells);
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
tl::weak_ptr<db::Layout> mp_target;
db::CellMapping m_cmap;
tl::weak_ptr<db::LayoutToNetlist> mp_source;
mutable cell_reuse_table_type m_reuse_table;
BuildNetHierarchyMode m_hier_mode;
bool m_has_net_cell_name_prefix;
std::string m_net_cell_name_prefix;
bool m_has_cell_name_prefix;
std::string m_cell_name_prefix;
bool m_has_device_cell_name_prefix;
std::string m_device_cell_name_prefix;
// implementation of NetlistManipulationCallbacks
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);
virtual void link_nets (const db::Net *net, const db::Net *with);
void build_net_rec (const db::Net &net, cell_index_type circuit_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const;
void build_net_rec (const db::Net &net, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const;
void build_net_rec (db::cell_index_type ci, size_t cid, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const Net *net, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const;
void prepare_build_nets () const;
db::Layout &target () const
{
return const_cast<db::Layout &> (*mp_target);
}
};
/**

View File

@ -0,0 +1,85 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2023 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_dbLayoutToNetlistEnums
#define _HDR_dbLayoutToNetlistEnums
namespace db
{
/**
* @brief An enum describing the way how net information is attached to shapes as properties in "build_nets"
*/
enum NetPropertyMode
{
/**
* @brief Do no generate properties
*/
NPM_NoProperties,
/**
* @brief Attach all net properties plus the net name (if a "netname_prop" is specified to "build_nets")
*/
NPM_AllProperties,
/**
* @brief Attach net name only (if a "netname_prop" is specified to "build_nets")
*/
NPM_NetNameOnly,
/**
* @brief Like NetNameOnly, but use a unique net ID (db::Net address actually) instead of name
*/
NPM_NetIDOnly,
/**
* @brief Like NetNameOnly, but use a tuple of net and circuit name
*/
NPM_NetQualifiedNameOnly,
};
/**
* @brief An enum describing the way the net hierarchy is mapped
*/
enum BuildNetHierarchyMode
{
/**
* @brief Flatten the net
* Collects all shapes of a net and puts that into the net cell or circuit cell
*/
BNH_Flatten = 0,
/**
* @brief Build a net hierarchy adding cells for each subcircuit on the net
* Uses the circuit_cell_prefix to build the subcircuit cell names
*/
BNH_SubcircuitCells = 1,
/**
* @brief No hierarchy
* Just output the shapes of the net belonging to the circuit cell.
* Connections are not indicated!
*/
BNH_Disconnected = 2
};
}
#endif

View File

@ -26,6 +26,7 @@
#include "dbPolygonTools.h"
#include "tlProgress.h"
#include "tlTimer.h"
#include "tlThreads.h"
namespace db
{
@ -60,8 +61,14 @@ DirectLayerMapping::map_layer (const LayerProperties &lprops)
// ------------------------------------------------------------------------------------
// PropertyMapper implementation
PropertyMapper::PropertyMapper (db::Layout &target, const db::Layout &source)
: mp_target (&target), mp_source (&source)
PropertyMapper::PropertyMapper (db::Layout *target, const db::Layout *source)
: mp_target (target ? &target->properties_repository () : 0), mp_source (source ? &source->properties_repository () : 0)
{
// .. nothing yet ..
}
PropertyMapper::PropertyMapper (db::PropertiesRepository *target, const db::PropertiesRepository *source)
: mp_target (target), mp_source (source)
{
// .. nothing yet ..
}
@ -82,11 +89,24 @@ PropertyMapper::PropertyMapper ()
* @brief Specify the source layout
*/
void
PropertyMapper::set_source (const db::Layout &source)
PropertyMapper::set_source (const db::Layout *source)
{
if (&source != mp_source) {
const db::PropertiesRepository *pr = source ? &source->properties_repository () : 0;
if (pr != mp_source) {
m_prop_id_map.clear ();
mp_source = &source;
mp_source = pr;
}
}
/**
* @brief Specify the source property repository
*/
void
PropertyMapper::set_source (const db::PropertiesRepository *source)
{
if (source != mp_source) {
m_prop_id_map.clear ();
mp_source = source;
}
}
@ -94,11 +114,24 @@ PropertyMapper::set_source (const db::Layout &source)
* @brief Specify the target layout
*/
void
PropertyMapper::set_target (db::Layout &target)
PropertyMapper::set_target (db::Layout *target)
{
if (&target != mp_target) {
db::PropertiesRepository *pr = target ? &target->properties_repository () : 0;
if (pr != mp_target) {
m_prop_id_map.clear ();
mp_target = &target;
mp_target = pr;
}
}
/**
* @brief Specify the target property repository
*/
void
PropertyMapper::set_target (db::PropertiesRepository *target)
{
if (target != mp_target) {
m_prop_id_map.clear ();
mp_target = target;
}
}
@ -108,17 +141,20 @@ PropertyMapper::set_target (db::Layout &target)
db::Layout::properties_id_type
PropertyMapper::operator() (db::Layout::properties_id_type source_id)
{
if (source_id == 0 || mp_source == mp_target) {
if (source_id == 0 || mp_source == mp_target || ! mp_source || ! mp_target) {
return source_id;
}
tl_assert (mp_source != 0);
tl_assert (mp_target != 0);
static tl::Mutex s_mutex;
tl::MutexLocker locker (&s_mutex);
std::map <db::Layout::properties_id_type, db::Layout::properties_id_type>::const_iterator p = m_prop_id_map.find (source_id);
if (p == m_prop_id_map.end ()) {
db::Layout::properties_id_type new_id = mp_target->properties_repository ().translate (mp_source->properties_repository (), source_id);
db::Layout::properties_id_type new_id = mp_target->translate (*mp_source, source_id);
m_prop_id_map.insert (std::make_pair (source_id, new_id));
return new_id;
} else {
@ -196,7 +232,7 @@ merge_layouts (db::Layout &target,
}
// provide the property mapper
db::PropertyMapper pm (target, source);
db::PropertyMapper pm (&target, &source);
tl::RelativeProgress progress (tl::to_string (tr ("Merge cells")), all_cells_to_copy.size (), 1);
@ -308,7 +344,7 @@ copy_or_move_shapes (db::Layout &target,
collect_cells_to_copy (source, source_cells, cell_mapping, all_top_level_cells, all_cells_to_copy);
// provide the property mapper
db::PropertyMapper pm (target, source);
db::PropertyMapper pm (&target, &source);
tl::RelativeProgress progress (tl::to_string (tr ("Merge cells")), all_cells_to_copy.size () * layer_mapping.size (), 1);

View File

@ -80,8 +80,16 @@ public:
* @param source The source layout
* @param target The target layout
*/
PropertyMapper (db::Layout &target, const db::Layout &source);
PropertyMapper (db::Layout *target, const db::Layout *source);
/**
* @brief Instantiate a property mapper for mapping of property ids from the source to the target property repository
*
* @param source The source property repository
* @param target The target property repository
*/
PropertyMapper (db::PropertiesRepository *target, const db::PropertiesRepository *source);
/**
* @brief Instantiate a property mapper for mapping of property ids from the source to the target layout
*
@ -93,21 +101,31 @@ public:
/**
* @brief Specify the source layout
*/
void set_source (const db::Layout &source);
void set_source (const db::Layout *source);
/**
* @brief Specify the source property repository
*/
void set_source (const db::PropertiesRepository *source);
/**
* @brief Specify the target layout
*/
void set_target (db::Layout &target);
void set_target (db::Layout *target);
/**
* @brief Specify the target property repository
*/
void set_target (db::PropertiesRepository *target);
/**
* @brief The actual mapping function
*/
db::Layout::properties_id_type operator() (db::Layout::properties_id_type source_id);
private:
db::Layout *mp_target;
const db::Layout *mp_source;
db::PropertiesRepository *mp_target;
const db::PropertiesRepository *mp_source;
std::map <db::Layout::properties_id_type, db::Layout::properties_id_type> m_prop_id_map;
};

View File

@ -224,7 +224,7 @@ LibraryProxy::update (db::ImportLayerMapping *layer_mapping)
clear_shapes ();
clear_insts ();
PropertyMapper prop_id_map (*layout (), lib->layout ());
PropertyMapper prop_id_map (layout (), &lib->layout ());
for (unsigned int l = 0; l < lib->layout ().layers (); ++l) {
if (layer_indices [l] >= 0) {

View File

@ -22,17 +22,6 @@
#include "dbLocalOperation.h"
#include "dbHierProcessor.h"
#include "dbBoxScanner.h"
#include "dbRecursiveShapeIterator.h"
#include "dbBoxConvert.h"
#include "dbPolygonGenerators.h"
#include "dbPolygonTools.h"
#include "dbLocalOperationUtils.h"
#include "dbEdgeBoolean.h"
#include "tlLog.h"
#include "tlTimer.h"
#include "tlInternational.h"
#include "tlProgress.h"
namespace db
{
@ -92,6 +81,14 @@ template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
template class DB_PUBLIC local_operation<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
template class DB_PUBLIC local_operation<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
template class DB_PUBLIC local_operation<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
template class DB_PUBLIC local_operation<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
template class DB_PUBLIC local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_operation<db::PolygonRef, db::Text, db::PolygonRef>;
template class DB_PUBLIC local_operation<db::PolygonRef, db::TextRef, db::PolygonRef>;
@ -109,401 +106,5 @@ template class DB_PUBLIC local_operation<db::Edge, db::Edge, db::EdgePair>;
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::TextRef>;
// ---------------------------------------------------------------------------------------------
// BoolAndOrNotLocalOperation implementation
BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and)
: m_is_and (is_and)
{
// .. nothing yet ..
}
OnEmptyIntruderHint
BoolAndOrNotLocalOperation::on_empty_intruder_hint () const
{
return m_is_and ? Drop : Copy;
}
std::string
BoolAndOrNotLocalOperation::description () const
{
return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation"));
}
void
BoolAndOrNotLocalOperation::do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t max_vertex_count, double area_ratio) const
{
tl_assert (results.size () == 1);
std::unordered_set<db::PolygonRef> &result = results.front ();
db::EdgeProcessor ep;
size_t p1 = 0, p2 = 1;
std::set<db::PolygonRef> others;
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j).second);
}
}
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::PolygonRef &subject = interactions.subject_shape (i->first);
if (others.find (subject) != others.end ()) {
if (m_is_and) {
result.insert (subject);
}
} else if (i->second.empty ()) {
// shortcut (not: keep, and: drop)
if (! m_is_and) {
result.insert (subject);
}
} else {
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p1);
}
p1 += 2;
}
}
if (! others.empty () || p1 > 0) {
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p2);
}
p2 += 2;
}
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
db::PolygonRefGenerator pr (layout, result);
db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count);
db::PolygonGenerator pg (splitter, true, true);
ep.set_base_verbosity (50);
ep.process (pg, op);
}
}
// ---------------------------------------------------------------------------------------------
// TwoBoolAndNotLocalOperation implementation
TwoBoolAndNotLocalOperation::TwoBoolAndNotLocalOperation ()
: db::local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> ()
{
// .. nothing yet ..
}
void
TwoBoolAndNotLocalOperation::do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t max_vertex_count, double area_ratio) const
{
tl_assert (results.size () == 2);
db::EdgeProcessor ep;
std::unordered_set<db::PolygonRef> &result0 = results [0];
std::unordered_set<db::PolygonRef> &result1 = results [1];
size_t p1 = 0, p2 = 1;
std::set<db::PolygonRef> others;
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j).second);
}
}
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::PolygonRef &subject = interactions.subject_shape (i->first);
if (others.find (subject) != others.end ()) {
result0.insert (subject);
} else if (i->second.empty ()) {
// shortcut (not: keep, and: drop)
result1.insert (subject);
} else {
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p1);
}
p1 += 2;
}
}
if (! others.empty () || p1 > 0) {
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p2);
}
p2 += 2;
}
db::BooleanOp op0 (db::BooleanOp::And);
db::PolygonRefGenerator pr0 (layout, result0);
db::PolygonSplitter splitter0 (pr0, area_ratio, max_vertex_count);
db::PolygonGenerator pg0 (splitter0, true, true);
db::BooleanOp op1 (db::BooleanOp::ANotB);
db::PolygonRefGenerator pr1 (layout, result1);
db::PolygonSplitter splitter1 (pr1, area_ratio, max_vertex_count);
db::PolygonGenerator pg1 (splitter1, true, true);
ep.set_base_verbosity (50);
std::vector<std::pair<db::EdgeSink *, db::EdgeEvaluatorBase *> > procs;
procs.push_back (std::make_pair (&pg0, &op0));
procs.push_back (std::make_pair (&pg1, &op1));
ep.process (procs);
}
}
std::string TwoBoolAndNotLocalOperation::description () const
{
return tl::to_string (tr ("ANDNOT operation"));
}
// ---------------------------------------------------------------------------------------------
SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wrap_count)
: m_wrap_count (wrap_count)
{
// .. nothing yet ..
}
void
SelfOverlapMergeLocalOperation::do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
tl_assert (results.size () == 1);
std::unordered_set<db::PolygonRef> &result = results.front ();
if (m_wrap_count == 0) {
return;
}
db::EdgeProcessor ep;
size_t p1 = 0, p2 = 1;
std::set<unsigned int> seen;
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
if (seen.find (i->first) == seen.end ()) {
seen.insert (i->first);
const db::PolygonRef &subject = interactions.subject_shape (i->first);
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p1);
}
p1 += 2;
}
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 o = i->second.begin (); o != i->second.end (); ++o) {
// don't take the same (really the same, not an identical one) shape twice - the interaction
// set does not take care to list just one copy of the same item on the intruder side.
if (seen.find (*o) == seen.end ()) {
seen.insert (*o);
const db::PolygonRef &intruder = interactions.intruder_shape (*o).second;
for (db::PolygonRef::polygon_edge_iterator e = intruder.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p2);
}
p2 += 2;
}
}
}
db::MergeOp op (m_wrap_count - 1);
db::PolygonRefGenerator pr (layout, result);
db::PolygonGenerator pg (pr, true, true);
ep.set_base_verbosity (50);
ep.process (pg, op);
}
OnEmptyIntruderHint SelfOverlapMergeLocalOperation::on_empty_intruder_hint () const
{
return m_wrap_count > 1 ? Drop : Copy;
}
std::string SelfOverlapMergeLocalOperation::description () const
{
return tl::sprintf (tl::to_string (tr ("Self-overlap (wrap count %d)")), int (m_wrap_count));
}
// ---------------------------------------------------------------------------------------------
// EdgeBoolAndOrNotLocalOperation implementation
EdgeBoolAndOrNotLocalOperation::EdgeBoolAndOrNotLocalOperation (EdgeBoolOp op)
: m_op (op)
{
// .. nothing yet ..
}
OnEmptyIntruderHint
EdgeBoolAndOrNotLocalOperation::on_empty_intruder_hint () const
{
return (m_op == EdgeAnd || m_op == EdgeIntersections) ? Drop : Copy;
}
std::string
EdgeBoolAndOrNotLocalOperation::description () const
{
if (m_op == EdgeIntersections) {
return tl::to_string (tr ("Edge INTERSECTION operation"));
} else if (m_op == EdgeAnd) {
return tl::to_string (tr ("Edge AND operation"));
} else if (m_op == EdgeNot) {
return tl::to_string (tr ("Edge NOT operation"));
} else {
return std::string ();
}
}
void
EdgeBoolAndOrNotLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
tl_assert (results.size () == size_t (m_op == EdgeAndNot ? 2 : 1));
std::unordered_set<db::Edge> &result = results.front ();
std::unordered_set<db::Edge> *result2 = 0;
if (results.size () > 1) {
result2 = &results[1];
}
EdgeBooleanClusterCollector<std::unordered_set<db::Edge> > cluster_collector (&result, m_op, result2);
db::box_scanner<db::Edge, size_t> scanner;
std::set<db::Edge> others;
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j).second);
}
}
bool any_subject = false;
bool is_and = (m_op == EdgeAnd || m_op == EdgeAndNot || m_op == EdgeIntersections);
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
if (others.find (subject) != others.end ()) {
if (is_and) {
result.insert (subject);
}
} else if (i->second.empty ()) {
// shortcut (not: keep, and: drop)
if (! is_and) {
result.insert (subject);
}
} else {
scanner.insert (&subject, 0);
any_subject = true;
}
}
if (! others.empty () || any_subject) {
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
scanner.insert (o.operator-> (), 1);
}
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
}
}
// ---------------------------------------------------------------------------------------------
// EdgeToPolygonLocalOperation implementation
EdgeToPolygonLocalOperation::EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders)
: m_op (op), m_include_borders (include_borders)
{
// .. nothing yet ..
}
OnEmptyIntruderHint
EdgeToPolygonLocalOperation::on_empty_intruder_hint () const
{
return m_op == EdgePolygonOp::Inside ? Drop : (m_op == EdgePolygonOp::Outside ? Copy : CopyToSecond);
}
std::string
EdgeToPolygonLocalOperation::description () const
{
if (m_op == EdgePolygonOp::Inside) {
return tl::to_string (tr ("Edge to polygon AND/INSIDE"));
} else if (m_op == EdgePolygonOp::Outside) {
return tl::to_string (tr ("Edge to polygon NOT/OUTSIDE"));
} else {
return tl::to_string (tr ("Edge to polygon ANDNOT/INOUTSIDE"));
}
}
void
EdgeToPolygonLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
tl_assert (results.size () == size_t (m_op == EdgePolygonOp::Both ? 2 : 1));
std::unordered_set<db::Edge> &result = results.front ();
std::unordered_set<db::Edge> *result2 = 0;
if (results.size () > 1) {
result2 = &results[1];
}
db::EdgeProcessor ep;
std::set<db::PolygonRef> others;
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (shape_interactions<db::Edge, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j).second);
}
}
bool any_subject = false;
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
if (i->second.empty ()) {
// shortcut (outside: keep, otherwise: drop)
if (m_op == db::EdgePolygonOp::Outside) {
result.insert (subject);
} else if (m_op == db::EdgePolygonOp::Both) {
result2->insert (subject);
}
} else {
ep.insert (subject, 1);
any_subject = true;
}
}
if (! others.empty () || any_subject) {
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end (); ++e) {
ep.insert (*e, 0);
}
}
std::unique_ptr<db::EdgeToEdgeSetGenerator> cc_second;
if (result2) {
cc_second.reset (new db::EdgeToEdgeSetGenerator (*result2, 2 /*second tag*/));
}
db::EdgeToEdgeSetGenerator cc (result, 1 /*first tag*/, cc_second.get ());
db::EdgePolygonOp op (m_op, m_include_borders);
ep.process (cc, op);
}
}
}

View File

@ -26,10 +26,7 @@
#define HDR_dbLocalOperation
#include "dbCommon.h"
#include "dbLayout.h"
#include "dbEdgeBoolean.h"
#include "dbEdgeProcessor.h"
#include <unordered_map>
#include <unordered_set>
@ -129,102 +126,6 @@ protected:
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const = 0;
};
/**
* @brief Implements a boolean AND or NOT operation
*/
class DB_PUBLIC BoolAndOrNotLocalOperation
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
{
public:
BoolAndOrNotLocalOperation (bool is_and);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &result, size_t max_vertex_count, double area_ratio) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
private:
bool m_is_and;
};
/**
* @brief Implements a boolean AND plus NOT operation
*
* This processor delivers two outputs: the first one having the AND result, the second
* one having the NOT result.
*/
class DB_PUBLIC TwoBoolAndNotLocalOperation
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
{
public:
TwoBoolAndNotLocalOperation ();
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &result, size_t max_vertex_count, double area_ratio) const;
virtual std::string description () const;
};
/**
* @brief Implements a merge operation with an overlap count
* With a given wrap_count, the result will only contains shapes where
* the original shapes overlap at least "wrap_count" times.
*/
class DB_PUBLIC SelfOverlapMergeLocalOperation
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
{
public:
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &result, size_t max_vertex_count, double area_ratio) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
private:
unsigned int m_wrap_count;
};
/**
* @brief Implements a boolean AND or NOT operation between edges
*/
class DB_PUBLIC EdgeBoolAndOrNotLocalOperation
: public local_operation<db::Edge, db::Edge, db::Edge>
{
public:
EdgeBoolAndOrNotLocalOperation (db::EdgeBoolOp op);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
// edge interaction distance is 1 to force overlap between edges and edge/boxes
virtual db::Coord dist () const { return 1; }
private:
db::EdgeBoolOp m_op;
};
/**
* @brief Implements a boolean AND or NOT operation between edges and polygons (polygons as intruders)
*
* "AND" is implemented by "outside == false", "NOT" by "outside == true" with "include_borders == true".
* With "include_borders == false" the operations are "INSIDE" and "OUTSIDE".
*/
class DB_PUBLIC EdgeToPolygonLocalOperation
: public local_operation<db::Edge, db::PolygonRef, db::Edge>
{
public:
EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
// edge interaction distance is 1 to force overlap between edges and edge/boxes
virtual db::Coord dist () const { return m_include_borders ? 1 : 0; }
private:
db::EdgePolygonOp::mode_t m_op;
bool m_include_borders;
};
}
#endif

View File

@ -27,38 +27,11 @@
namespace db
{
// -----------------------------------------------------------------------------------------------
// class EdgeToEdgeSetGenerator
EdgeToEdgeSetGenerator::EdgeToEdgeSetGenerator (std::unordered_set<db::Edge> &edges, int tag, EdgeToEdgeSetGenerator *chained)
: mp_edges (&edges), m_tag (tag), mp_chained (chained)
{
// .. nothing yet ..
}
void EdgeToEdgeSetGenerator::put (const db::Edge &edge)
{
mp_edges->insert (edge);
if (mp_chained) {
mp_chained->put (edge);
}
}
void EdgeToEdgeSetGenerator::put (const db::Edge &edge, int tag)
{
if (m_tag == 0 || m_tag == tag) {
mp_edges->insert (edge);
}
if (mp_chained) {
mp_chained->put (edge, tag);
}
}
// -----------------------------------------------------------------------------------------------
// class PolygonRefGenerator
PolygonRefToShapesGenerator::PolygonRefToShapesGenerator (db::Layout *layout, db::Shapes *shapes)
: PolygonSink (), mp_layout (layout), mp_shapes (shapes)
PolygonRefToShapesGenerator::PolygonRefToShapesGenerator (db::Layout *layout, db::Shapes *shapes, db::properties_id_type prop_id)
: PolygonSink (), mp_layout (layout), mp_shapes (shapes), m_prop_id (prop_id)
{
// .. nothing yet ..
}
@ -66,7 +39,11 @@ PolygonRefToShapesGenerator::PolygonRefToShapesGenerator (db::Layout *layout, db
void PolygonRefToShapesGenerator::put (const db::Polygon &polygon)
{
tl::MutexLocker locker (&mp_layout->lock ());
mp_shapes->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
if (m_prop_id != 0) {
mp_shapes->insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, mp_layout->shape_repository ()), m_prop_id));
} else {
mp_shapes->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
}
}
// -----------------------------------------------------------------------------------------------

View File

@ -28,7 +28,9 @@
#include "dbCommon.h"
#include "dbLayout.h"
#include "dbPropertyConstraint.h"
#include "dbPolygonGenerators.h"
#include "dbLocalOperation.h"
#include "dbHash.h"
#include "tlThreads.h"
@ -37,6 +39,8 @@
namespace db
{
class PropertyMapper;
template <class Trans>
class polygon_transformation_filter
: public PolygonSink
@ -123,31 +127,117 @@ private:
typedef polygon_ref_generator<db::PolygonRef> PolygonRefGenerator;
class DB_PUBLIC EdgeToEdgeSetGenerator
template <class T>
class DB_PUBLIC polygon_ref_generator_with_properties;
template <>
class DB_PUBLIC polygon_ref_generator_with_properties<db::PolygonRefWithProperties>
: public PolygonSink
{
public:
/**
* @brief Constructor
*/
polygon_ref_generator_with_properties (db::Layout *layout, std::unordered_set<db::PolygonRefWithProperties> &polyrefs, db::properties_id_type prop_id)
: PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs), m_prop_id (prop_id)
{
// .. nothing yet ..
}
/**
* @brief Implementation of the PolygonSink interface
*/
void put (const db::Polygon &polygon)
{
tl::MutexLocker locker (&mp_layout->lock ());
mp_polyrefs->insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, mp_layout->shape_repository ()), m_prop_id));
}
private:
db::Layout *mp_layout;
std::unordered_set<db::PolygonRefWithProperties> *mp_polyrefs;
db::properties_id_type m_prop_id;
};
template <>
class DB_PUBLIC polygon_ref_generator_with_properties<db::PolygonWithProperties>
: public PolygonSink
{
public:
/**
* @brief Constructor
*/
polygon_ref_generator_with_properties (db::Layout *, std::unordered_set<db::PolygonWithProperties> &polygons, db::properties_id_type prop_id)
: mp_polygons (&polygons), m_prop_id (prop_id)
{
// .. nothing yet ..
}
/**
* @brief Implementation of the PolygonSink interface
*/
virtual void put (const db::Polygon &polygon)
{
mp_polygons->insert (db::PolygonWithProperties (polygon, m_prop_id));
}
private:
std::unordered_set<db::PolygonWithProperties> *mp_polygons;
db::properties_id_type m_prop_id;
};
typedef polygon_ref_generator<db::PolygonRef> PolygonRefGenerator;
template <class Container>
class DB_PUBLIC edge_to_edge_set_generator
: public EdgeSink
{
public:
/**
* @brief Constructor
*/
EdgeToEdgeSetGenerator (std::unordered_set<db::Edge> &edges, int tag = 0, EdgeToEdgeSetGenerator *chained = 0);
edge_to_edge_set_generator (Container &edges, int tag = 0, EdgeSink *chained = 0)
: mp_edges (&edges), m_tag (tag), mp_chained (chained)
{
// .. nothing yet ..
}
/**
* @brief Implementation of the PolygonSink interface
*/
virtual void put (const db::Edge &edge);
virtual void put (const db::Edge &edge)
{
if (mp_edges) {
mp_edges->insert (edge);
}
if (mp_chained) {
mp_chained->put (edge);
}
}
/**
* @brief Implementation of the PolygonSink interface
*/
virtual void put (const db::Edge &edge, int tag);
virtual void put (const db::Edge &edge, int tag)
{
if (m_tag == 0 || m_tag == tag) {
if (mp_edges) {
mp_edges->insert (edge);
}
}
if (mp_chained) {
mp_chained->put (edge, tag);
}
}
private:
std::unordered_set<db::Edge> *mp_edges;
Container *mp_edges;
int m_tag;
EdgeToEdgeSetGenerator *mp_chained;
EdgeSink *mp_chained;
};
typedef edge_to_edge_set_generator<std::unordered_set<db::Edge> > EdgeToEdgeSetGenerator;
class DB_PUBLIC PolygonRefToShapesGenerator
: public PolygonSink
{
@ -155,7 +245,15 @@ public:
/**
* @brief Constructor specifying an external vector for storing the polygons
*/
PolygonRefToShapesGenerator (db::Layout *layout, db::Shapes *shapes);
PolygonRefToShapesGenerator (db::Layout *layout, db::Shapes *shapes, db::properties_id_type prop_id = 0);
/**
* @brief Sets the property ID to be used for the next polygon
*/
void set_prop_id (db::properties_id_type prop_id)
{
m_prop_id = prop_id;
}
/**
* @brief Implementation of the PolygonSink interface
@ -165,6 +263,7 @@ public:
private:
db::Layout *mp_layout;
db::Shapes *mp_shapes;
db::properties_id_type m_prop_id;
};
class DB_PUBLIC PolygonSplitter
@ -184,6 +283,129 @@ private:
size_t m_max_vertex_count;
};
template <class T, class Container>
class DB_PUBLIC property_injector
{
public:
typedef typename Container::const_iterator const_iterator;
property_injector (Container *container, db::properties_id_type prop_id)
: mp_container (container), m_prop_id (prop_id)
{
// .. nothing yet ..
}
const_iterator begin () const
{
return mp_container->begin ();
}
const_iterator end () const
{
return mp_container->end ();
}
void insert (const T &t)
{
mp_container->insert (db::object_with_properties<T> (t, m_prop_id));
}
private:
Container *mp_container;
db::properties_id_type m_prop_id;
};
/**
* @brief Separates the interacting shapes by property relation
*
* Returns a map of property ID, subject shapes and intruder shapes belonging to the subject shapes.
* Depending on the property constraint the intruders will either be ones with and properties (NoPropertyConstraint),
* the same properties than the subject (SamePropertiesConstraint) or different properties (DifferentPropertiesConstraint).
*/
template <class TS, class TI>
DB_PUBLIC_TEMPLATE
std::map<db::properties_id_type, std::pair<std::vector<const TS *>, std::set<const TI *> > >
separate_interactions_by_properties (const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, db::PropertyConstraint property_constraint, db::PropertyMapper &pms, db::PropertyMapper &pmi)
{
std::map<db::properties_id_type, std::pair<std::vector<const TS *>, std::set<const TI *> > > by_prop_id;
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
const db::object_with_properties<TS> &subject = interactions.subject_shape (i->first);
db::properties_id_type prop_id = pms (subject.properties_id ());
std::pair<std::vector<const TS *>, std::set<const TI *> > &s2p = by_prop_id [prop_id];
s2p.first.push_back (&subject);
for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) {
const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii);
if (pc_match (property_constraint, prop_id, pmi (intruder.second.properties_id ()))) {
s2p.second.insert (&intruder.second);
}
}
}
return by_prop_id;
}
/**
* @brief Separates the interacting shapes by property relation
*
* Returns a map of property ID, subject shapes and intruder shapes belonging to the subject shapes.
* Depending on the property constraint the intruders will either be ones with and properties (NoPropertyConstraint),
* the same properties than the subject (SamePropertiesConstraint) or different properties (DifferentPropertiesConstraint).
*/
template <class TS, class TI>
DB_PUBLIC_TEMPLATE
std::map<db::properties_id_type, db::shape_interactions<TS, TI> >
separate_interactions_to_interactions_by_properties (const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, db::PropertyConstraint property_constraint, db::PropertyMapper &pms, std::vector<db::PropertyMapper> &pmis)
{
std::map<db::properties_id_type, db::shape_interactions<TS, TI> > by_prop_id;
std::map<db::properties_id_type, std::set<unsigned int> > intruder_ids_by_prop_id;
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
const db::object_with_properties<TS> &subject = interactions.subject_shape (i->first);
db::properties_id_type prop_id = pms (subject.properties_id ());
db::shape_interactions<TS, TI> &s2p = by_prop_id [prop_id];
std::set<unsigned int> &intruder_ids = intruder_ids_by_prop_id [prop_id];
s2p.add_subject (i->first, subject);
for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) {
const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii);
tl_assert (intruder.first < (unsigned int) pmis.size ());
if (pc_match (property_constraint, prop_id, pmis[intruder.first] (intruder.second.properties_id ()))) {
s2p.add_interaction (i->first, *ii);
intruder_ids.insert (*ii);
}
}
}
for (auto i = intruder_ids_by_prop_id.begin (); i != intruder_ids_by_prop_id.end (); ++i) {
db::shape_interactions<TS, TI> &s2p = by_prop_id [i->first];
const std::set<unsigned int> &intruder_ids = intruder_ids_by_prop_id [i->first];
for (auto ii = intruder_ids.begin (); ii != intruder_ids.end (); ++ii) {
auto is = interactions.intruder_shape (*ii);
s2p.add_intruder_shape (*ii, is.first, is.second);
}
}
return by_prop_id;
}
}
#endif

View File

@ -50,10 +50,21 @@ void
MutableEdges::insert (const db::Box &box)
{
if (! box.empty () && box.width () > 0 && box.height () > 0) {
do_insert (db::Edge (box.lower_left (), box.upper_left ()));
do_insert (db::Edge (box.upper_left (), box.upper_right ()));
do_insert (db::Edge (box.upper_right (), box.lower_right ()));
do_insert (db::Edge (box.lower_right (), box.lower_left ()));
do_insert (db::Edge (box.lower_left (), box.upper_left ()), 0);
do_insert (db::Edge (box.upper_left (), box.upper_right ()), 0);
do_insert (db::Edge (box.upper_right (), box.lower_right ()), 0);
do_insert (db::Edge (box.lower_right (), box.lower_left ()), 0);
}
}
void
MutableEdges::insert (const db::BoxWithProperties &box)
{
if (! box.empty () && box.width () > 0 && box.height () > 0) {
do_insert (db::Edge (box.lower_left (), box.upper_left ()), box.properties_id ());
do_insert (db::Edge (box.upper_left (), box.upper_right ()), box.properties_id ());
do_insert (db::Edge (box.upper_right (), box.lower_right ()), box.properties_id ());
do_insert (db::Edge (box.lower_right (), box.lower_left ()), box.properties_id ());
}
}
@ -65,12 +76,30 @@ MutableEdges::insert (const db::Path &path)
}
}
void
MutableEdges::insert (const db::PathWithProperties &path)
{
if (path.points () > 0) {
insert (db::PolygonWithProperties (path.polygon (), path.properties_id ()));
}
}
void
MutableEdges::insert (const db::Polygon &polygon)
{
if (polygon.holes () > 0 || polygon.vertices () > 0) {
for (db::Polygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
do_insert (*e);
do_insert (*e, 0);
}
}
}
void
MutableEdges::insert (const db::PolygonWithProperties &polygon)
{
if (polygon.holes () > 0 || polygon.vertices () > 0) {
for (db::Polygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
do_insert (*e, polygon.properties_id ());
}
}
}
@ -80,7 +109,17 @@ MutableEdges::insert (const db::SimplePolygon &polygon)
{
if (polygon.vertices () > 0) {
for (db::SimplePolygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
do_insert (*e);
do_insert (*e, 0);
}
}
}
void
MutableEdges::insert (const db::SimplePolygonWithProperties &polygon)
{
if (polygon.vertices () > 0) {
for (db::SimplePolygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
do_insert (*e, polygon.properties_id ());
}
}
}
@ -88,17 +127,21 @@ MutableEdges::insert (const db::SimplePolygon &polygon)
void
MutableEdges::insert (const db::Shape &shape)
{
db::properties_id_type prop_id = shape.prop_id ();
if (shape.is_polygon () || shape.is_path () || shape.is_box ()) {
db::Polygon poly;
shape.polygon (poly);
insert (poly);
for (auto e = poly.begin_edge (); ! e.at_end (); ++e) {
do_insert (*e, prop_id);
}
} else if (shape.is_edge ()) {
db::Edge edge;
shape.edge (edge);
do_insert (edge);
do_insert (edge, prop_id);
}
}

View File

@ -54,7 +54,7 @@ public:
virtual void reserve (size_t n) = 0;
virtual void do_insert (const db::Edge &edge) = 0;
virtual void do_insert (const db::Edge &edge, db::properties_id_type prop_id) = 0;
void transform (const db::UnitTrans &) { }
void transform (const db::Disp &t) { do_transform (db::Trans (t)); }
@ -63,29 +63,37 @@ public:
void transform (const db::IMatrix2d &t) { do_transform (t); }
void transform (const db::IMatrix3d &t) { do_transform (t); }
void insert (const db::Edge &edge) { do_insert (edge); }
void insert (const db::Edge &edge) { do_insert (edge, 0); }
void insert (const db::EdgeWithProperties &edge) { do_insert (edge, edge.properties_id ()); }
void insert (const db::Box &box);
void insert (const db::BoxWithProperties &box);
void insert (const db::Path &path);
void insert (const db::PathWithProperties &path);
void insert (const db::SimplePolygon &polygon);
void insert (const db::SimplePolygonWithProperties &polygon);
void insert (const db::Polygon &polygon);
void insert (const db::PolygonWithProperties &polygon);
void insert (const db::Shape &shape);
template <class T>
void insert (const db::Shape &shape, const T &trans)
{
db::properties_id_type prop_id = shape.prop_id ();
if (shape.is_polygon () || shape.is_path () || shape.is_box ()) {
db::Polygon poly;
shape.polygon (poly);
poly.transform (trans);
insert (poly);
for (auto e = poly.begin_edge (); ! e.at_end (); ++e) {
do_insert ((*e).transformed (trans), prop_id);
}
} else if (shape.is_edge ()) {
db::Edge edge;
shape.edge (edge);
edge.transform (trans);
insert (edge);
do_insert (edge, prop_id);
}
}

View File

@ -50,7 +50,15 @@ void
MutableRegion::insert (const db::Box &box)
{
if (! box.empty () && box.width () > 0 && box.height () > 0) {
do_insert (db::Polygon (box));
do_insert (db::Polygon (box), 0);
}
}
void
MutableRegion::insert (const db::BoxWithProperties &box)
{
if (! box.empty () && box.width () > 0 && box.height () > 0) {
do_insert (db::Polygon (box), box.properties_id ());
}
}
@ -58,7 +66,15 @@ void
MutableRegion::insert (const db::Path &path)
{
if (path.points () > 0) {
do_insert (path.polygon ());
do_insert (path.polygon (), 0);
}
}
void
MutableRegion::insert (const db::PathWithProperties &path)
{
if (path.points () > 0) {
do_insert (path.polygon (), path.properties_id ());
}
}
@ -68,7 +84,17 @@ MutableRegion::insert (const db::SimplePolygon &polygon)
if (polygon.vertices () > 0) {
db::Polygon poly;
poly.assign_hull (polygon.begin_hull (), polygon.end_hull ());
do_insert (poly);
do_insert (poly, 0);
}
}
void
MutableRegion::insert (const db::SimplePolygonWithProperties &polygon)
{
if (polygon.vertices () > 0) {
db::Polygon poly;
poly.assign_hull (polygon.begin_hull (), polygon.end_hull ());
do_insert (poly, polygon.properties_id ());
}
}
@ -78,13 +104,8 @@ MutableRegion::insert (const db::Shape &shape)
if (shape.is_polygon () || shape.is_path () || shape.is_box ()) {
db::Polygon poly;
shape.polygon (poly);
insert (poly);
} else if (shape.is_path ()) {
insert (shape.path ());
} else if (shape.is_box ()) {
insert (shape.box ());
do_insert (poly, shape.prop_id ());
}
}
}

View File

@ -45,7 +45,7 @@ public:
MutableRegion (const MutableRegion &other);
virtual ~MutableRegion ();
virtual void do_insert (const db::Polygon &polygon) = 0;
virtual void do_insert (const db::Polygon &polygon, db::properties_id_type prop_id) = 0;
void transform (const db::UnitTrans &) { }
void transform (const db::Disp &t) { do_transform (db::Trans (t)); }
@ -63,10 +63,14 @@ public:
virtual void reserve (size_t n) = 0;
void insert (const db::Polygon &polygon) { do_insert (polygon); }
void insert (const db::Polygon &polygon) { do_insert (polygon, 0); }
void insert (const db::PolygonWithProperties &polygon) { do_insert (polygon, polygon.properties_id ()); }
void insert (const db::Box &box);
void insert (const db::BoxWithProperties &box);
void insert (const db::Path &path);
void insert (const db::PathWithProperties &path);
void insert (const db::SimplePolygon &polygon);
void insert (const db::SimplePolygonWithProperties &polygon);
void insert (const db::Shape &shape);
@ -77,7 +81,7 @@ public:
db::Polygon poly;
shape.polygon (poly);
poly.transform (trans);
insert (poly);
do_insert (poly, shape.prop_id ());
}
}

View File

@ -27,6 +27,9 @@
#include "dbText.h"
#include "dbShapeRepository.h"
#include "dbBoxConvert.h"
#include "dbShape.h"
#include "dbShapeFlags.h" // for addressable_object_from_shape
#include "tlSList.h"
namespace db {
@ -172,6 +175,28 @@ struct box_convert<db::NetShape>
}
};
template <>
struct addressable_object_from_shape<db::NetShape>
{
typedef db::NetShape value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.type () == db::Shape::TextRef) {
m_heap.push_back (db::NetShape (shape.text_ref ()));
return &m_heap.back ();
} else if (shape.type () == db::Shape::PolygonRef) {
m_heap.push_back (db::NetShape (shape.polygon_ref ()));
return &m_heap.back ();
} else {
tl_assert (false);
}
}
private:
tl::slist<NetShape> m_heap;
};
}
#endif

View File

@ -285,7 +285,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
for (connected_clusters_type::all_iterator c = clusters.begin_all (); ! c.at_end (); ++c) {
const db::local_cluster<db::NetShape> &lc = clusters.cluster_by_id (*c);
if (clusters.connections_for_cluster (*c).empty () && lc.empty ()) {
const connected_clusters_type::connections_type &cc = clusters.connections_for_cluster (*c);
if (cc.empty () && lc.empty ()) {
// this is an entirely empty cluster so we skip it.
// Such clusters are left over when joining clusters.
continue;
@ -313,6 +314,23 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
}
}
#if 0
// This code will pull net names from subcircuits into their parents if those nets are dummy connections
// made to satisfy the subcircuit's pin, but not to make a physical connection.
// Don't know whether this is a good idea, so this code is disabled for now.
if (net_names.empty () && clusters.is_dummy (*c) && net->subcircuit_pin_count () == 1) {
// in the case of a dummy connection (partially connected subcircuits) create a
// new name indicating the subcircuit and the subcircuit net name - this makes subcircuit
// net names available (the net is pseudo-root inside in the subcircuit)
const db::NetSubcircuitPinRef &sc_pin = *net->begin_subcircuit_pins ();
const db::Net *sc_net = sc_pin.subcircuit ()->circuit_ref ()->net_for_pin (sc_pin.pin_id ());
if (sc_net && ! sc_net->name ().empty ()) {
net_names.insert (sc_pin.subcircuit ()->expanded_name () + ":" + sc_net->name ());
}
}
#endif
assign_net_names (net, net_names);
if (! clusters.is_root (*c)) {

View File

@ -176,6 +176,15 @@ public:
m_id = id;
}
/**
* @brief Returns the transformed object
*/
template <class Trans>
object_with_properties<Obj> transformed (const Trans &tr) const
{
return object_with_properties<Obj> (Obj::transformed (tr), m_id);
}
private:
properties_id_type m_id;
};

View File

@ -41,7 +41,7 @@ namespace
typedef db::EdgePair value_type;
OriginalLayerEdgePairsIterator (const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans)
: m_rec_iter (iter), m_iter_trans (trans)
: m_rec_iter (iter), m_iter_trans (trans), m_prop_id (0)
{
set ();
}
@ -67,6 +67,11 @@ namespace
return &m_shape;
}
virtual db::properties_id_type prop_id () const
{
return m_prop_id;
}
virtual EdgePairsIteratorDelegate *clone () const
{
return new OriginalLayerEdgePairsIterator (*this);
@ -100,15 +105,17 @@ namespace
db::RecursiveShapeIterator m_rec_iter;
db::ICplxTrans m_iter_trans;
value_type m_shape;
db::properties_id_type m_prop_id;
void set ()
{
while (! m_rec_iter.at_end () && !m_rec_iter.shape ().is_edge_pair ()) {
while (! m_rec_iter.at_end () && !m_rec_iter->is_edge_pair ()) {
++m_rec_iter;
}
if (! m_rec_iter.at_end ()) {
m_rec_iter.shape ().edge_pair (m_shape);
m_rec_iter->edge_pair (m_shape);
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
m_prop_id = m_rec_iter.prop_id ();
}
}
@ -195,6 +202,24 @@ OriginalLayerEdgePairs::iter () const
return &m_iter;
}
void
OriginalLayerEdgePairs::apply_property_translator (const db::PropertiesTranslator &pt)
{
m_iter.apply_property_translator (pt);
}
db::PropertiesRepository *
OriginalLayerEdgePairs::properties_repository ()
{
return m_iter.layout () ? &const_cast<db::Layout * >(m_iter.layout ())->properties_repository () : 0;
}
const db::PropertiesRepository *
OriginalLayerEdgePairs::properties_repository () const
{
return m_iter.layout () ? &m_iter.layout ()->properties_repository () : 0;
}
bool
OriginalLayerEdgePairs::equals (const EdgePairs &other) const
{

View File

@ -56,6 +56,9 @@ public:
virtual bool has_valid_edge_pairs () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual bool equals (const EdgePairs &other) const;
virtual bool less (const EdgePairs &other) const;

View File

@ -42,7 +42,7 @@ namespace
typedef db::Edge value_type;
OriginalLayerEdgesIterator (const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans)
: m_rec_iter (iter), m_iter_trans (trans)
: m_rec_iter (iter), m_iter_trans (trans), m_prop_id (0)
{
set ();
}
@ -68,6 +68,11 @@ namespace
return &m_shape;
}
virtual db::properties_id_type prop_id () const
{
return m_prop_id;
}
virtual EdgesIteratorDelegate *clone () const
{
return new OriginalLayerEdgesIterator (*this);
@ -101,15 +106,17 @@ namespace
db::RecursiveShapeIterator m_rec_iter;
db::ICplxTrans m_iter_trans;
value_type m_shape;
db::properties_id_type m_prop_id;
void set ()
{
while (! m_rec_iter.at_end () && !m_rec_iter.shape ().is_edge ()) {
while (! m_rec_iter.at_end () && !m_rec_iter->is_edge ()) {
++m_rec_iter;
}
if (! m_rec_iter.at_end ()) {
m_rec_iter.shape ().edge (m_shape);
m_rec_iter->edge (m_shape);
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
m_prop_id = m_rec_iter.prop_id ();
}
}
@ -120,7 +127,6 @@ namespace
}
}
};
}
OriginalLayerEdges::OriginalLayerEdges ()
@ -245,6 +251,27 @@ OriginalLayerEdges::iter () const
return &m_iter;
}
void
OriginalLayerEdges::apply_property_translator (const db::PropertiesTranslator &pt)
{
m_iter.apply_property_translator (pt);
m_merged_edges_valid = false;
m_merged_edges.clear ();
}
db::PropertiesRepository *
OriginalLayerEdges::properties_repository ()
{
return m_iter.layout () ? &const_cast<db::Layout * >(m_iter.layout ())->properties_repository () : 0;
}
const db::PropertiesRepository *
OriginalLayerEdges::properties_repository () const
{
return m_iter.layout () ? &m_iter.layout ()->properties_repository () : 0;
}
bool
OriginalLayerEdges::equals (const Edges &other) const
{
@ -287,7 +314,7 @@ OriginalLayerEdges::ensure_merged_edges_valid () const
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve (count ());
AddressableEdgeDelivery e (begin (), has_valid_edges ());
AddressableEdgeDelivery e (begin ());
for ( ; ! e.at_end (); ++e) {
if (! e->is_degenerate ()) {

View File

@ -62,6 +62,9 @@ public:
virtual bool has_valid_merged_edges () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual bool equals (const Edges &other) const;
virtual bool less (const Edges &other) const;

View File

@ -25,7 +25,6 @@
#include "dbFlatRegion.h"
#include "dbFlatEdges.h"
#include "dbRegion.h"
#include "dbShapeProcessor.h"
#include "dbDeepEdges.h"
#include "dbDeepRegion.h"
#include "dbDeepShapeStore.h"
@ -46,7 +45,7 @@ namespace
{
public:
OriginalLayerRegionIterator (const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans)
: m_rec_iter (iter), m_iter_trans (trans)
: m_rec_iter (iter), m_iter_trans (trans), m_prop_id (0)
{
set ();
}
@ -72,6 +71,11 @@ namespace
return &m_polygon;
}
virtual db::properties_id_type prop_id () const
{
return m_prop_id;
}
virtual RegionIteratorDelegate *clone () const
{
return new OriginalLayerRegionIterator (*this);
@ -105,15 +109,17 @@ namespace
db::RecursiveShapeIterator m_rec_iter;
db::ICplxTrans m_iter_trans;
db::Polygon m_polygon;
db::properties_id_type m_prop_id;
void set ()
{
while (! m_rec_iter.at_end () && ! (m_rec_iter.shape ().is_polygon () || m_rec_iter.shape ().is_path () || m_rec_iter.shape ().is_box ())) {
while (! m_rec_iter.at_end () && ! (m_rec_iter->is_polygon () || m_rec_iter->is_path () || m_rec_iter->is_box ())) {
++m_rec_iter;
}
if (! m_rec_iter.at_end ()) {
m_rec_iter.shape ().polygon (m_polygon);
m_rec_iter->polygon (m_polygon);
m_polygon.transform (m_iter_trans * m_rec_iter.trans (), false);
m_prop_id = m_rec_iter.prop_id ();
}
}
@ -234,10 +240,10 @@ OriginalLayerRegion::count () const
size_t nn = 0;
if (iter.multiple_layers ()) {
for (std::vector<unsigned int>::const_iterator l = iter.layers ().begin (); l != iter.layers ().end (); ++l) {
nn += layout.cell (*c).shapes (*l).size (iter.shape_flags () & db::ShapeIterator::Regions);
nn += layout.cell (*c).shapes (*l).size (iter.shape_flags () & (db::ShapeIterator::Regions | db::ShapeIterator::Properties));
}
} else if (iter.layer () < layout.layers ()) {
nn += layout.cell (*c).shapes (iter.layer ()).size (iter.shape_flags () & db::ShapeIterator::Regions);
nn += layout.cell (*c).shapes (iter.layer ()).size (iter.shape_flags () & (db::ShapeIterator::Regions | db::ShapeIterator::Properties));
}
n += cc.weight (*c) * nn;
}
@ -339,6 +345,12 @@ OriginalLayerRegion::nth (size_t) const
throw tl::Exception (tl::to_string (tr ("Random access to polygons is available only for flat regions")));
}
db::properties_id_type
OriginalLayerRegion::nth_prop_id (size_t) const
{
throw tl::Exception (tl::to_string (tr ("Random access to polygons is available only for flat regions")));
}
bool
OriginalLayerRegion::has_valid_polygons () const
{
@ -357,6 +369,27 @@ OriginalLayerRegion::iter () const
return &m_iter;
}
void
OriginalLayerRegion::apply_property_translator (const db::PropertiesTranslator &pt)
{
m_iter.apply_property_translator (pt);
m_merged_polygons_valid = false;
m_merged_polygons.clear ();
}
db::PropertiesRepository *
OriginalLayerRegion::properties_repository ()
{
return m_iter.layout () ? &const_cast<db::Layout * >(m_iter.layout ())->properties_repository () : 0;
}
const db::PropertiesRepository *
OriginalLayerRegion::properties_repository () const
{
return m_iter.layout () ? &m_iter.layout ()->properties_repository () : 0;
}
bool
OriginalLayerRegion::equals (const Region &other) const
{
@ -386,6 +419,17 @@ OriginalLayerRegion::init ()
m_merged_polygons_valid = false;
}
namespace {
struct AssignProp
{
AssignProp () : prop_id (0) { }
db::properties_id_type operator() (db::properties_id_type) { return prop_id; }
db::properties_id_type prop_id;
};
}
void
OriginalLayerRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
@ -397,12 +441,19 @@ OriginalLayerRegion::insert_into (Layout *layout, db::cell_index_type into_cell,
db::Shapes &sh = layout->cell (into_cell).shapes (into_layer);
db::PropertyMapper pm;
if (m_iter.layout ()) {
pm = db::PropertyMapper (layout, m_iter.layout ());
}
// NOTE: if the source (r) is from the same layout than the shapes live in, we better
// lock the layout against updates while inserting
db::LayoutLocker locker (layout);
AssignProp ap;
for (db::RecursiveShapeIterator i = m_iter; !i.at_end (); ++i) {
tl::ident_map<db::properties_id_type> pm;
sh.insert (*i, i.trans (), pm);
db::properties_id_type prop_id = i.prop_id ();
ap.prop_id = (prop_id != 0 ? pm (prop_id) : 0);
sh.insert (*i, i.trans (), ap);
}
}
@ -412,28 +463,7 @@ OriginalLayerRegion::ensure_merged_polygons_valid () const
if (! m_merged_polygons_valid) {
m_merged_polygons.clear ();
db::EdgeProcessor ep (report_progress (), progress_desc ());
ep.set_base_verbosity (base_verbosity ());
// count edges and reserve memory
size_t n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
n += p->vertices ();
}
ep.reserve (n);
// insert the polygons into the processor
n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p, ++n) {
ep.insert (*p, n);
}
// and run the merge step
db::MergeOp op (0);
db::ShapeGenerator pc (m_merged_polygons);
db::PolygonGenerator pg (pc, false /*don't resolve holes*/, min_coherence ());
ep.process (pg, op);
merge_polygons_to (m_merged_polygons, min_coherence (), 0);
m_merged_polygons_valid = true;

View File

@ -62,10 +62,14 @@ public:
virtual size_t hier_count () const;
virtual const db::Polygon *nth (size_t n) const;
virtual db::properties_id_type nth_prop_id (size_t) const;
virtual bool has_valid_polygons () const;
virtual bool has_valid_merged_polygons () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;

View File

@ -41,7 +41,7 @@ namespace
typedef db::Text value_type;
OriginalLayerTextsIterator (const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans)
: m_rec_iter (iter), m_iter_trans (trans)
: m_rec_iter (iter), m_iter_trans (trans), m_prop_id (0)
{
set ();
}
@ -67,6 +67,11 @@ namespace
return &m_shape;
}
virtual db::properties_id_type prop_id () const
{
return m_prop_id;
}
virtual OriginalLayerTextsIterator *clone () const
{
return new OriginalLayerTextsIterator (*this);
@ -100,6 +105,7 @@ namespace
db::RecursiveShapeIterator m_rec_iter;
db::ICplxTrans m_iter_trans;
value_type m_shape;
db::properties_id_type m_prop_id;
void set ()
{
@ -107,8 +113,9 @@ namespace
++m_rec_iter;
}
if (! m_rec_iter.at_end ()) {
m_rec_iter.shape ().text (m_shape);
m_rec_iter->text (m_shape);
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
m_prop_id = m_rec_iter.prop_id ();
}
}
@ -195,6 +202,24 @@ OriginalLayerTexts::iter () const
return &m_iter;
}
void
OriginalLayerTexts::apply_property_translator (const db::PropertiesTranslator &pt)
{
m_iter.apply_property_translator (pt);
}
db::PropertiesRepository *
OriginalLayerTexts::properties_repository ()
{
return m_iter.layout () ? &const_cast<db::Layout * >(m_iter.layout ())->properties_repository () : 0;
}
const db::PropertiesRepository *
OriginalLayerTexts::properties_repository () const
{
return m_iter.layout () ? &m_iter.layout ()->properties_repository () : 0;
}
bool
OriginalLayerTexts::equals (const Texts &other) const
{

View File

@ -56,6 +56,9 @@ public:
virtual bool has_valid_texts () const;
virtual const db::RecursiveShapeIterator *iter () const;
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual bool equals (const Texts &other) const;
virtual bool less (const Texts &other) const;

View File

@ -42,6 +42,12 @@ PropertiesRepository::PropertiesRepository (db::LayoutStateModel *state_model)
tl_assert (id == 0);
}
PropertiesRepository::PropertiesRepository (const PropertiesRepository &d)
: mp_state_model (0)
{
operator= (d);
}
PropertiesRepository &
PropertiesRepository::operator= (const PropertiesRepository &d)
{
@ -207,5 +213,135 @@ PropertiesRepository::translate (const PropertiesRepository &rep, properties_id_
return properties_id (new_pset);
}
// ----------------------------------------------------------------------------------
// PropertiesRepository implementation
PropertiesTranslator::PropertiesTranslator ()
: m_pass (true), m_null (true)
{
// .. nothing yet ..
}
PropertiesTranslator::PropertiesTranslator (bool pass)
: m_pass (pass), m_null (false)
{
// .. nothing yet ..
}
PropertiesTranslator::PropertiesTranslator (const std::map<db::properties_id_type, db::properties_id_type> &map)
: m_map (map), m_pass (false), m_null (false)
{
// .. nothing yet ..
}
PropertiesTranslator
PropertiesTranslator::operator* (const PropertiesTranslator &other) const
{
if (other.m_pass) {
// NOTE: by handling this first, "pass_all * null" will give "pass_all" which is desired
// for RecursiveShapeIterator::apply_property_translator.
return *this;
} else if (m_pass) {
return other;
} else {
std::map<db::properties_id_type, db::properties_id_type> new_map;
for (auto i = other.m_map.begin (); i != other.m_map.end (); ++i) {
auto ii = m_map.find (i->second);
if (ii != m_map.end ()) {
new_map.insert (std::make_pair (i->first, ii->second));
}
}
return PropertiesTranslator (new_map);
}
}
db::properties_id_type
PropertiesTranslator::operator() (db::properties_id_type id) const
{
if (m_pass || id == 0) {
return id;
} else {
auto i = m_map.find (id);
return i != m_map.end () ? i->second : 0;
}
}
PropertiesTranslator
PropertiesTranslator::make_remove_all ()
{
return PropertiesTranslator (false);
}
PropertiesTranslator
PropertiesTranslator::make_pass_all ()
{
return PropertiesTranslator (true);
}
PropertiesTranslator
PropertiesTranslator::make_filter (db::PropertiesRepository &repo, const std::set<tl::Variant> &keys)
{
std::map<db::properties_id_type, db::properties_id_type> map;
std::set<db::property_names_id_type> names_selected;
for (auto k = keys.begin (); k != keys.end (); ++k) {
names_selected.insert (repo.prop_name_id (*k));
}
db::PropertiesRepository org_repo = repo;
for (auto p = org_repo.begin (); p != org_repo.end (); ++p) {
db::PropertiesRepository::properties_set new_set;
for (auto i = p->second.begin (); i != p->second.end (); ++i) {
if (names_selected.find (i->first) != names_selected.end ()) {
new_set.insert (*i);
}
}
if (! new_set.empty ()) {
map.insert (std::make_pair (p->first, repo.properties_id (new_set)));
}
}
return PropertiesTranslator (map);
}
PropertiesTranslator
PropertiesTranslator::make_key_mapper (db::PropertiesRepository &repo, const std::map<tl::Variant, tl::Variant> &keys)
{
std::map<db::properties_id_type, db::properties_id_type> map;
std::map<db::property_names_id_type, db::property_names_id_type> name_map;
for (auto k = keys.begin (); k != keys.end (); ++k) {
name_map.insert (std::make_pair (repo.prop_name_id (k->first), repo.prop_name_id (k->second)));
}
db::PropertiesRepository org_repo = repo;
for (auto p = org_repo.begin (); p != org_repo.end (); ++p) {
db::PropertiesRepository::properties_set new_set;
for (auto i = p->second.begin (); i != p->second.end (); ++i) {
auto nm = name_map.find (i->first);
if (nm != name_map.end ()) {
new_set.insert (std::make_pair (nm->second, i->second));
}
}
if (! new_set.empty ()) {
map.insert (std::make_pair (p->first, repo.properties_id (new_set)));
}
}
return PropertiesTranslator (map);
}
} // namespace db

View File

@ -63,6 +63,11 @@ public:
*/
PropertiesRepository (db::LayoutStateModel *state_model = 0);
/**
* @brief Copy constructor
*/
PropertiesRepository (const PropertiesRepository &d);
/**
* @brief Assignment
*/
@ -232,8 +237,117 @@ private:
std::map <name_value_pair, properties_id_vector> m_properties_component_table;
db::LayoutStateModel *mp_state_model;
};
PropertiesRepository (const PropertiesRepository &d);
/**
* @brief A map for selecting/translating properties
*
* The following rules apply:
* - All non-mapped properties are mapped to 0 (removed)
* - 0 is always mapped to 0
* - Do not include key or value 0 in the map passed to the constructor
*
* A "pass translator" will pass all IDs unchanged.
*
* Note that a property translator - specifically the filters and
* mappers created by "make_filter" and "make_key_mapper" - are snapshots.
* As creating new filters will generate new property IDs for the mapping
* targets, property translators generated previously may become invalid.
* In general it is safe to concatenate new translators after old ones.
* The old ones will not map the property IDs understood by the new ones,
* but as such IDs cannot become input to the old translator, this should
* not matter.
*/
class DB_PUBLIC PropertiesTranslator
{
public:
/**
* @brief Default constructor - this creates a null translator
*/
PropertiesTranslator ();
/**
* @brief Creates a "pass all" (pass = true) or "remove all" (pass = false) translator
*/
PropertiesTranslator (bool pass);
/**
* @brief Creates a property ID mapper from a table
*/
PropertiesTranslator (const std::map<db::properties_id_type, db::properties_id_type> &map);
/**
* @brief Gets a value indicating whether the translator is "pass"
*/
bool is_pass () const
{
return m_pass;
}
/**
* @brief Gets a value indicating whether the translator is "empty" (remove all)
*/
bool is_empty () const
{
return ! m_pass && m_map.empty ();
}
/**
* @brief Gets a value indicating whether the translator is "null" (default-constructed)
*/
bool is_null () const
{
return m_null;
}
/**
* @brief Concatenates two translators (the right one first)
*/
PropertiesTranslator operator* (const PropertiesTranslator &other) const;
/**
* @brief Concatenates two translators (the right one first) - in place version
*/
PropertiesTranslator &operator*= (const PropertiesTranslator &other)
{
*this = this->operator* (other);
return *this;
}
/**
* @brief Translation of the property ID
*/
db::properties_id_type operator() (db::properties_id_type id) const;
/**
* @brief Factory: create a "remove all" translator
*/
static PropertiesTranslator make_remove_all ();
/**
* @brief Factory: create a "pass all" translator
*/
static PropertiesTranslator make_pass_all ();
/**
* @brief Factory: create a filter translator
*
* The translator delivered by this function will leave only the given keys in the properties.
*/
static PropertiesTranslator make_filter (db::PropertiesRepository &repo, const std::set<tl::Variant> &keys);
/**
* @brief Factory: create a key mapper translator
*
* The translator delivered by this function will translate the given keys to new ones
* and remove non-listed keys.
*/
static PropertiesTranslator make_key_mapper (db::PropertiesRepository &repo, const std::map<tl::Variant, tl::Variant> &keys);
private:
std::map<db::properties_id_type, db::properties_id_type> m_map;
bool m_pass, m_null;
};
/**

View File

@ -0,0 +1,131 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2023 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_dbPropertyConstraint
#define HDR_dbPropertyConstraint
#include "dbCommon.h"
#include "dbTypes.h"
namespace db
{
/**
* @brief Specifies a property constraint for some operations
*/
enum PropertyConstraint
{
/**
* @brief Ignore properties
*
* In this mode, properties are not considered and erased.
*/
IgnoreProperties = 0,
/**
* @brief No constraint, shapes are processed regardless of their properties
*
* Properties are attached to the outputs where applicable.
*/
NoPropertyConstraint = 1,
/**
* @brief Shapes are processed if their properties are the same
*
* Properties are attached to the outputs where applicable.
*/
SamePropertiesConstraint = 2,
/**
* @brief Shapes are processed if their properties are the same
*
* No properties are attached to the output.
*/
SamePropertiesConstraintDrop = 3,
/**
* @brief Shapes are processed if their properties are different
*
* Properties are attached to the outputs where applicable.
*/
DifferentPropertiesConstraint = 4,
/**
* @brief Shapes are processed if their properties are different
*
* No properties are attached to the output.
*/
DifferentPropertiesConstraintDrop = 5
};
/**
* @brief Returns a predicate indicating whether properties need to be considered
*/
bool inline pc_skip (PropertyConstraint pc)
{
return pc == IgnoreProperties;
}
/**
* @brief Returns a predicate indicating whether properties are always different
*/
bool inline pc_always_different (PropertyConstraint pc)
{
return pc == DifferentPropertiesConstraint || pc == DifferentPropertiesConstraintDrop;
}
/**
* @brief Returns a value indicating whether two properties satisfy the condition
*/
bool inline pc_match (PropertyConstraint pc, db::properties_id_type a, db::properties_id_type b)
{
if (pc == SamePropertiesConstraint || pc == SamePropertiesConstraintDrop) {
return a == b;
} else if (pc == DifferentPropertiesConstraint || pc == DifferentPropertiesConstraintDrop) {
return a != b;
} else {
return true;
}
}
/**
* @brief Returns a value indicating whether the property can be removed on output
*/
bool inline pc_remove (PropertyConstraint pc)
{
return pc == IgnoreProperties || pc == SamePropertiesConstraintDrop || pc == DifferentPropertiesConstraintDrop;
}
/**
* @brief Returns a normalized property for output
*/
db::properties_id_type inline pc_norm (PropertyConstraint pc, db::properties_id_type prop_id)
{
return pc_remove (pc) ? 0 : prop_id;
}
}
#endif

View File

@ -73,6 +73,7 @@ RecursiveShapeIterator &RecursiveShapeIterator::operator= (const RecursiveShapeI
m_shape = d.m_shape;
m_trans = d.m_trans;
m_global_trans = d.m_global_trans;
m_property_translator = d.m_property_translator;
m_trans_stack = d.m_trans_stack;
m_inst_iterators = d.m_inst_iterators;
m_inst_array_iterators = d.m_inst_array_iterators;
@ -284,6 +285,7 @@ RecursiveShapeIterator::init ()
mp_cell = 0;
m_current_layer = 0;
m_global_trans = cplx_trans_type ();
m_property_translator = db::PropertiesTranslator ();
}
void

View File

@ -320,6 +320,41 @@ public:
return mp_top_cell;
}
/**
* @brief Gets the installed property translator
*
* The property translator is not automatically applied, but available to consumers
* of shapes to perform property translation.
*/
const db::PropertiesTranslator &property_translator () const
{
return m_property_translator;
}
/**
* @brief Applies a PropertyTranslator
*
* The property translator is available for receivers of the recursive shape
* iterator items. This method will apply an additional property translator
* atop of existing ones.
*/
void apply_property_translator (const db::PropertiesTranslator &pt)
{
m_property_translator = pt * m_property_translator;
}
/**
* @brief Sets a PropertyTranslator
*
* The property translator is available for receivers of the recursive shape
* iterator items. This method will apply an additional property translator
* atop of existing ones.
*/
void set_property_translator (const db::PropertiesTranslator &pt)
{
m_property_translator = pt;
}
/**
* @brief Gets the basic region the iterator is using (will be world if none is set)
* In addition to the basic region, a complex region may be defined that is further confining the
@ -648,6 +683,21 @@ public:
*/
bool at_end () const;
/**
* @brief Gets the translated property ID
*
* This version employs the property translator to deliver the real property ID.
*/
db::properties_id_type prop_id () const
{
if (m_property_translator.is_null ()) {
return 0;
} else {
validate (0);
return m_property_translator (m_shape->prop_id ());
}
}
/**
* @brief Gets the current cell's index
*/
@ -765,6 +815,7 @@ private:
bool m_overlapping;
std::set<db::cell_index_type> m_start, m_stop;
cplx_trans_type m_global_trans;
db::PropertiesTranslator m_property_translator;
tl::weak_ptr<layout_type> mp_layout;
const cell_type *mp_top_cell;

View File

@ -105,7 +105,7 @@ const db::RecursiveShapeIterator &
Region::iter () const
{
static db::RecursiveShapeIterator def_iter;
const db::RecursiveShapeIterator *i = mp_delegate->iter ();
const db::RecursiveShapeIterator *i = mp_delegate ? mp_delegate->iter () : 0;
return *(i ? i : &def_iter);
}
@ -155,9 +155,13 @@ void Region::insert (const Sh &shape)
}
template DB_PUBLIC void Region::insert (const db::Box &);
template DB_PUBLIC void Region::insert (const db::BoxWithProperties &);
template DB_PUBLIC void Region::insert (const db::SimplePolygon &);
template DB_PUBLIC void Region::insert (const db::SimplePolygonWithProperties &);
template DB_PUBLIC void Region::insert (const db::Polygon &);
template DB_PUBLIC void Region::insert (const db::PolygonWithProperties &);
template DB_PUBLIC void Region::insert (const db::Path &);
template DB_PUBLIC void Region::insert (const db::PathWithProperties &);
void Region::insert (const db::Shape &shape)
{
@ -197,35 +201,35 @@ Region::mutable_region ()
}
EdgePairs
Region::cop_to_edge_pairs (db::CompoundRegionOperationNode &node)
Region::cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{
tl_assert (node.result_type () == db::CompoundRegionOperationNode::EdgePairs);
return EdgePairs (mp_delegate->cop_to_edge_pairs (node));
return EdgePairs (mp_delegate->cop_to_edge_pairs (node, prop_constraint));
}
Region
Region::cop_to_region (db::CompoundRegionOperationNode &node)
Region::cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{
tl_assert (node.result_type () == db::CompoundRegionOperationNode::Region);
return Region (mp_delegate->cop_to_region (node));
return Region (mp_delegate->cop_to_region (node, prop_constraint));
}
Edges
Region::cop_to_edges (db::CompoundRegionOperationNode &node)
Region::cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{
tl_assert (node.result_type () == db::CompoundRegionOperationNode::Edges);
return Edges (mp_delegate->cop_to_edges (node));
return Edges (mp_delegate->cop_to_edges (node, prop_constraint));
}
tl::Variant
Region::cop (db::CompoundRegionOperationNode &node)
Region::cop (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
{
if (node.result_type () == db::CompoundRegionOperationNode::EdgePairs) {
return tl::Variant::make_variant (new EdgePairs (mp_delegate->cop_to_edge_pairs (node)));
return tl::Variant::make_variant (new EdgePairs (mp_delegate->cop_to_edge_pairs (node, prop_constraint)));
} else if (node.result_type () == db::CompoundRegionOperationNode::Edges) {
return tl::Variant::make_variant (new Edges (mp_delegate->cop_to_edges (node)));
return tl::Variant::make_variant (new Edges (mp_delegate->cop_to_edges (node, prop_constraint)));
} else if (node.result_type () == db::CompoundRegionOperationNode::Region) {
return tl::Variant::make_variant (new Region (mp_delegate->cop_to_region (node)));
return tl::Variant::make_variant (new Region (mp_delegate->cop_to_region (node, prop_constraint)));
} else {
return tl::Variant ();
}
@ -376,6 +380,8 @@ static void fill_texts (const Iter &iter, const std::string &pat, bool pattern,
const db::Layout *layout = 0;
if (org_deep) {
// NOTE: deep regions can store texts in a special way - as small boxes with a special property attached.
// The property will give the text string. This function can restore these pseudo-texts as Text objects.
layout = &org_deep->deep_layer ().layout ();
const db::DeepShapeStore *store = org_deep->deep_layer ().store ();
if (! store->text_property_name ().is_nil ()) {
@ -451,7 +457,7 @@ public:
}
}
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
virtual void push (const db::Shape &shape, db::properties_id_type, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{
bool is_text = false;
std::string text_string;
@ -494,8 +500,8 @@ public:
}
}
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Box &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Polygon &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
private:
Delivery m_delivery;

View File

@ -43,62 +43,7 @@ class DeepShapeStore;
class TransformationReducer;
class CompoundRegionOperationNode;
/**
* @brief A region iterator
*
* The iterator delivers the polygons of the region
*/
class DB_PUBLIC RegionIterator
: public generic_shape_iterator<db::Polygon>
{
public:
/**
* @brief Default constructor
*/
RegionIterator ()
: generic_shape_iterator<db::Polygon> ()
{
// .. nothing yet ..
}
/**
* @brief Constructor from a delegate
* The iterator will take ownership over the delegate
*/
RegionIterator (RegionIteratorDelegate *delegate)
: generic_shape_iterator<db::Polygon> (delegate)
{
// .. nothing yet ..
}
/**
* @brief Copy constructor and assignment
*/
RegionIterator (const RegionIterator &other)
: generic_shape_iterator<db::Polygon> (static_cast<const generic_shape_iterator<db::Polygon> &> (other))
{
// .. nothing yet ..
}
/**
* @brief Assignment
*/
RegionIterator &operator= (const RegionIterator &other)
{
generic_shape_iterator<db::Polygon>::operator= (other);
return *this;
}
/**
* @brief Increment
*/
RegionIterator &operator++ ()
{
generic_shape_iterator<db::Polygon>::operator++ ();
return *this;
}
};
typedef generic_shape_iterator<db::Polygon> RegionIterator;
typedef addressable_shape_delivery<db::Polygon> AddressablePolygonDelivery;
/**
@ -168,6 +113,15 @@ public:
insert (s);
}
/**
* @brief Constructor from a box with properties
*/
explicit Region (const db::BoxWithProperties &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from a polygon
*/
@ -177,6 +131,15 @@ public:
insert (s);
}
/**
* @brief Constructor from a polygon with properties
*/
explicit Region (const db::PolygonWithProperties &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from a simple polygon
*/
@ -186,6 +149,15 @@ public:
insert (s);
}
/**
* @brief Constructor from a simple polygon with properties
*/
explicit Region (const db::SimplePolygonWithProperties &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Constructor from a path
*/
@ -195,6 +167,15 @@ public:
insert (s);
}
/**
* @brief Constructor from a path with properties
*/
explicit Region (const db::PathWithProperties &s)
: mp_delegate (0)
{
insert (s);
}
/**
* @brief Sequence constructor
*
@ -262,7 +243,15 @@ public:
/**
* @brief Gets the underlying delegate object
*/
RegionDelegate *delegate () const
const RegionDelegate *delegate () const
{
return mp_delegate;
}
/**
* @brief Gets the underlying delegate object
*/
RegionDelegate *delegate ()
{
return mp_delegate;
}
@ -624,7 +613,7 @@ public:
* The compound operation needs to feature edge pair output, e.g.
* node.result_type() needs to be EdgePairs.
*/
EdgePairs cop_to_edge_pairs (db::CompoundRegionOperationNode &node);
EdgePairs cop_to_edge_pairs (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint = db::IgnoreProperties);
/**
* @brief Performs a compound operation rendering a region
@ -632,7 +621,7 @@ public:
* The compound operation needs to feature region output, e.g.
* node.result_type() needs to be Region.
*/
Region cop_to_region (db::CompoundRegionOperationNode &node);
Region cop_to_region (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint = db::IgnoreProperties);
/**
* @brief Performs a compound operation rendering edges
@ -640,7 +629,7 @@ public:
* The compound operation needs to feature region output, e.g.
* node.result_type() needs to be Edges.
*/
Edges cop_to_edges (db::CompoundRegionOperationNode &node);
Edges cop_to_edges (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint = db::IgnoreProperties);
/**
* @brief A universal form of the compound operation
@ -648,7 +637,7 @@ public:
* The returned variant will be of the type requested by the
* compound operation node.
*/
tl::Variant cop (db::CompoundRegionOperationNode &node);
tl::Variant cop (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint = db::IgnoreProperties);
/**
* @brief Applies a width check and returns EdgePairs which correspond to violation markers
@ -992,7 +981,15 @@ public:
*/
Region operator& (const Region &other) const
{
return Region (mp_delegate->and_with (other));
return Region (mp_delegate->and_with (other, db::IgnoreProperties));
}
/**
* @brief Boolean AND operator with options
*/
Region bool_and (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
{
return Region (mp_delegate->and_with (other, prop_constraint));
}
/**
@ -1003,7 +1000,19 @@ public:
*/
Region &operator&= (const Region &other)
{
set_delegate (mp_delegate->and_with (other));
set_delegate (mp_delegate->and_with (other, db::IgnoreProperties));
return *this;
}
/**
* @brief In-place boolean AND operator with options
*
* This method does not necessarily merge the region. To ensure the region
* is merged, call merge afterwards.
*/
Region &bool_and_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
{
set_delegate (mp_delegate->and_with (other, prop_constraint));
return *this;
}
@ -1012,7 +1021,15 @@ public:
*/
Region operator- (const Region &other) const
{
return Region (mp_delegate->not_with (other));
return Region (mp_delegate->not_with (other, db::IgnoreProperties));
}
/**
* @brief Boolean NOT operator with options
*/
Region bool_not (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
{
return Region (mp_delegate->not_with (other, prop_constraint));
}
/**
@ -1023,7 +1040,19 @@ public:
*/
Region &operator-= (const Region &other)
{
set_delegate (mp_delegate->not_with (other));
set_delegate (mp_delegate->not_with (other, db::IgnoreProperties));
return *this;
}
/**
* @brief In-place boolean NOT operator with options
*
* This method does not necessarily merge the region. To ensure the region
* is merged, call merge afterwards.
*/
Region bool_not_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
{
set_delegate (mp_delegate->not_with (other, prop_constraint));
return *this;
}
@ -1032,7 +1061,17 @@ public:
*/
Region operator^ (const Region &other) const
{
return Region (mp_delegate->xor_with (other));
return Region (mp_delegate->xor_with (other, db::IgnoreProperties));
}
/**
* @brief Boolean XOR operator with options
*
* TODO: property constraints are not implemented properly yet.
*/
Region bool_xor (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
{
return Region (mp_delegate->xor_with (other, prop_constraint));
}
/**
@ -1043,7 +1082,21 @@ public:
*/
Region &operator^= (const Region &other)
{
set_delegate (mp_delegate->xor_with (other));
set_delegate (mp_delegate->xor_with (other, db::IgnoreProperties));
return *this;
}
/**
* @brief In-place boolean XOR operator with options
*
* This method does not necessarily merge the region. To ensure the region
* is merged, call merge afterwards.
*
* TODO: property constraints are not implemented properly yet.
*/
Region &bool_xor_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
{
set_delegate (mp_delegate->xor_with (other, prop_constraint));
return *this;
}
@ -1054,7 +1107,19 @@ public:
*/
Region operator| (const Region &other) const
{
return Region (mp_delegate->or_with (other));
return Region (mp_delegate->or_with (other, db::IgnoreProperties));
}
/**
* @brief Boolean OR operator with options
*
* This method merges the polygons of both regions.
*
* TODO: property constraints are not implemented properly yet.
*/
Region bool_or (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
{
return Region (mp_delegate->or_with (other, prop_constraint));
}
/**
@ -1062,7 +1127,18 @@ public:
*/
Region &operator|= (const Region &other)
{
set_delegate (mp_delegate->or_with (other));
set_delegate (mp_delegate->or_with (other, db::IgnoreProperties));
return *this;
}
/**
* @brief In-place boolean OR operator with options
*
* TODO: property constraints are not implemented properly yet.
*/
Region &bool_or_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
{
set_delegate (mp_delegate->or_with (other, prop_constraint));
return *this;
}
@ -1090,9 +1166,9 @@ public:
*
* The first region delivered will be the AND result, the second one the NOT result.
*/
std::pair<Region, Region> andnot (const Region &other) const
std::pair<Region, Region> andnot (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
{
std::pair<RegionDelegate *, RegionDelegate *> res = mp_delegate->andnot_with (other);
std::pair<RegionDelegate *, RegionDelegate *> res = mp_delegate->andnot_with (other, prop_constraint);
return std::make_pair (Region (res.first), Region (res.second));
}
@ -1652,6 +1728,17 @@ public:
return mp_delegate->nth (n);
}
/**
* @brief Returns the nth polygon's property ID
*
* This operation is available only for flat regions - i.e. such for which
* "has_valid_polygons" is true.
*/
db::properties_id_type nth_prop_id (size_t n) const
{
return mp_delegate->nth_prop_id (n);
}
/**
* @brief Forces flattening of the region
*
@ -1743,6 +1830,20 @@ public:
return mp_delegate->insert_into (layout, into_cell, into_layer);
}
/**
* @brief Pulls the net shapes from a LayoutToNetlist database
*
* This will pull the net shapes from the LayoutToNetlist database, provided that this
* layer was an input to the netlist extraction.
*
* Netlist names will be attached as properties according to prop_mode and net_prop_name.
* A net filter can be provided so that only certain nets are produced.
*/
Region nets (LayoutToNetlist &l2n, NetPropertyMode prop_mode = db::NPM_NoProperties, const tl::Variant &net_prop_name = tl::Variant (0), const std::vector<const db::Net *> *nets = 0) const
{
return Region (mp_delegate->nets (&l2n, prop_mode, net_prop_name, nets));
}
/**
* @brief Delivers texts as dots (degenerated edges)
*

View File

@ -156,14 +156,14 @@ class DB_PUBLIC_TEMPLATE edge2edge_check
: public Edge2EdgeCheckBase
{
public:
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output), mp_output_intra (0)
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges, db::properties_id_type prop_id = 0)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output), mp_output_intra (0), m_prop_id (prop_id)
{
// .. nothing yet ..
}
edge2edge_check (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output_inter), mp_output_intra (&output_intra)
edge2edge_check (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges, db::properties_id_type prop_id = 0)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output_inter), mp_output_intra (&output_intra), m_prop_id (prop_id)
{
// .. nothing yet ..
}
@ -172,15 +172,24 @@ protected:
void put (const db::EdgePair &edge, bool inter_polygon) const
{
if (! inter_polygon || ! mp_output_intra) {
mp_output_inter->insert (edge);
if (m_prop_id != 0) {
mp_output_inter->insert (db::EdgePairWithProperties(edge, m_prop_id));
} else {
mp_output_inter->insert (edge);
}
} else {
mp_output_intra->insert (edge);
if (m_prop_id != 0) {
mp_output_intra->insert (db::EdgePairWithProperties(edge, m_prop_id));
} else {
mp_output_intra->insert (edge);
}
}
}
private:
Output *mp_output_inter;
Output *mp_output_intra;
db::properties_id_type m_prop_id;
};
/**
@ -194,16 +203,16 @@ class DB_PUBLIC_TEMPLATE edge2edge_check_with_negative_output
: public edge2edge_check<Output>
{
public:
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric_edges),
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges, db::properties_id_type prop_id = 0)
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric_edges, prop_id),
mp_l1_negative_output (&l1_negative_output),
mp_l2_negative_output (&l2_negative_output)
{
edge2edge_check<Output>::set_has_negative_edge_output (true);
}
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric_edges),
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges, db::properties_id_type prop_id = 0)
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric_edges, prop_id),
mp_l1_negative_output (&l1_negative_output),
mp_l2_negative_output (&l2_negative_output)
{
@ -272,15 +281,15 @@ class DB_PUBLIC_TEMPLATE edge2edge_check_negative_or_positive
: public edge2edge_check<Output>
{
public:
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric)
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric)
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric, db::properties_id_type prop_id = 0)
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric, prop_id)
{
edge2edge_check<Output>::set_has_negative_edge_output (negative_output);
edge2edge_check<Output>::set_has_edge_pair_output (! negative_output);
}
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric)
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric)
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric, db::properties_id_type prop_id = 0)
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric, prop_id)
{
edge2edge_check<Output>::set_has_negative_edge_output (negative_output);
edge2edge_check<Output>::set_has_edge_pair_output (! negative_output);

View File

@ -35,8 +35,10 @@
#include "dbGenericShapeIterator.h"
#include "dbRegionLocalOperations.h"
#include "dbHash.h"
#include "dbLayoutToNetlistEnums.h"
#include <list>
#include <set>
#include <unordered_set>
namespace db {
@ -46,6 +48,8 @@ class EdgeFilterBase;
class EdgesDelegate;
class EdgePairsDelegate;
class CompoundRegionOperationNode;
class LayoutToNetlist;
class Net;
/**
* @brief A base class for polygon filters
@ -192,6 +196,12 @@ public:
virtual RegionDelegate *clone () const = 0;
RegionDelegate *remove_properties (bool remove = true)
{
ShapeCollectionDelegateBase::remove_properties (remove);
return this;
}
void set_base_verbosity (int vb);
int base_verbosity () const
{
@ -237,9 +247,9 @@ public:
virtual perimeter_type perimeter (const db::Box &box) const = 0;
virtual Box bbox () const = 0;
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node) = 0;
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node) = 0;
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node) = 0;
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) = 0;
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) = 0;
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) = 0;
virtual EdgePairsDelegate *width_check (db::Coord d, const RegionCheckOptions &options) const = 0;
virtual EdgePairsDelegate *space_check (db::Coord d, const RegionCheckOptions &options) const = 0;
@ -273,13 +283,13 @@ public:
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const = 0;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const = 0;
virtual RegionDelegate *and_with (const Region &other) const = 0;
virtual RegionDelegate *not_with (const Region &other) const = 0;
virtual RegionDelegate *xor_with (const Region &other) const = 0;
virtual RegionDelegate *or_with (const Region &other) const = 0;
virtual RegionDelegate *and_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *not_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *xor_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *or_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *add_in_place (const Region &other) = 0;
virtual RegionDelegate *add (const Region &other) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &other) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
virtual RegionDelegate *selected_outside (const Region &other) const = 0;
virtual RegionDelegate *selected_not_outside (const Region &other) const = 0;
@ -311,16 +321,23 @@ public:
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out (const Region &other) const = 0;
virtual const db::Polygon *nth (size_t n) const = 0;
virtual db::properties_id_type nth_prop_id (size_t n) const = 0;
virtual bool has_valid_polygons () const = 0;
virtual bool has_valid_merged_polygons () const = 0;
virtual const db::RecursiveShapeIterator *iter () const = 0;
virtual void apply_property_translator (const db::PropertiesTranslator &pt) = 0;
virtual db::PropertiesRepository *properties_repository () = 0;
virtual const db::PropertiesRepository *properties_repository () const = 0;
virtual bool equals (const Region &other) const = 0;
virtual bool less (const Region &other) const = 0;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const = 0;
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const = 0;
const std::string &progress_desc () const
{
return m_progress_desc;

File diff suppressed because it is too large Load Diff

View File

@ -27,8 +27,11 @@
#include "dbCommon.h"
#include "dbEdgePairRelations.h"
#include "dbLocalOperation.h"
#include "dbLocalOperationUtils.h"
#include "dbEdgeProcessor.h"
#include "dbRegionCheckUtils.h"
#include "dbPropertyConstraint.h"
#include "dbLayoutUtils.h"
#include <vector>
#include <unordered_set>
@ -124,7 +127,8 @@ struct DB_PUBLIC RegionCheckOptions
bool _shielded = true,
OppositeFilter _opposite_filter = NoOppositeFilter,
RectFilter _rect_filter = NoRectFilter,
bool _negative = false)
bool _negative = false,
PropertyConstraint _prop_constraint = IgnoreProperties)
: whole_edges (_whole_edges),
metrics (_metrics),
ignore_angle (_ignore_angle),
@ -133,7 +137,8 @@ struct DB_PUBLIC RegionCheckOptions
shielded (_shielded),
opposite_filter (_opposite_filter),
rect_filter (_rect_filter),
negative (_negative)
negative (_negative),
prop_constraint (_prop_constraint)
{ }
/**
@ -198,6 +203,11 @@ struct DB_PUBLIC RegionCheckOptions
*/
bool negative;
/**
* @brief Specifies a property constraint - e.g. checking only shapes with the same properties
*/
PropertyConstraint prop_constraint;
/**
* @brief Gets a value indicating whether merged primary input is required
*/
@ -212,9 +222,28 @@ struct DB_PUBLIC RegionCheckOptions
}
};
template <class TS, class TI>
class check_local_operation_base
{
public:
check_local_operation_base (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options);
protected:
EdgeRelationFilter m_check;
bool m_different_polygons;
bool m_is_merged;
bool m_has_other;
bool m_other_is_merged;
db::RegionCheckOptions m_options;
void compute_results (db::Layout *layout, const std::vector<const TS *> &subjects, const std::set<const TI *> &intruders, std::unordered_set<db::EdgePair> &result, std::unordered_set<db::EdgePair> &intra_polygon_result) const;
void apply_opposite_filter (const std::vector<const TS *> &subjects, std::unordered_set<db::EdgePair> &result, std::unordered_set<db::EdgePair> &intra_polygon_result) const;
void apply_rectangle_filter (const std::vector<const TS *> &subjects, std::unordered_set<db::EdgePair> &result) const;
};
template <class TS, class TI>
class check_local_operation
: public local_operation<TS, TI, db::EdgePair>
: public local_operation<TS, TI, db::EdgePair>, public check_local_operation_base<TS, TI>
{
public:
check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options);
@ -225,14 +254,24 @@ public:
virtual std::string description () const;
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
};
template <class TS, class TI>
class check_local_operation_with_properties
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::EdgePairWithProperties>, public check_local_operation_base<TS, TI>
{
public:
check_local_operation_with_properties (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr);
virtual db::Coord dist () const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual bool requests_single_subjects () const { return true; }
virtual std::string description () const;
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::EdgePairWithProperties> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
private:
EdgeRelationFilter m_check;
bool m_different_polygons;
bool m_is_merged;
bool m_has_other;
bool m_other_is_merged;
db::RegionCheckOptions m_options;
mutable db::PropertyMapper m_pms, m_pmi;
};
typedef check_local_operation<db::PolygonRef, db::PolygonRef> CheckLocalOperation;
@ -371,6 +410,131 @@ typedef contained_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef
// the implementation is type-agnostic and can be used for edges too
typedef contained_local_operation<db::Edge, db::Edge, db::Edge> ContainedEdgesLocalOperation;
/**
* @brief Implements a boolean AND or NOT operation
*/
template <class TS, class TI, class TR>
class DB_PUBLIC bool_and_or_not_local_operation
: public local_operation<TS, TI, TR>
{
public:
bool_and_or_not_local_operation (bool is_and);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
private:
bool m_is_and;
};
typedef bool_and_or_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> BoolAndOrNotLocalOperation;
/**
* @brief Implements a boolean AND or NOT operation with property handling
*/
template <class TS, class TI, class TR>
class DB_PUBLIC bool_and_or_not_local_operation_with_properties
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
{
public:
bool_and_or_not_local_operation_with_properties (bool is_and, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint);
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &result, size_t max_vertex_count, double area_ratio) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
private:
bool m_is_and;
db::PropertyConstraint m_property_constraint;
mutable db::PropertyMapper m_pms;
mutable db::PropertyMapper m_pmi;
};
typedef bool_and_or_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef> BoolAndOrNotLocalOperationWithProperties;
/**
* @brief Implements a boolean AND plus NOT operation
*
* This processor delivers two outputs: the first one having the AND result, the second
* one having the NOT result.
*/
template <class TS, class TI, class TR>
class DB_PUBLIC two_bool_and_not_local_operation
: public local_operation<TS, TI, TR>
{
public:
two_bool_and_not_local_operation ();
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const;
virtual std::string description () const;
};
typedef two_bool_and_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> TwoBoolAndNotLocalOperation;
/**
* @brief Implements a boolean AND plus NOT operation
*
* This processor delivers two outputs: the first one having the AND result, the second
* one having the NOT result.
*/
template <class TS, class TI, class TR>
class DB_PUBLIC two_bool_and_not_local_operation_with_properties
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
{
public:
two_bool_and_not_local_operation_with_properties (db::PropertiesRepository *target1_pr, db::PropertiesRepository *target2_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &result, size_t max_vertex_count, double area_ratio) const;
virtual std::string description () const;
private:
db::PropertyConstraint m_property_constraint;
mutable db::PropertyMapper m_pms, m_pmi, m_pm12;
};
typedef two_bool_and_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef> TwoBoolAndNotLocalOperationWithProperties;
/**
* @brief Implements a merge operation with an overlap count
* With a given wrap_count, the result will only contains shapes where
* the original shapes overlap at least "wrap_count" times.
*/
class DB_PUBLIC SelfOverlapMergeLocalOperation
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
{
public:
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &result, size_t max_vertex_count, double area_ratio) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
private:
unsigned int m_wrap_count;
};
/**
* @brief Converts polygons to edges
*/
class DB_PUBLIC PolygonToEdgeLocalOperation
: public local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>
{
public:
PolygonToEdgeLocalOperation (db::PropertiesRepository *target_pr, const db::PropertiesRepository *source_pr);
virtual db::Coord dist () const { return 1; }
virtual bool requests_single_subjects () const { return true; }
virtual std::string description () const;
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::EdgeWithProperties> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
private:
mutable db::PropertyMapper m_pm;
};
} // namespace db
#endif

View File

@ -0,0 +1,105 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2023 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 "dbShapeCollection.h"
#include "dbPropertiesRepository.h"
namespace db
{
// -------------------------------------------------------------------------------------------------------------
DeepShapeCollectionDelegateBase::DeepShapeCollectionDelegateBase ()
{
// .. nothing yet ..
}
DeepShapeCollectionDelegateBase::DeepShapeCollectionDelegateBase (const DeepShapeCollectionDelegateBase &other)
{
m_deep_layer = other.m_deep_layer.copy ();
}
DeepShapeCollectionDelegateBase &
DeepShapeCollectionDelegateBase::operator= (const DeepShapeCollectionDelegateBase &other)
{
if (this != &other) {
m_deep_layer = other.m_deep_layer.copy ();
}
return *this;
}
void
DeepShapeCollectionDelegateBase::apply_property_translator (const db::PropertiesTranslator &pt)
{
db::Layout &layout = m_deep_layer.layout ();
for (auto c = layout.begin (); c != layout.end (); ++c) {
db::Shapes &shapes = c->shapes (m_deep_layer.layer ());
if ((shapes.type_mask () & ShapeIterator::Properties) != 0) {
// properties are present - need to translate them
db::Shapes new_shapes (shapes.is_editable ());
shapes.swap (new_shapes);
shapes.assign (new_shapes, pt);
}
}
}
// -------------------------------------------------------------------------------------------------------------
// ShapeCollection implementation
const db::PropertiesRepository &
ShapeCollection::properties_repository () const
{
static db::PropertiesRepository empty_prop_repo;
const db::PropertiesRepository *r = get_delegate () ? get_delegate ()->properties_repository () : 0;
return *(r ? r : &empty_prop_repo);
}
db::PropertiesRepository &
ShapeCollection::properties_repository ()
{
db::PropertiesRepository *r = get_delegate () ? get_delegate ()->properties_repository () : 0;
tl_assert (r != 0);
return *r;
}
bool
ShapeCollection::has_properties_repository () const
{
return get_delegate () && get_delegate ()->properties_repository ();
}
void
ShapeCollection::apply_property_translator (const db::PropertiesTranslator &pt)
{
if (get_delegate ()) {
get_delegate ()->apply_property_translator (pt);
}
}
}

View File

@ -26,31 +26,25 @@
#include "dbCommon.h"
#include "dbDeepShapeStore.h"
#include "tlUniqueId.h"
#include "tlVariant.h"
#include "gsiObject.h"
namespace db
{
class PropertiesTranslator;
class PropertiesRepository;
/**
* @brief A base class for the deep collection delegates
*/
class DB_PUBLIC DeepShapeCollectionDelegateBase
{
public:
DeepShapeCollectionDelegateBase () { }
DeepShapeCollectionDelegateBase ();
DeepShapeCollectionDelegateBase (const DeepShapeCollectionDelegateBase &other);
DeepShapeCollectionDelegateBase (const DeepShapeCollectionDelegateBase &other)
{
m_deep_layer = other.m_deep_layer.copy ();
}
DeepShapeCollectionDelegateBase &operator= (const DeepShapeCollectionDelegateBase &other)
{
if (this != &other) {
m_deep_layer = other.m_deep_layer.copy ();
}
return *this;
}
DeepShapeCollectionDelegateBase &operator= (const DeepShapeCollectionDelegateBase &other);
const db::DeepLayer &deep_layer () const
{
@ -62,6 +56,8 @@ public:
return m_deep_layer;
}
void apply_property_translator (const db::PropertiesTranslator &pt);
protected:
virtual void set_deep_layer (const db::DeepLayer &dl)
{
@ -83,6 +79,17 @@ public:
virtual ~ShapeCollectionDelegateBase () { }
virtual DeepShapeCollectionDelegateBase *deep () { return 0; }
virtual void apply_property_translator (const db::PropertiesTranslator & /*pt*/) = 0;
virtual db::PropertiesRepository *properties_repository () = 0;
virtual const db::PropertiesRepository *properties_repository () const = 0;
void remove_properties (bool remove = true)
{
if (remove) {
apply_property_translator (db::PropertiesTranslator::make_remove_all ());
}
}
};
/**
@ -96,6 +103,35 @@ public:
virtual ~ShapeCollection () { }
virtual ShapeCollectionDelegateBase *get_delegate () const = 0;
/**
* @brief Applies a PropertyTranslator
*
* This method will translate the property IDs according to the given property translator.
*
* Note that the property translator needs to be built from the PropertiesRepository
* delivered by "properties_repository".
*/
void apply_property_translator (const db::PropertiesTranslator &pt);
/**
* @brief Gets the property repository
*
* Use this object to decode and encode property IDs.
*/
db::PropertiesRepository &properties_repository ();
/**
* @brief Gets the property repository (const version)
*
* Use this object to decode property IDs.
*/
const db::PropertiesRepository &properties_repository () const;
/**
* @brief Gets a value indicating whether a properties repository is available
*/
bool has_properties_repository () const;
};
}

View File

@ -39,9 +39,9 @@
namespace db {
/**
* @brief A template base class for edge processors
* @brief A template base class for a shape processors
*
* A polygon processor can turn a edge into something else.
* A shape processor can turn a shape into something else.
*/
template <class Shape, class Result>
class DB_PUBLIC_TEMPLATE shape_collection_processor
@ -209,6 +209,7 @@ shape_collection_processed_impl (const db::DeepLayer &input, const shape_collect
}
shape_collection_processor_delivery<Result> delivery (&layout, st);
shape_collection_processor_delivery<db::object_with_properties<Result> > delivery_wp (&layout, st);
const db::ICplxTrans &tr = v->first;
db::ICplxTrans trinv = tr.inverted ();
@ -220,7 +221,11 @@ shape_collection_processed_impl (const db::DeepLayer &input, const shape_collect
heap.clear ();
filter.process (s, heap);
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
delivery.put (i->transformed (trinv));
if (si->prop_id ()) {
delivery_wp.put (db::object_with_properties<Result> (i->transformed (trinv), si->prop_id ()));
} else {
delivery.put (i->transformed (trinv));
}
}
}
@ -230,6 +235,7 @@ shape_collection_processed_impl (const db::DeepLayer &input, const shape_collect
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
shape_collection_processor_delivery<Result> delivery (&layout, &st);
shape_collection_processor_delivery<db::object_with_properties<Result> > delivery_wp (&layout, &st);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
Shape s;
@ -237,7 +243,11 @@ shape_collection_processed_impl (const db::DeepLayer &input, const shape_collect
heap.clear ();
filter.process (s, heap);
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
delivery.put (*i);
if (si->prop_id ()) {
delivery_wp.put (db::object_with_properties<Result> (*i, si->prop_id ()));
} else {
delivery.put (*i);
}
}
}

View File

@ -26,48 +26,145 @@
#include "dbCommon.h"
#include "dbShapes.h"
#include "tlSList.h"
namespace db
{
template <class T> unsigned int shape_flags ();
template <class T> unsigned int shape_flags_pure ();
template <> inline unsigned int shape_flags<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
template <> inline unsigned int shape_flags_pure<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
template <> inline unsigned int shape_flags<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
template <> inline unsigned int shape_flags_pure<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
template <> inline unsigned int shape_flags<db::Box> () { return db::ShapeIterator::Boxes; }
template <> inline unsigned int shape_flags_pure<db::Box> () { return 1 << db::ShapeIterator::Box; }
template <> inline unsigned int shape_flags<db::Path> () { return db::ShapeIterator::Paths; }
template <> inline unsigned int shape_flags_pure<db::Path> () { return 1 << db::ShapeIterator::Path; }
template <> inline unsigned int shape_flags<db::Polygon> () { return db::ShapeIterator::Polygons; }
template <> inline unsigned int shape_flags_pure<db::Polygon> () { return 1 << db::ShapeIterator::Polygon; }
template <> inline unsigned int shape_flags<db::Edge> () { return db::ShapeIterator::Edges; }
template <> inline unsigned int shape_flags_pure<db::Edge> () { return 1 << db::ShapeIterator::Edge; }
template <> inline unsigned int shape_flags<db::EdgePair> () { return db::ShapeIterator::EdgePairs; }
template <> inline unsigned int shape_flags_pure<db::EdgePair> () { return 1 << db::ShapeIterator::EdgePair; }
template <> inline unsigned int shape_flags<db::Text> () { return db::ShapeIterator::Texts; }
template <> inline unsigned int shape_flags_pure<db::Text> () { return 1 << db::ShapeIterator::Text; }
template <class T>
struct DB_PUBLIC shape_to_object
struct shape_flags_traits
{
void set (const db::Shape &) { }
const T *get (const db::Shape &s) const { return s.basic_ptr (typename T::tag ()); }
static unsigned int generic () { return 0; }
static unsigned int pure () { return 0; }
static bool with_props () { return false; }
};
template <>
struct shape_flags_traits<db::PolygonRef>
: public shape_flags_traits<void>
{
static unsigned int generic () { return 1 << db::ShapeIterator::PolygonRef; }
static unsigned int pure () { return 1 << db::ShapeIterator::PolygonRef; }
};
template <>
struct DB_PUBLIC shape_to_object<db::Polygon>
struct shape_flags_traits<db::TextRef>
: public shape_flags_traits<void>
{
static unsigned int generic () { return 1 << db::ShapeIterator::TextRef; }
static unsigned int pure () { return 1 << db::ShapeIterator::TextRef; }
};
template <>
struct shape_flags_traits<db::Box>
: public shape_flags_traits<void>
{
static unsigned int generic () { return db::ShapeIterator::Boxes; }
static unsigned int pure () { return 1 << db::ShapeIterator::Box; }
};
template <>
struct shape_flags_traits<db::Path>
: public shape_flags_traits<void>
{
static unsigned int generic () { return db::ShapeIterator::Paths; }
static unsigned int pure () { return 1 << db::ShapeIterator::Path; }
};
template <>
struct shape_flags_traits<db::Polygon>
: public shape_flags_traits<void>
{
static unsigned int generic () { return db::ShapeIterator::Regions; }
static unsigned int pure () { return 1 << db::ShapeIterator::Polygon; }
};
template <>
struct shape_flags_traits<db::SimplePolygon>
: public shape_flags_traits<void>
{
static unsigned int generic () { return db::ShapeIterator::Regions; }
static unsigned int pure () { return 1 << db::ShapeIterator::SimplePolygon; }
};
template <>
struct shape_flags_traits<db::Edge>
: public shape_flags_traits<void>
{
static unsigned int generic () { return db::ShapeIterator::Edges; }
static unsigned int pure () { return 1 << db::ShapeIterator::Edge; }
};
template <>
struct shape_flags_traits<db::EdgePair>
: public shape_flags_traits<void>
{
static unsigned int generic () { return db::ShapeIterator::EdgePairs; }
static unsigned int pure () { return 1 << db::ShapeIterator::EdgePair; }
};
template <>
struct shape_flags_traits<db::Text>
: public shape_flags_traits<void>
{
static unsigned int generic () { return db::ShapeIterator::Texts; }
static unsigned int pure () { return 1 << db::ShapeIterator::Text; }
};
template <class T>
struct shape_flags_traits<db::object_with_properties<T> >
: public shape_flags_traits<T>
{
static bool with_props () { return true; }
};
template <class T> unsigned int shape_flags () { return shape_flags_traits<T>::generic (); }
template <class T> unsigned int shape_flags_pure () { return shape_flags_traits<T>::pure (); }
template <class T> bool shape_flags_with_props () { return shape_flags_traits<T>::with_props (); }
/**
* @brief Converter helpers for changing a shape to an object of a specific type
*
* These converters a volatile. The pointer delivered is not valid after the next object has
* been retrieved.
*/
template <class T>
struct DB_PUBLIC shape_to_object_impl
{
typedef T value_type;
void set (const db::Shape &) { }
const value_type *get (const db::Shape &s) const { return s.basic_ptr (typename T::tag ()); }
};
template <class T>
struct DB_PUBLIC shape_to_object_impl<db::object_with_properties<T> >
{
typedef db::object_with_properties<T> value_type;
void set (const db::Shape &s)
{
if (! s.has_prop_id ()) {
m_shape = value_type (*s.basic_ptr (typename T::tag ()), 0);
}
}
const value_type *get (const db::Shape &s) const
{
if (! s.has_prop_id ()) {
return &m_shape;
} else {
return s.basic_ptr (typename value_type::tag ());
}
}
private:
value_type m_shape;
};
template <>
struct DB_PUBLIC shape_to_object_impl<db::Polygon>
{
typedef db::Polygon value_type;
@ -79,7 +176,27 @@ private:
};
template <>
struct DB_PUBLIC shape_to_object<db::SimplePolygon>
struct DB_PUBLIC shape_to_object_impl<db::PolygonWithProperties>
{
typedef db::PolygonWithProperties value_type;
void set (const db::Shape &s)
{
s.polygon (m_shape);
m_shape.properties_id (s.prop_id ());
}
const value_type *get (const db::Shape &) const
{
return &m_shape;
}
private:
value_type m_shape;
};
template <>
struct DB_PUBLIC shape_to_object_impl<db::SimplePolygon>
{
typedef db::SimplePolygon value_type;
@ -91,7 +208,27 @@ private:
};
template <>
struct DB_PUBLIC shape_to_object<db::Path>
struct DB_PUBLIC shape_to_object_impl<db::SimplePolygonWithProperties>
{
typedef db::SimplePolygonWithProperties value_type;
void set (const db::Shape &s)
{
s.simple_polygon (m_shape);
m_shape.properties_id (s.prop_id ());
}
const value_type *get (const db::Shape &) const
{
return &m_shape;
}
private:
value_type m_shape;
};
template <>
struct DB_PUBLIC shape_to_object_impl<db::Path>
{
typedef db::Path value_type;
@ -103,7 +240,27 @@ private:
};
template <>
struct DB_PUBLIC shape_to_object<db::Text>
struct DB_PUBLIC shape_to_object_impl<db::PathWithProperties>
{
typedef db::PathWithProperties value_type;
void set (const db::Shape &s)
{
s.path (m_shape);
m_shape.properties_id (s.prop_id ());
}
const value_type *get (const db::Shape &) const
{
return &m_shape;
}
private:
value_type m_shape;
};
template <>
struct DB_PUBLIC shape_to_object_impl<db::Text>
{
typedef db::Text value_type;
@ -115,17 +272,395 @@ private:
};
template <>
struct DB_PUBLIC shape_to_object<db::Box>
struct DB_PUBLIC shape_to_object_impl<db::TextWithProperties>
{
typedef db::TextWithProperties value_type;
void set (const db::Shape &s)
{
s.text (m_shape);
m_shape.properties_id (s.prop_id ());
}
const value_type *get (const db::Shape &) const
{
return &m_shape;
}
private:
value_type m_shape;
};
template <>
struct DB_PUBLIC shape_to_object_impl<db::Box>
{
typedef db::Box value_type;
void set (const db::Shape *s) { s->box (m_shape); }
void set (const db::Shape &s) { s.box (m_shape); }
const value_type *get (const db::Shape *) const { return &m_shape; }
private:
value_type m_shape;
};
template <>
struct DB_PUBLIC shape_to_object_impl<db::BoxWithProperties>
{
typedef db::BoxWithProperties value_type;
void set (const db::Shape &s)
{
s.box (m_shape);
m_shape.properties_id (s.prop_id ());
}
const value_type *get (const db::Shape &) const
{
return &m_shape;
}
private:
value_type m_shape;
};
template <class T>
struct DB_PUBLIC shape_to_object
: public shape_to_object_impl<T>
{
const typename shape_to_object_impl<T>::value_type &operator() (const db::Shape &s)
{
shape_to_object_impl<T>::set (s);
return *shape_to_object_impl<T>::get (s);
}
};
/**
* @brief Implements an addressable object heap
*
* This object can deliver addressable objects from shapes. It will keep temporary objects
* internally if required.
*/
template <class T>
struct addressable_object_from_shape
{
typedef T value_type;
const T *operator () (const db::Shape &shape)
{
typename T::tag object_tag;
return shape.basic_ptr (object_tag);
}
};
template <class T>
struct addressable_object_from_shape<db::object_with_properties<T> >
{
typedef db::object_with_properties<T> value_type;
const db::object_with_properties<T> *operator () (const db::Shape &shape)
{
if (shape.has_prop_id ()) {
typename db::object_with_properties<T>::tag object_tag;
return shape.basic_ptr (object_tag);
} else {
typename T::tag object_tag;
m_heap.push_back (db::object_with_properties<T> (*shape.basic_ptr (object_tag), 0));
return &m_heap.back ();
}
}
private:
tl::slist<db::object_with_properties<T> > m_heap;
};
template <>
struct addressable_object_from_shape<db::Box>
{
typedef db::Box value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.type () == db::Shape::Box) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.box (m_heap.front ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::BoxWithProperties>
{
typedef db::BoxWithProperties value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.has_prop_id () && shape.type () == db::Shape::Box) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.box (m_heap.front ());
m_heap.front ().properties_id (shape.prop_id ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::Polygon>
{
typedef db::Polygon value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.type () == db::Shape::Polygon) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.polygon (m_heap.front ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::PolygonWithProperties>
{
typedef db::PolygonWithProperties value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.has_prop_id () && shape.type () == db::Shape::Polygon) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.polygon (m_heap.front ());
m_heap.front ().properties_id (shape.prop_id ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::SimplePolygon>
{
typedef db::SimplePolygon value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.type () == db::Shape::SimplePolygon) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.simple_polygon (m_heap.front ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::SimplePolygonWithProperties>
{
typedef db::SimplePolygonWithProperties value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.has_prop_id () && shape.type () == db::Shape::SimplePolygon) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.simple_polygon (m_heap.front ());
m_heap.front ().properties_id (shape.prop_id ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::Path>
{
typedef db::Path value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.type () == db::Shape::Path) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.path (m_heap.front ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::PathWithProperties>
{
typedef db::PathWithProperties value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.has_prop_id () && shape.type () == db::Shape::Path) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.path (m_heap.front ());
m_heap.front ().properties_id (shape.prop_id ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::Edge>
{
typedef db::Edge value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.type () == db::Shape::Edge) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.edge (m_heap.front ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::EdgeWithProperties>
{
typedef db::EdgeWithProperties value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.has_prop_id () && shape.type () == db::Shape::Edge) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.edge (m_heap.front ());
m_heap.front ().properties_id (shape.prop_id ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::EdgePair>
{
typedef db::EdgePair value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.type () == db::Shape::EdgePair) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.edge_pair (m_heap.front ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::EdgePairWithProperties>
{
typedef db::EdgePairWithProperties value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.has_prop_id () && shape.type () == db::Shape::EdgePair) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.edge_pair (m_heap.front ());
m_heap.front ().properties_id (shape.prop_id ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::Text>
{
typedef db::Text value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.type () == db::Shape::Text) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.text (m_heap.front ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
template <>
struct addressable_object_from_shape<db::TextWithProperties>
{
typedef db::TextWithProperties value_type;
const value_type *operator () (const db::Shape &shape)
{
if (shape.has_prop_id () && shape.type () == db::Shape::Text) {
return shape.basic_ptr (value_type::tag ());
} else {
m_heap.push_front (value_type ());
shape.text (m_heap.front ());
m_heap.front ().properties_id (shape.prop_id ());
return &m_heap.front ();
}
}
private:
tl::slist<value_type> m_heap;
};
}
#endif

View File

@ -56,18 +56,32 @@ public:
* the start method is called and when the shape container is cleared if "clear_shapes"
* is set.
*
* @param shapes Where to store the shapes
* @param clear_shapes If true, the shapes container is cleared on the start event.
* @param prop_id The properties ID to assign to all the output shapes (or 0 if no property shall be assigned)
*/
ShapeGenerator (db::Shapes &shapes, bool clear_shapes = false)
: PolygonSink (), mp_shapes (&shapes), m_clear_shapes (clear_shapes)
ShapeGenerator (db::Shapes &shapes, bool clear_shapes = false, db::properties_id_type prop_id = 0)
: PolygonSink (), mp_shapes (&shapes), m_clear_shapes (clear_shapes), m_prop_id (prop_id)
{ }
/**
* @brief Sets the properties ID to be used for the next polygon
*/
void set_prop_id (db::properties_id_type prop_id)
{
m_prop_id = prop_id;
}
/**
* @brief Implementation of the PolygonSink interface
*/
virtual void put (const db::Polygon &polygon)
{
mp_shapes->insert (polygon);
if (m_prop_id) {
mp_shapes->insert (db::PolygonWithProperties (polygon, m_prop_id));
} else {
mp_shapes->insert (polygon);
}
}
/**
@ -85,6 +99,7 @@ public:
private:
db::Shapes *mp_shapes;
bool m_clear_shapes;
db::properties_id_type m_prop_id;
};
/**

View File

@ -469,6 +469,8 @@ template <class Trans>
Shapes::shape_type
Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_delegate_base <db::properties_id_type> &pm)
{
db::properties_id_type new_pid = shape.has_prop_id () ? pm (shape.prop_id ()) : 0;
switch (shape.m_type) {
case shape_type::Null:
default:
@ -478,10 +480,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
shape_type::polygon_type p (shape.polygon ());
// Hint: we don't compress so we don't loose information
p.transform (t, false);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::polygon_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::polygon_type> (p, new_pid));
}
}
case shape_type::PolygonRef:
@ -492,10 +494,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
// Hint: we don't compress so we don't loose information
p.transform (t, false);
// TODO: could create a reference again, but this is what a transform would to as well.
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::polygon_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::polygon_type> (p, new_pid));
}
}
case shape_type::SimplePolygon:
@ -503,10 +505,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
shape_type::simple_polygon_type p (shape.simple_polygon ());
// Hint: we don't compress so we don't loose information
p.transform (t, false);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, new_pid));
}
}
case shape_type::SimplePolygonRef:
@ -517,50 +519,50 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
// Hint: we don't compress so we don't loose information
p.transform (t, false);
// TODO: could create a reference again, but this is what a transform would to as well.
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, new_pid));
}
}
case shape_type::Edge:
{
shape_type::edge_type p (shape.edge ());
p.transform (t);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::edge_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::edge_type> (p, new_pid));
}
}
case shape_type::Point:
{
shape_type::point_type p (shape.point ());
p = t.trans (p);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::point_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::point_type> (p, new_pid));
}
}
case shape_type::EdgePair:
{
shape_type::edge_pair_type p (shape.edge_pair ());
p.transform (t);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::edge_pair_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::edge_pair_type> (p, new_pid));
}
}
case shape_type::Path:
{
shape_type::path_type p (shape.path ());
p.transform (t);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::path_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::path_type> (p, new_pid));
}
}
case shape_type::PathRef:
@ -570,10 +572,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
shape.path (p);
p.transform (t);
// TODO: could create a reference again, but this is what a transform would to as well.
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::path_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::path_type> (p, new_pid));
}
}
case shape_type::Box:
@ -584,19 +586,19 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
if (t.is_ortho ()) {
shape_type::box_type p (shape.box ());
p.transform (t);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::box_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::box_type> (p, new_pid));
}
} else {
// A box cannot stay a box in this case ...
shape_type::simple_polygon_type p (shape.box ());
p.transform (t);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, new_pid));
}
}
}
@ -604,10 +606,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
{
shape_type::text_type p (shape.text ());
p.transform (t);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::text_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::text_type> (p, new_pid));
}
}
case shape_type::TextRef:
@ -617,20 +619,20 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
shape.text (p);
p.transform (t);
// TODO: could create a reference again, but this is what a transform would to as well.
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::text_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::text_type> (p, new_pid));
}
}
case shape_type::UserObject:
{
shape_type::user_object_type p (shape.user_object ());
p.transform (t);
if (! shape.has_prop_id ()) {
if (new_pid == 0) {
return insert (p);
} else {
return insert (db::object_with_properties<shape_type::user_object_type> (p, pm (shape.prop_id ())));
return insert (db::object_with_properties<shape_type::user_object_type> (p, new_pid));
}
}
case shape_type::PolygonPtrArray:
@ -709,7 +711,7 @@ Shapes::replace_prop_id (const Shapes::shape_type &ref, db::properties_id_type p
throw tl::Exception (tl::to_string (tr ("Function 'replace_prop_id' is permitted only in editable mode")));
}
if (ref.with_props ()) {
if (ref.has_prop_id ()) {
// this assumes we can simply patch the properties ID ..
switch (ref.m_type) {
@ -1241,7 +1243,7 @@ Shapes::reinsert_member_with_props (typename db::object_tag<Sh1>, const shape_ty
}
// the shape types are not equal - resolve into erase and insert (of new)
if (! ref.with_props ()) {
if (! ref.has_prop_id ()) {
erase_shape (ref);
return insert (sh);
} else {
@ -1260,7 +1262,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh1>, const shape_typ
}
// the shape types are not equal - resolve into erase and insert (of new)
if (! ref.with_props ()) {
if (! ref.has_prop_id ()) {
erase_shape (ref);
return insert (sh);
} else {
@ -1310,7 +1312,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh> tag, const shape_
throw tl::Exception (tl::to_string (tr ("Function 'replace' is permitted only in editable mode")));
}
if (! ref.with_props ()) {
if (! ref.has_prop_id ()) {
if (manager () && manager ()->transacting ()) {
check_is_editable_for_undo_redo ();

View File

@ -787,7 +787,7 @@ public:
} else {
// translate and transform into this
for (tl::vector<LayerBase *>::const_iterator l = d.m_layers.begin (); l != d.m_layers.end (); ++l) {
(*l)->transform_into (this, shape_repository (), array_repository (), pm_delegate);
(*l)->translate_into (this, shape_repository (), array_repository (), pm_delegate);
}
}
@ -1266,7 +1266,8 @@ public:
{
size_t n = 0;
for (tl::vector<LayerBase *>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
if ((flags & (*l)->type_mask ()) != 0) {
unsigned int tm = (*l)->type_mask ();
if (((flags & db::ShapeIterator::Properties) == 0 || (tm & db::ShapeIterator::Properties) != 0) && (flags & tm) != 0) {
n += (*l)->size ();
}
}
@ -1465,6 +1466,25 @@ public:
return (db::Cell *) (size_t (mp_cell) & ~3);
}
/**
* @brief Gets a flag indicating whether an update is needed
*
* This flag means that the shape collection has been modified and the bounding box
* and the quad trees will be recomputed (internally).
*/
bool is_dirty () const
{
return (size_t (mp_cell) & 1) != 0;
}
/**
* @brief Gets a value indicating that the shape collection is constructed with editable scope
*/
bool is_editable () const
{
return (size_t (mp_cell) & 2) != 0;
}
/**
* @brief Gets the pointer to layout that the shapes container belongs to
*
@ -1472,7 +1492,7 @@ public:
*/
db::Layout *layout () const;
/**
/**
* @brief Implementation of the redo method
*/
void redo (db::Op *op);
@ -1504,18 +1524,6 @@ private:
return m_layers;
}
// extract dirty flag from mp_cell
bool is_dirty () const
{
return (size_t (mp_cell) & 1) != 0;
}
// extract editable flag from mp_cell
bool is_editable () const
{
return (size_t (mp_cell) & 2) != 0;
}
// get the shape repository associated with this container
db::GenericRepository &shape_repository () const;

View File

@ -487,7 +487,7 @@ struct translate_into_shapes
mp_shapes->insert (new_shape);
}
template <class Sh, class T>
template <class Sh>
void operator() (const db::object_with_properties<Sh> &sh)
{
Sh new_shape;
@ -495,7 +495,7 @@ struct translate_into_shapes
mp_shapes->insert (db::object_with_properties<Sh> (new_shape, sh.properties_id ()));
}
template <class Sh, class T, class PropIdMap>
template <class Sh, class PropIdMap>
void operator() (const db::object_with_properties<Sh> &sh, PropIdMap &pm)
{
Sh new_shape;
@ -755,7 +755,7 @@ inline unsigned int iterator_type_mask (ShapeIterator::user_object_type::tag)
template <class Sh>
inline unsigned int iterator_type_mask (db::object_tag< db::object_with_properties<Sh> >)
{
return iterator_type_mask (typename Sh::tag ());
return iterator_type_mask (typename Sh::tag ()) | ShapeIterator::Properties;
}
template <class Sh, class StableTag>

View File

@ -419,4 +419,24 @@ bool compare (const db::Box &box, const std::string &string)
return box.to_string () == string;
}
/**
* @brief Converts a property ID into a property key/value string representation
*/
std::string prop2string (const db::PropertiesRepository &pr, db::properties_id_type prop_id)
{
const db::PropertiesRepository::properties_set &ps = pr.properties (prop_id);
std::string res;
for (auto i = ps.begin (); i != ps.end (); ++i) {
if (i != ps.begin ()) {
res += "\n";
}
res += pr.prop_name (i->first).to_string ();
res += "=";
res += i->second.to_string ();
}
return res;
}
}

View File

@ -37,6 +37,7 @@ namespace tl
namespace db
{
class PropertiesRepository;
class Layout;
class Cell;
class LayerMap;
@ -117,6 +118,11 @@ bool DB_PUBLIC compare (const db::Texts &texts, const std::string &string);
*/
bool DB_PUBLIC compare (const db::Box &box, const std::string &string);
/**
* @brief Converts a property ID into a property key/value string representation
*/
std::string DB_PUBLIC prop2string (const db::PropertiesRepository &pr, db::properties_id_type prop_id);
}
#endif

View File

@ -146,10 +146,26 @@ const db::RecursiveShapeIterator &
Texts::iter () const
{
static db::RecursiveShapeIterator def_iter;
const db::RecursiveShapeIterator *i = mp_delegate->iter ();
const db::RecursiveShapeIterator *i = mp_delegate ? mp_delegate->iter () : 0;
return *(i ? i : &def_iter);
}
const db::PropertiesRepository &
Texts::properties_repository () const
{
static db::PropertiesRepository empty_prop_repo;
const db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
return *(r ? r : &empty_prop_repo);
}
db::PropertiesRepository &
Texts::properties_repository ()
{
db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
tl_assert (r != 0);
return *r;
}
void Texts::polygons (Region &output, db::Coord e) const
{
output.set_delegate (mp_delegate->polygons (e));

View File

@ -43,64 +43,8 @@ class Region;
class DeepShapeStore;
class TransformationReducer;
/**
* @brief An text set iterator
*
* The iterator delivers the texts of the text set
*/
class DB_PUBLIC TextsIterator
: public generic_shape_iterator<db::Text>
{
public:
/**
* @brief Default constructor
*/
TextsIterator ()
: generic_shape_iterator<db::Text> ()
{
// .. nothing yet ..
}
/**
* @brief Constructor from a delegate
* The iterator will take ownership over the delegate
*/
TextsIterator (TextsIteratorDelegate *delegate)
: generic_shape_iterator<db::Text> (delegate)
{
// .. nothing yet ..
}
/**
* @brief Copy constructor and assignment
*/
TextsIterator (const TextsIterator &other)
: generic_shape_iterator<db::Text> (static_cast<const generic_shape_iterator<db::Text> &> (other))
{
// .. nothing yet ..
}
/**
* @brief Assignment
*/
TextsIterator &operator= (const TextsIterator &other)
{
generic_shape_iterator<db::Text>::operator= (other);
return *this;
}
/**
* @brief Increment
*/
TextsIterator &operator++ ()
{
generic_shape_iterator<db::Text>::operator++ ();
return *this;
}
};
typedef addressable_shape_delivery_gen<TextsIterator> AddressableTextDelivery;
typedef generic_shape_iterator<Text> TextsIterator;
typedef addressable_shape_delivery<Text> AddressableTextDelivery;
class Texts;
@ -248,7 +192,15 @@ public:
/**
* @brief Gets the underlying delegate object
*/
TextsDelegate *delegate () const
const TextsDelegate *delegate () const
{
return mp_delegate;
}
/**
* @brief Gets the underlying delegate object
*/
TextsDelegate *delegate ()
{
return mp_delegate;
}
@ -514,7 +466,7 @@ public:
*/
AddressableTextDelivery addressable_texts () const
{
return AddressableTextDelivery (begin (), has_valid_texts ());
return AddressableTextDelivery (begin ());
}
/**
@ -524,6 +476,20 @@ public:
*/
const db::RecursiveShapeIterator &iter () const;
/**
* @brief Gets the property repository
*
* Use this object to decode property IDs.
*/
const db::PropertiesRepository &properties_repository () const;
/**
* @brief Gets the property repository
*
* Use this object to decode and encode property IDs.
*/
db::PropertiesRepository &properties_repository ();
/**
* @brief Equality
*/

View File

@ -66,6 +66,12 @@ public:
virtual TextsDelegate *clone () const = 0;
TextsDelegate *remove_properties (bool remove = true)
{
ShapeCollectionDelegateBase::remove_properties (remove);
return this;
}
void enable_progress (const std::string &progress_desc);
void disable_progress ();
@ -102,6 +108,9 @@ public:
virtual bool has_valid_texts () const = 0;
virtual const db::RecursiveShapeIterator *iter () const = 0;
virtual void apply_property_translator (const db::PropertiesTranslator &pt) = 0;
virtual db::PropertiesRepository *properties_repository () = 0;
virtual const db::PropertiesRepository *properties_repository () const = 0;
virtual bool equals (const Texts &other) const = 0;
virtual bool less (const Texts &other) const = 0;

Some files were not shown because too many files have changed in this diff Show More