WIP: reworked and implemented a property translation/selection/enabling scheme for the shape containers + GSI binding.

This commit is contained in:
Matthias Koefferlein 2023-01-19 00:25:07 +01:00
parent 500051ef1d
commit 8ac08778c2
55 changed files with 809 additions and 96 deletions

View File

@ -375,6 +375,7 @@ HEADERS = \
dbRegionUtils.h \
dbEdgesUtils.h \
dbRegionProcessors.h \
gsiDeclDbContainerHelpers.h \
gsiDeclDbHelpers.h \
dbNetlistCompare.h \
dbNetlistReader.h \

View File

@ -314,6 +314,11 @@ 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 ();

View File

@ -72,6 +72,7 @@ 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;

View File

@ -454,6 +454,11 @@ DeepEdges::iter () const
return 0;
}
void DeepEdges::apply_property_translator (const db::PropertiesTranslator &pt)
{
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
}
db::PropertiesRepository *DeepEdges::properties_repository ()
{
return &deep_layer ().layout ().properties_repository ();

View File

@ -80,6 +80,7 @@ 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;

View File

@ -475,6 +475,11 @@ DeepRegion::iter () const
return 0;
}
void DeepRegion::apply_property_translator (const db::PropertiesTranslator &pt)
{
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
}
db::PropertiesRepository *DeepRegion::properties_repository ()
{
return &deep_layer ().layout ().properties_repository ();

View File

@ -79,6 +79,7 @@ public:
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;

View File

@ -477,7 +477,6 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Region &region, bool for_n
// try to maintain the texts on top level - go through shape iterator
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = region.begin_iter ();
bool regard_props = ((ii.first.shape_flags () & db::ShapeIterator::RegardProperties) != 0);
db::ICplxTrans ttop = trans * ii.second;
// The chain of operators for producing clipped and reduced polygon references
@ -489,7 +488,7 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Region &region, bool for_n
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, regard_props ? ii.first->prop_id () : 0, ttop * ii.first.trans (), world, 0, shapes);
red.push (*ii.first, ii.first.prop_id (), ttop * ii.first.trans (), world, 0, shapes);
}
++ii.first;
@ -518,12 +517,11 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Edges &edges, const db::IC
db::Box world = db::Box::world ();
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = edges.begin_iter ();
bool regard_props = ((ii.first.shape_flags () & db::ShapeIterator::RegardProperties) != 0);
db::ICplxTrans ttop = trans * ii.second;
db::EdgeBuildingHierarchyBuilderShapeReceiver eb (&layout (), ii.first.layout (), false);
while (! ii.first.at_end ()) {
eb.push (*ii.first, regard_props ? ii.first->prop_id () : 0, ttop * ii.first.trans (), world, 0, shapes);
eb.push (*ii.first, ii.first.prop_id (), ttop * ii.first.trans (), world, 0, shapes);
++ii.first;
}
@ -549,13 +547,12 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Texts &texts, const db::IC
db::Box world = db::Box::world ();
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = texts.begin_iter ();
bool regard_props = ((ii.first.shape_flags () & db::ShapeIterator::RegardProperties) != 0);
db::ICplxTrans ttop = trans * ii.second;
db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout (), ii.first.layout ());
while (! ii.first.at_end ()) {
tb.push (*ii.first, regard_props ? ii.first->prop_id () : 0, ttop * ii.first.trans (), world, 0, shapes);
tb.push (*ii.first, ii.first.prop_id (), ttop * ii.first.trans (), world, 0, shapes);
++ii.first;
}

View File

@ -338,6 +338,11 @@ 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 ();

View File

@ -73,6 +73,7 @@ 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;

View File

@ -205,6 +205,7 @@ 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;

View File

@ -340,6 +340,7 @@ 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;

View File

@ -73,6 +73,7 @@ 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; }

View File

@ -122,6 +122,7 @@ 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; }

View File

@ -141,6 +141,7 @@ public:
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; }

View File

@ -71,6 +71,7 @@ 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; }

View File

@ -188,6 +188,13 @@ const db::RecursiveShapeIterator *FlatEdgePairs::iter () const
return 0;
}
void FlatEdgePairs::apply_property_translator (const db::PropertiesTranslator &pt)
{
db::Shapes new_edge_pairs;
new_edge_pairs.assign (*mp_edge_pairs, pt);
mp_edge_pairs->swap (new_edge_pairs);
}
db::PropertiesRepository *FlatEdgePairs::properties_repository ()
{
return mp_properties_repository.get_non_const ();

View File

@ -78,6 +78,7 @@ 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;

View File

@ -345,6 +345,13 @@ const db::RecursiveShapeIterator *FlatEdges::iter () const
return 0;
}
void FlatEdges::apply_property_translator (const db::PropertiesTranslator &pt)
{
db::Shapes new_edges;
new_edges.assign (*mp_edges, pt);
mp_edges->swap (new_edges);
}
db::PropertiesRepository *FlatEdges::properties_repository ()
{
return mp_properties_repository.get_non_const ();

View File

@ -93,6 +93,7 @@ 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;

View File

@ -419,6 +419,13 @@ const db::RecursiveShapeIterator *FlatRegion::iter () const
return 0;
}
void FlatRegion::apply_property_translator (const db::PropertiesTranslator &pt)
{
db::Shapes new_polygons;
new_polygons.assign (*mp_polygons, pt);
mp_polygons->swap (new_polygons);
}
db::PropertiesRepository *FlatRegion::properties_repository ()
{
return mp_properties_repository.get_non_const ();

View File

@ -99,6 +99,7 @@ public:
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;

View File

@ -188,6 +188,13 @@ const db::RecursiveShapeIterator *FlatTexts::iter () const
return 0;
}
void FlatTexts::apply_property_translator (const db::PropertiesTranslator &pt)
{
db::Shapes new_texts;
new_texts.assign (*mp_texts, pt);
mp_texts->swap (new_texts);
}
db::PropertiesRepository *FlatTexts::properties_repository ()
{
return mp_properties_repository.get_non_const ();

View File

@ -79,6 +79,7 @@ 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;

View File

@ -152,13 +152,13 @@ static std::pair<bool, std::set<db::Box> > compute_clip_variant (const db::Box &
}
HierarchyBuilder::HierarchyBuilder (db::Layout *target, unsigned int target_layer, const db::ICplxTrans &trans, HierarchyBuilderShapeReceiver *pipe)
: mp_target (target), m_initial_pass (true), m_ignore_properties (true), m_cm_new_entry (false), m_target_layer (target_layer), m_trans (trans)
: mp_target (target), m_initial_pass (true), m_cm_new_entry (false), m_target_layer (target_layer), m_trans (trans)
{
set_shape_receiver (pipe);
}
HierarchyBuilder::HierarchyBuilder (db::Layout *target, const db::ICplxTrans &trans, HierarchyBuilderShapeReceiver *pipe)
: mp_target (target), m_initial_pass (true), m_ignore_properties (true), m_cm_new_entry (false), m_target_layer (0), m_trans (trans)
: mp_target (target), m_initial_pass (true), m_cm_new_entry (false), m_target_layer (0), m_trans (trans)
{
set_shape_receiver (pipe);
}
@ -179,7 +179,6 @@ HierarchyBuilder::reset ()
{
m_initial_pass = true;
mp_initial_cell = 0;
m_ignore_properties = true;
m_cells_to_be_filled.clear ();
m_cell_map.clear ();
@ -245,8 +244,6 @@ HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
tl_assert (compare_iterators_with_respect_to_target_hierarchy (m_source, *iter) == 0);
}
m_ignore_properties = ((iter->shape_flags () & db::ShapeIterator::RegardProperties) == 0);
m_cell_stack.clear ();
m_cells_seen.clear ();
@ -278,7 +275,6 @@ HierarchyBuilder::end (const RecursiveShapeIterator *iter)
{
tl_assert (! iter->layout () || ! iter->top_cell () || m_cell_stack.size () == 1);
m_ignore_properties = true;
m_initial_pass = false;
m_cells_seen.clear ();
mp_initial_cell = m_cell_stack.empty () ? 0 : m_cell_stack.front ().second.front ();
@ -411,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_ignore_properties ? 0 : shape.prop_id (), m_trans * apply_always, region, complex_region, &shapes);
mp_pipe->push (shape, iter->prop_id (), m_trans * apply_always, region, complex_region, &shapes);
}
}

View File

@ -406,7 +406,6 @@ private:
tl::weak_ptr<db::Layout> mp_target;
HierarchyBuilderShapeReceiver *mp_pipe;
bool m_initial_pass;
bool m_ignore_properties;
db::RecursiveShapeIterator m_source;
cell_map_type m_cell_map;
original_target_to_variants_map_type m_original_targets_to_variants_map;

View File

@ -115,7 +115,7 @@ namespace
if (! m_rec_iter.at_end ()) {
m_rec_iter->edge_pair (m_shape);
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::RegardProperties) != 0 ? m_rec_iter->prop_id () : 0;
m_prop_id = m_rec_iter.prop_id ();
}
}
@ -202,6 +202,12 @@ 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 ()
{

View File

@ -56,6 +56,7 @@ 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;

View File

@ -116,7 +116,7 @@ namespace
if (! m_rec_iter.at_end ()) {
m_rec_iter->edge (m_shape);
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::RegardProperties) != 0 ? m_rec_iter->prop_id () : 0;
m_prop_id = m_rec_iter.prop_id ();
}
}
@ -251,6 +251,12 @@ OriginalLayerEdges::iter () const
return &m_iter;
}
void
OriginalLayerEdges::apply_property_translator (const db::PropertiesTranslator &pt)
{
m_iter.apply_property_translator (pt);
}
db::PropertiesRepository *
OriginalLayerEdges::properties_repository ()
{

View File

@ -62,6 +62,7 @@ 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;

View File

@ -119,7 +119,7 @@ namespace
if (! m_rec_iter.at_end ()) {
m_rec_iter->polygon (m_polygon);
m_polygon.transform (m_iter_trans * m_rec_iter.trans (), false);
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::RegardProperties) != 0 ? m_rec_iter->prop_id () : 0;
m_prop_id = m_rec_iter.prop_id ();
}
}
@ -369,6 +369,12 @@ OriginalLayerRegion::iter () const
return &m_iter;
}
void
OriginalLayerRegion::apply_property_translator (const db::PropertiesTranslator &pt)
{
m_iter.apply_property_translator (pt);
}
db::PropertiesRepository *
OriginalLayerRegion::properties_repository ()
{

View File

@ -67,6 +67,7 @@ public:
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;

View File

@ -115,7 +115,7 @@ namespace
if (! m_rec_iter.at_end ()) {
m_rec_iter->text (m_shape);
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
m_prop_id = (m_rec_iter.shape_flags () & db::ShapeIterator::RegardProperties) != 0 ? m_rec_iter->prop_id () : 0;
m_prop_id = m_rec_iter.prop_id ();
}
}
@ -202,6 +202,12 @@ 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 ()
{

View File

@ -56,6 +56,7 @@ 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;

View File

@ -213,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

@ -239,6 +239,117 @@ private:
db::LayoutStateModel *mp_state_model;
};
/**
* @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;
};
/**
* @brief Collect memory statistics
*/

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

@ -109,22 +109,6 @@ Region::iter () const
return *(i ? i : &def_iter);
}
const db::PropertiesRepository &
Region::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 &
Region::properties_repository ()
{
db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
tl_assert (r != 0);
return *r;
}
void
Region::set_delegate (RegionDelegate *delegate, bool keep_attributes)
{
@ -396,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 ()) {

View File

@ -1796,20 +1796,6 @@ 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

@ -316,6 +316,8 @@ public:
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;

View File

@ -0,0 +1,93 @@
/*
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 ());
db::Shapes new_shapes;
new_shapes.assign (shapes, pt);
shapes.swap (new_shapes);
}
}
// -------------------------------------------------------------------------------------------------------------
// 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;
}
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,10 @@ 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;
};
/**
@ -96,6 +96,30 @@ 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;
};
}

View File

@ -171,7 +171,6 @@ public:
Properties = (1 << Null),
All = (1 << Null) - 1,
AllWithProperties = (1 << (Null + 1)) - 1,
RegardProperties = (1 << (Null + 1)), // special flag, not evaluated on query but in receiver (indicates to regard shapes with different properties as different entities)
Nothing = 0
};

View File

@ -102,6 +102,7 @@ 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;

View File

@ -0,0 +1,101 @@
/*
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_gsiDeclDbContainerHelpers
#define HDR_gsiDeclDbContainerHelpers
#include "dbPropertiesRepository.h"
#include "tlVariant.h"
#include "gsiDecl.h"
#include <vector>
#include <map>
namespace gsi
{
template <class Container>
static void enable_properties (Container *c)
{
c->apply_property_translator (db::PropertiesTranslator::make_pass_all ());
}
template <class Container>
static void remove_properties (Container *c)
{
c->apply_property_translator (db::PropertiesTranslator::make_remove_all ());
}
template <class Container>
static void filter_properties (Container *c, const std::vector<tl::Variant> &keys)
{
std::set<tl::Variant> kf;
kf.insert (keys.begin (), keys.end ());
c->apply_property_translator (db::PropertiesTranslator::make_filter (c->properties_repository (), kf));
}
template <class Container>
static void map_properties (Container *c, const std::map<tl::Variant, tl::Variant> &map)
{
c->apply_property_translator (db::PropertiesTranslator::make_key_mapper (c->properties_repository (), map));
}
template <class Container>
static gsi::Methods
make_property_methods ()
{
return
gsi::method_ext ("enable_properties", &enable_properties<Container>,
"@brief Enables properties for the given container.\n"
"This method has an effect mainly on original layers and will import properties from such layers. "
"By default, properties are not enabled on original layers. Alternatively you can apply \\filter_properties "
"or \\map_properties to enable properties with a specific name key.\n"
"\n"
"This method has been introduced in version 0.28.4."
) +
gsi::method_ext ("remove_properties", &remove_properties<Container>,
"@brief Removes properties for the given container.\n"
"This will remove all properties on the given container.\n"
"\n"
"This method has been introduced in version 0.28.4."
) +
gsi::method_ext ("filter_properties", &filter_properties<Container>, gsi::arg ("keys"),
"@brief Filters properties by certain keys.\n"
"Calling this method on a container will reduce the properties to values with name keys from the 'keys' list.\n"
"As a side effect, this method enables properties on original layers.\n"
"\n"
"This method has been introduced in version 0.28.4."
) +
gsi::method_ext ("map_properties", &map_properties<Container>, gsi::arg ("key_map"),
"@brief Maps properties by name key.\n"
"Calling this method on a container will reduce the properties to values with name keys from the 'keys' hash and "
"renames the properties. Properties not listed in the key map will be removed.\n"
"As a side effect, this method enables properties on original layers.\n"
"\n"
"This method has been introduced in version 0.28.4."
);
}
}
#endif

View File

@ -31,6 +31,8 @@
#include "dbEdgesUtils.h"
#include "dbEdgePairFilters.h"
#include "gsiDeclDbContainerHelpers.h"
namespace gsi
{
@ -912,7 +914,9 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
method_ext ("to_s", &to_string1, gsi::arg ("max_count"),
"@brief Converts the edge pair collection to a string\n"
"This version allows specification of the maximum number of edge pairs contained in the string."
),
) +
gsi::make_property_methods<db::EdgePairs> ()
,
"@brief EdgePairs (a collection of edge pairs)\n"
"\n"
"Edge pairs are used mainly in the context of the DRC functions (width_check, space_check etc.) of \\Region and \\Edges. "

View File

@ -32,6 +32,8 @@
#include "dbOriginalLayerRegion.h"
#include "dbLayoutUtils.h"
#include "gsiDeclDbContainerHelpers.h"
namespace gsi
{
@ -1750,7 +1752,9 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
method ("disable_progress", &db::Edges::disable_progress,
"@brief Disable progress reporting\n"
"Calling this method will disable progress reporting. See \\enable_progress.\n"
),
) +
gsi::make_property_methods<db::Edges> ()
,
"@brief A collection of edges (Not necessarily describing closed contours)\n"
"\n\n"
"This class was introduced to simplify operations on edges sets. "

View File

@ -37,6 +37,8 @@
#include "dbCompoundOperation.h"
#include "tlGlobPattern.h"
#include "gsiDeclDbContainerHelpers.h"
#include <memory>
#include <vector>
#include <set>
@ -3030,7 +3032,9 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
"\n"
"This method has been introduced in version 0.27.\n"
),
) +
gsi::make_property_methods<db::Region> ()
,
"@brief A region (a potentially complex area consisting of multiple polygons)\n"
"\n\n"
"This class was introduced to simplify operations on polygon sets like boolean or sizing operations. "

View File

@ -448,7 +448,6 @@ static db::Layout *layout (db::Shapes *sh)
static unsigned int s_all () { return db::ShapeIterator::All; }
static unsigned int s_all_with_properties () { return db::ShapeIterator::AllWithProperties; }
static unsigned int s_regard_properties () { return db::ShapeIterator::RegardProperties; }
static unsigned int s_properties () { return db::ShapeIterator::Properties; }
static unsigned int s_polygons () { return db::ShapeIterator::Polygons; }
static unsigned int s_regions () { return db::ShapeIterator::Regions; }
@ -1336,10 +1335,6 @@ Class<db::Shapes> decl_Shapes ("db", "Shapes",
gsi::method ("SProperties|#s_properties", &s_properties,
"@brief Indicates that only shapes with properties shall be retrieved"
) +
gsi::method ("SRegardProperties|#s_regard_properties", &s_regard_properties,
"@brief Special option to regard shapes with different properties as different entities (used by \\Region for example).\n"
"This option has been introduced in version 0.28.4.\n"
) +
gsi::method_ext ("dump_mem_statistics", &dump_mem_statistics, gsi::arg<bool> ("detailed", false),
"@hide"
),

View File

@ -28,6 +28,8 @@
#include "dbDeepTexts.h"
#include "dbTextsUtils.h"
#include "gsiDeclDbContainerHelpers.h"
namespace gsi
{
@ -506,7 +508,9 @@ Class<db::Texts> decl_Texts (decl_dbShapeCollection, "db", "Texts",
method_ext ("to_s", &to_string1, gsi::arg ("max_count"),
"@brief Converts the text collection to a string\n"
"This version allows specification of the maximum number of texts contained in the string."
),
) +
gsi::make_property_methods<db::Texts> ()
,
"@brief Texts (a collection of texts)\n"
"\n"
"Text objects are useful as labels for net names, to identify certain regions and to specify specific locations in general. "

View File

@ -1660,15 +1660,15 @@ TEST(40_BoolWithProperties)
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1 (si1);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2 (si2);
db::RecursiveShapeIterator si3 (ly, top_cell, l3);
si3.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si3.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r3 (si3);
db::Layout target;
@ -1735,7 +1735,7 @@ TEST(41_EdgesWithProperties)
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1wp (si1);
db::Region r1wp_nomerge = r1wp;
r1wp_nomerge.set_merged_semantics (false);
@ -1744,7 +1744,7 @@ TEST(41_EdgesWithProperties)
db::Region r1 (si1);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2wp (si2);
db::Region r2wp_nomerge = r2wp;
r2wp_nomerge.set_merged_semantics (false);
@ -1788,13 +1788,13 @@ TEST(42_DRCWithProperties)
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1 (si1);
db::Region r1_nomerge (r1);
r1_nomerge.set_merged_semantics (false);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2 (si2);
db::Region r2_nomerge (r2);
r2_nomerge.set_merged_semantics (false);
@ -1857,11 +1857,11 @@ TEST(43_ComplexOpsWithProperties)
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1 (si1);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2 (si2);
db::Layout target;
@ -1922,11 +1922,11 @@ TEST(44_SizeWithProperties)
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1 (si1);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2 (si2);
db::Layout target;

View File

@ -2148,15 +2148,15 @@ TEST(40_BoolWithProperties)
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1 (si1, dss);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2 (si2, dss);
db::RecursiveShapeIterator si3 (ly, top_cell, l3);
si3.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si3.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r3 (si3, dss);
db::Layout target;
@ -2225,7 +2225,7 @@ TEST(41_EdgesWithProperties)
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1wp (si1, dss);
db::Region r1wp_nomerge = r1wp;
r1wp_nomerge.set_merged_semantics (false);
@ -2234,7 +2234,7 @@ TEST(41_EdgesWithProperties)
db::Region r1 (si1, dss);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2wp (si2, dss);
db::Region r2wp_nomerge = r2wp;
r2wp_nomerge.set_merged_semantics (false);
@ -2280,13 +2280,13 @@ TEST(42_DRCWithProperties)
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1 (si1, dss);
db::Region r1_nomerge (r1);
r1_nomerge.set_merged_semantics (false);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2 (si2, dss);
db::Region r2_nomerge (r2);
r2_nomerge.set_merged_semantics (false);
@ -2351,11 +2351,11 @@ TEST(43_ComplexOpsWithProperties)
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1 (si1, dss);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2 (si2, dss);
db::Layout target;
@ -2418,11 +2418,11 @@ TEST(44_SizeWithProperties)
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::RecursiveShapeIterator si1 (ly, top_cell, l1);
si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si1.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r1 (si1, dss);
db::RecursiveShapeIterator si2 (ly, top_cell, l2);
si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
si2.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
db::Region r2 (si2, dss);
db::Layout target;

View File

@ -22,6 +22,7 @@
#include "dbPropertiesRepository.h"
#include "dbTestSupport.h"
#include "tlString.h"
#include "tlUnitTest.h"
@ -259,3 +260,135 @@ TEST(6)
EXPECT_EQ (pid2, size_t (2));
}
TEST(10_PropertiesTranslator)
{
EXPECT_EQ (db::PropertiesTranslator ().is_null (), true);
EXPECT_EQ (db::PropertiesTranslator ().is_pass (), true);
EXPECT_EQ (db::PropertiesTranslator ().is_empty (), false);
EXPECT_EQ (db::PropertiesTranslator::make_pass_all ().is_null (), false);
EXPECT_EQ (db::PropertiesTranslator::make_pass_all ().is_pass (), true);
EXPECT_EQ (db::PropertiesTranslator::make_pass_all ().is_empty (), false);
EXPECT_EQ (db::PropertiesTranslator::make_remove_all ().is_null (), false);
EXPECT_EQ (db::PropertiesTranslator::make_remove_all ().is_pass (), false);
EXPECT_EQ (db::PropertiesTranslator::make_remove_all ().is_empty (), true);
db::PropertiesRepository rp;
db::property_names_id_type key1 = rp.prop_name_id (1);
db::property_names_id_type key2 = rp.prop_name_id (2);
db::property_names_id_type key3 = rp.prop_name_id (3);
db::PropertiesRepository::properties_set ps;
ps.insert (std::make_pair (key1, 100));
ps.insert (std::make_pair (key2, 101));
db::properties_id_type prop1a = rp.properties_id (ps);
EXPECT_EQ (prop2string (rp, prop1a), "1=100\n2=101");
ps.clear ();
ps.insert (std::make_pair (key1, 0));
ps.insert (std::make_pair (key2, 101));
db::properties_id_type prop1b = rp.properties_id (ps);
EXPECT_EQ (prop2string (rp, prop1b), "1=0\n2=101");
ps.clear ();
ps.insert (std::make_pair (key1, 100));
ps.insert (std::make_pair (key3, 102));
db::properties_id_type prop2 = rp.properties_id (ps);
EXPECT_EQ (prop2string (rp, prop2), "1=100\n3=102");
ps.clear ();
ps.insert (std::make_pair (key1, 100));
db::properties_id_type prop3 = rp.properties_id (ps);
EXPECT_EQ (prop2string (rp, prop3), "1=100");
db::PropertiesRepository rp_org = rp;
db::PropertiesTranslator t;
EXPECT_EQ (prop2string (rp, t (prop1a)), "1=100\n2=101");
EXPECT_EQ (prop2string (rp, t (prop1b)), "1=0\n2=101");
EXPECT_EQ (prop2string (rp, t (prop2)), "1=100\n3=102");
EXPECT_EQ (prop2string (rp, t (prop3)), "1=100");
t = db::PropertiesTranslator::make_pass_all ();
EXPECT_EQ (prop2string (rp, t (prop1a)), "1=100\n2=101");
EXPECT_EQ (prop2string (rp, t (prop1b)), "1=0\n2=101");
EXPECT_EQ (prop2string (rp, t (prop2)), "1=100\n3=102");
EXPECT_EQ (prop2string (rp, t (prop3)), "1=100");
t = db::PropertiesTranslator::make_remove_all ();
EXPECT_EQ (prop2string (rp, t (prop1a)), "");
EXPECT_EQ (prop2string (rp, t (prop1b)), "");
EXPECT_EQ (prop2string (rp, t (prop2)), "");
EXPECT_EQ (prop2string (rp, t (prop3)), "");
std::set<tl::Variant> kf;
kf.insert (1);
t = db::PropertiesTranslator::make_filter (rp, kf);
EXPECT_EQ (prop2string (rp, t (prop1a)), "1=100");
EXPECT_EQ (prop2string (rp, t (prop1b)), "1=0");
EXPECT_EQ (prop2string (rp, t (prop2)), "1=100");
EXPECT_EQ (prop2string (rp, t (prop3)), "1=100");
kf.insert (3);
t = db::PropertiesTranslator::make_filter (rp, kf);
EXPECT_EQ (prop2string (rp, t (prop1a)), "1=100");
EXPECT_EQ (prop2string (rp, t (prop1b)), "1=0");
EXPECT_EQ (prop2string (rp, t (prop2)), "1=100\n3=102");
EXPECT_EQ (prop2string (rp, t (prop3)), "1=100");
std::map<tl::Variant, tl::Variant> km;
km[1] = 4;
km[3] = 1;
t = db::PropertiesTranslator::make_key_mapper (rp, km);
EXPECT_EQ (prop2string (rp, t (prop1a)), "4=100");
EXPECT_EQ (prop2string (rp, t (prop1b)), "4=0");
EXPECT_EQ (prop2string (rp, t (prop2)), "1=102\n4=100");
EXPECT_EQ (prop2string (rp, t (prop3)), "4=100");
kf.clear ();
kf.insert (4);
t = db::PropertiesTranslator::make_filter (rp, kf) * db::PropertiesTranslator::make_key_mapper (rp, km);
EXPECT_EQ (t.is_empty (), false);
EXPECT_EQ (prop2string (rp, t (prop1a)), "4=100");
EXPECT_EQ (prop2string (rp, t (prop1b)), "4=0");
EXPECT_EQ (prop2string (rp, t (prop2)), "4=100");
EXPECT_EQ (prop2string (rp, t (prop3)), "4=100");
kf.clear ();
kf.insert (3);
t = db::PropertiesTranslator::make_filter (rp, kf) * db::PropertiesTranslator::make_key_mapper (rp, km);
EXPECT_EQ (t.is_empty (), true);
EXPECT_EQ (prop2string (rp, t (prop1a)), "");
EXPECT_EQ (prop2string (rp, t (prop1b)), "");
EXPECT_EQ (prop2string (rp, t (prop2)), "");
EXPECT_EQ (prop2string (rp, t (prop3)), "");
t = db::PropertiesTranslator::make_key_mapper (rp, km) * db::PropertiesTranslator::make_filter (rp, kf);
EXPECT_EQ (t.is_empty (), false);
EXPECT_EQ (prop2string (rp, t (prop1a)), "");
EXPECT_EQ (prop2string (rp, t (prop1b)), "");
EXPECT_EQ (prop2string (rp, t (prop2)), "1=102");
EXPECT_EQ (prop2string (rp, t (prop3)), "");
rp = rp_org;
t = db::PropertiesTranslator::make_key_mapper (rp, km);
t = db::PropertiesTranslator::make_filter (rp, kf) * t;
EXPECT_EQ (t.is_empty (), true);
EXPECT_EQ (prop2string (rp, t (prop1a)), "");
EXPECT_EQ (prop2string (rp, t (prop1b)), "");
EXPECT_EQ (prop2string (rp, t (prop2)), "");
EXPECT_EQ (prop2string (rp, t (prop3)), "");
rp = rp_org;
t = db::PropertiesTranslator::make_filter (rp, kf);
t = db::PropertiesTranslator::make_key_mapper (rp, km) * t;
EXPECT_EQ (t.is_empty (), false);
EXPECT_EQ (prop2string (rp, t (prop1a)), "");
EXPECT_EQ (prop2string (rp, t (prop1b)), "");
EXPECT_EQ (prop2string (rp, t (prop2)), "1=102");
EXPECT_EQ (prop2string (rp, t (prop3)), "");
}

View File

@ -2153,7 +2153,7 @@ TEST(51_PropertiesFlatFromLayout)
// NOTE: now with regarding properties
rsi = db::RecursiveShapeIterator (ly, top, li);
rsi.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
rsi.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
r = db::Region (rsi);
EXPECT_EQ (r.count (), size_t (4));
@ -2340,7 +2340,7 @@ TEST(53_PropertiesDeepFromLayout)
// NOTE: now with regarding properties
rsi = db::RecursiveShapeIterator (ly, top, li);
rsi.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties);
rsi.apply_property_translator (db::PropertiesTranslator::make_pass_all ());
r = db::Region (rsi, dss);
EXPECT_EQ (r.count (), size_t (4));