Merge pull request #403 from KLayout/issue_400

Issue 400
This commit is contained in:
Matthias Köfferlein 2019-11-08 23:26:04 +01:00 committed by GitHub
commit f2bfa1522b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1037 additions and 135 deletions

View File

@ -31,7 +31,21 @@
* Enhancement: %GITHUB%/issues/393
DRC syntax errors are now shown in their original code line
of the DRC script.
* Enhancement: New Region#pull_* methods and DRC features
* Bugfix: %GITHUB%/issues/400
Snap feature wasn't working for deep regions in certain use
cases.
* Enhancement: new "scale_and_snap" methods
These methods allow scaling and snapping of layouts. Scaling
is supported by a rational factor. After scaling, snapping can
be applied to an integer grid. There are two incarnations.
Region#scale_and_snap (or Region#scaled_and_snapped): this is
a flat implementation which allows anisotropic scaling/snapping
as well.
And there is Layout#scale_and_snap which is a fully
hierarchical scale-and-snap feature. The latter does not support
anisotropic scaling/snapping, but works hierarchically without
opening gaps. It operates on a top cell and on all layers.
* Enhancement: new Region#pull_* methods and DRC features
"pull_*" is a class of methods that allows rehierarchisation
of shapes. These methods act similar to "interacting", but
the other way around: instead of delivering interacting

View File

@ -632,56 +632,11 @@ AsIfFlatRegion::angle_check (double min, double max, bool inverse) const
return res.release ();
}
static inline db::Coord snap_to_grid (db::Coord c, db::Coord g)
{
// This form of snapping always snaps g/2 to right/top.
if (c < 0) {
c = -g * ((-c + (g - 1) / 2) / g);
} else {
c = g * ((c + g / 2) / g);
}
return c;
}
db::Polygon
AsIfFlatRegion::snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap)
{
db::Polygon pnew;
for (size_t i = 0; i < poly.holes () + 1; ++i) {
heap.clear ();
db::Polygon::polygon_contour_iterator b, e;
if (i == 0) {
b = poly.begin_hull ();
e = poly.end_hull ();
} else {
b = poly.begin_hole ((unsigned int) (i - 1));
e = poly.end_hole ((unsigned int) (i - 1));
}
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
heap.push_back (db::Point (snap_to_grid ((*pt).x (), gx), snap_to_grid ((*pt).y (), gy)));
}
if (i == 0) {
pnew.assign_hull (heap.begin (), heap.end ());
} else {
pnew.insert_hole (heap.begin (), heap.end ());
}
}
return pnew;
}
RegionDelegate *
AsIfFlatRegion::snapped (db::Coord gx, db::Coord gy)
{
if (gx < 0 || gy < 0) {
throw tl::Exception (tl::to_string (tr ("Grid check requires a positive grid value")));
throw tl::Exception (tl::to_string (tr ("Grid snap requires a positive grid value")));
}
std::auto_ptr<FlatRegion> new_region (new FlatRegion (merged_semantics ()));
@ -698,6 +653,31 @@ AsIfFlatRegion::snapped (db::Coord gx, db::Coord gy)
return new_region.release ();
}
RegionDelegate *
AsIfFlatRegion::scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy)
{
if (gx < 0 || gy < 0) {
throw tl::Exception (tl::to_string (tr ("Grid snap requires a positive grid value")));
}
if (mx <= 0 || dx <= 0 || my <= 0 || dy <= 0) {
throw tl::Exception (tl::to_string (tr ("Scale and snap requires positive and non-null magnification or divisor values")));
}
std::auto_ptr<FlatRegion> new_region (new FlatRegion (merged_semantics ()));
gx = std::max (db::Coord (1), gx);
gy = std::max (db::Coord (1), gy);
std::vector<db::Point> heap;
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
new_region->raw_polygons ().insert (scaled_and_snapped_polygon (*p, gx, mx, dx, 0, gy, my, dy, 0, heap));
}
return new_region.release ();
}
EdgePairsDelegate *
AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{

View File

@ -105,6 +105,13 @@ public:
virtual RegionDelegate *snapped (db::Coord gx, db::Coord gy);
virtual RegionDelegate *scaled_and_snapped_in_place (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy)
{
return scaled_and_snapped (gx, mx, dx, gy, my, dy);
}
virtual RegionDelegate *scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy);
virtual EdgesDelegate *edges (const EdgeFilterBase *) const;
virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter)
@ -247,7 +254,6 @@ protected:
static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);
template <class Trans>
static void produce_markers_for_angle_check (const db::Polygon &poly, const Trans &tr, double min, double max, bool inverse, db::Shapes &shapes);
static db::Polygon snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap);
private:
AsIfFlatRegion &operator= (const AsIfFlatRegion &other);

View File

@ -295,9 +295,26 @@ CellMapping::create_from_names (const db::Layout &layout_a, db::cell_index_type
}
std::vector<db::cell_index_type>
CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /*cell_index_a*/, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells)
CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells)
{
std::vector<db::cell_index_type> new_cells;
do_create_missing_mapping (layout_a, cell_index_a, layout_b, cell_index_b, exclude_cells, include_cells, &new_cells, 0);
return new_cells;
}
std::vector<std::pair<db::cell_index_type, db::cell_index_type> >
CellMapping::create_missing_mapping2 (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells)
{
std::vector<std::pair<db::cell_index_type, db::cell_index_type> > cell_pairs;
do_create_missing_mapping (layout_a, cell_index_a, layout_b, cell_index_b, exclude_cells, include_cells, 0, &cell_pairs);
return cell_pairs;
}
void
CellMapping::do_create_missing_mapping (db::Layout &layout_a, db::cell_index_type /*cell_index_a*/, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells, std::vector<db::cell_index_type> *new_cells_ptr, std::vector<std::pair<db::cell_index_type, db::cell_index_type> > *mapped_pairs)
{
std::vector<db::cell_index_type> new_cells_int;
std::vector<db::cell_index_type> &new_cells = *(new_cells_ptr ? new_cells_ptr : &new_cells_int);
std::vector<db::cell_index_type> new_cells_b;
std::set<db::cell_index_type> called_b;
@ -308,10 +325,17 @@ CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /
if (m_b2a_mapping.find (*b) == m_b2a_mapping.end ()
&& (! exclude_cells || exclude_cells->find (*b) == exclude_cells->end ())
&& (! include_cells || include_cells->find (*b) != include_cells->end ())) {
db::cell_index_type new_cell = layout_a.add_cell (layout_b.cell_name (*b));
new_cells.push_back (new_cell);
new_cells_b.push_back (*b);
if (mapped_pairs) {
mapped_pairs->push_back (std::make_pair (*b, new_cell));
}
map (*b, new_cell);
}
}
@ -355,8 +379,6 @@ CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /
layout_a.end_changes ();
}
return new_cells;
}
void

View File

@ -197,6 +197,14 @@ public:
*/
std::vector<db::cell_index_type> create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0, const std::set<db::cell_index_type> *include_cells = 0);
/**
* @brief Like create_missing_mapping, but returns the newly mapped pairs
*
* The first cell index of the pair is the old cell in layout_a, the second cell index
* is the new cell in layout_b.
*/
std::vector<std::pair<db::cell_index_type, db::cell_index_type> > create_missing_mapping2 (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0, const std::set<db::cell_index_type> *include_cells = 0);
private:
void extract_unique (std::map <db::cell_index_type, std::vector<db::cell_index_type> >::const_iterator cand,
std::map<db::cell_index_type, db::cell_index_type> &unique_mapping,
@ -205,6 +213,8 @@ private:
void dump_mapping (const std::map <db::cell_index_type, std::vector<db::cell_index_type> > &candidates,
const db::Layout &layout_a, const db::Layout &layout_b);
void do_create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells, std::vector<db::cell_index_type> *new_cells, std::vector<std::pair<db::cell_index_type, db::cell_index_type> > *mapped_pairs);
std::map <db::cell_index_type, db::cell_index_type> m_b2a_mapping;
};

View File

@ -22,11 +22,124 @@
#include "dbCellVariants.h"
#include "dbRegionUtils.h"
#include "tlUtils.h"
namespace db
{
// ------------------------------------------------------------------------------------------
db::ICplxTrans OrientationReducer::reduce (const db::ICplxTrans &trans) const
{
db::ICplxTrans res (trans);
res.disp (db::Vector ());
res.mag (1.0);
return res;
}
db::Trans OrientationReducer::reduce (const db::Trans &trans) const
{
return db::Trans (trans.fp_trans ());
}
// ------------------------------------------------------------------------------------------
db::ICplxTrans MagnificationReducer::reduce (const db::ICplxTrans &trans) const
{
return db::ICplxTrans (trans.mag ());
}
db::Trans MagnificationReducer::reduce (const db::Trans &) const
{
return db::Trans ();
}
// ------------------------------------------------------------------------------------------
db::ICplxTrans MagnificationAndOrientationReducer::reduce (const db::ICplxTrans &trans) const
{
db::ICplxTrans res (trans);
res.disp (db::Vector ());
return res;
}
db::Trans MagnificationAndOrientationReducer::reduce (const db::Trans &trans) const
{
return db::Trans (trans.fp_trans ());
}
// ------------------------------------------------------------------------------------------
GridReducer::GridReducer (db::Coord grid)
: m_grid (grid)
{
// .. nothing yet ..
}
db::ICplxTrans GridReducer::reduce (const db::ICplxTrans &trans) const
{
// NOTE: we need to keep magnification, angle and mirror so when combining the
// reduced transformations, the result will be equivalent to reducing the combined
// transformation.
db::ICplxTrans res (trans);
res.disp (db::Vector (trans.disp ().x () - snap_to_grid (trans.disp ().x (), m_grid), trans.disp ().y () - snap_to_grid (trans.disp ().y (), m_grid)));
return res;
}
db::Trans GridReducer::reduce (const db::Trans &trans) const
{
db::Trans res (trans);
res.disp (db::Vector (trans.disp ().x () - snap_to_grid (trans.disp ().x (), m_grid), trans.disp ().y () - snap_to_grid (trans.disp ().y (), m_grid)));
return res;
}
// ------------------------------------------------------------------------------------------
ScaleAndGridReducer::ScaleAndGridReducer (db::Coord grid, db::Coord mult, db::Coord div)
: m_mult (mult), m_grid (int64_t (grid) * int64_t (div))
{
// .. nothing yet ..
}
db::ICplxTrans ScaleAndGridReducer::reduce_trans (const db::ICplxTrans &trans) const
{
db::ICplxTrans res (trans);
int64_t dx = int64_t (trans.disp ().x ()) * m_mult;
int64_t dy = int64_t (trans.disp ().y ()) * m_mult;
res.disp (db::Vector (db::Coord (dx - snap_to_grid (dx, m_grid)), db::Coord (dy - snap_to_grid (dy, m_grid))));
return res;
}
db::Trans ScaleAndGridReducer::reduce_trans (const db::Trans &trans) const
{
db::Trans res (trans);
int64_t dx = int64_t (trans.disp ().x ()) * m_mult;
int64_t dy = int64_t (trans.disp ().y ()) * m_mult;
res.disp (db::Vector (db::Coord (dx - snap_to_grid (dx, m_grid)), db::Coord (dy - snap_to_grid (dy, m_grid))));
return res;
}
db::ICplxTrans ScaleAndGridReducer::reduce (const db::ICplxTrans &trans) const
{
db::ICplxTrans res (trans);
int64_t dx = int64_t (trans.disp ().x ());
int64_t dy = int64_t (trans.disp ().y ());
res.disp (db::Vector (db::Coord (dx - snap_to_grid (dx, m_grid)), db::Coord (dy - snap_to_grid (dy, m_grid))));
return res;
}
db::Trans ScaleAndGridReducer::reduce (const db::Trans &trans) const
{
db::Trans res (trans);
int64_t dx = int64_t (trans.disp ().x ());
int64_t dy = int64_t (trans.disp ().y ());
res.disp (db::Vector (db::Coord (dx - snap_to_grid (dx, m_grid)), db::Coord (dy - snap_to_grid (dy, m_grid))));
return res;
}
// ------------------------------------------------------------------------------------------
VariantsCollectorBase::VariantsCollectorBase ()
: mp_red ()
{
@ -219,7 +332,7 @@ VariantsCollectorBase::commit_shapes (db::Layout &layout, db::Cell &top_cell, un
for (db::CellInstArray::iterator ia = i->begin (); ! ia.at_end (); ++ia) {
db::ICplxTrans t = i->complex_trans (*ia);
db::ICplxTrans rt = mp_red->reduce (vc->first * t);
db::ICplxTrans rt = mp_red->reduce (vc->first * mp_red->reduce_trans (t));
std::map<db::ICplxTrans, db::Shapes>::const_iterator v = vt.find (rt);
if (v != vt.end ()) {
@ -263,7 +376,7 @@ VariantsCollectorBase::commit_shapes (db::Layout &layout, db::Cell &top_cell, un
for (db::CellInstArray::iterator ia = i->begin (); ! ia.at_end (); ++ia) {
db::ICplxTrans t = i->complex_trans (*ia);
db::ICplxTrans rt = mp_red->reduce (vvc.begin ()->first * t);
db::ICplxTrans rt = mp_red->reduce (vvc.begin ()->first * mp_red->reduce_trans (t));
std::map<db::ICplxTrans, db::Shapes>::const_iterator v = vt.find (rt);
if (v != vt.end ()) {
@ -325,11 +438,11 @@ VariantsCollectorBase::add_variant_non_tl_invariant (std::map<db::ICplxTrans, si
{
if (inst.is_complex ()) {
for (db::CellInstArray::iterator i = inst.begin (); ! i.at_end (); ++i) {
variants [mp_red->reduce (inst.complex_trans (*i))] += 1;
variants [mp_red->reduce_trans (inst.complex_trans (*i))] += 1;
}
} else {
for (db::CellInstArray::iterator i = inst.begin (); ! i.at_end (); ++i) {
variants [db::ICplxTrans (mp_red->reduce (*i))] += 1;
variants [db::ICplxTrans (mp_red->reduce_trans (*i))] += 1;
}
}
}
@ -338,9 +451,9 @@ void
VariantsCollectorBase::add_variant_tl_invariant (std::map<db::ICplxTrans, size_t> &variants, const db::CellInstArray &inst) const
{
if (inst.is_complex ()) {
variants [mp_red->reduce (inst.complex_trans ())] += inst.size ();
variants [mp_red->reduce_trans (inst.complex_trans ())] += inst.size ();
} else {
variants [db::ICplxTrans (mp_red->reduce (inst.front ()))] += inst.size ();
variants [db::ICplxTrans (mp_red->reduce_trans (inst.front ()))] += inst.size ();
}
}
@ -355,7 +468,7 @@ VariantsCollectorBase::product (const std::map<db::ICplxTrans, size_t> &v1, cons
}
void
VariantsCollectorBase::copy_shapes (db::Layout &layout, db::cell_index_type ci_to, db::cell_index_type ci_from) const
VariantsCollectorBase::copy_shapes (db::Layout &layout, db::cell_index_type ci_to, db::cell_index_type ci_from)
{
db::Cell &to = layout.cell (ci_to);
const db::Cell &from = layout.cell (ci_from);
@ -390,7 +503,7 @@ VariantsCollectorBase::create_var_instances_non_tl_invariant (db::Cell &in_cell,
for (db::CellInstArray::iterator ia = i->begin (); ! ia.at_end (); ++ia) {
db::ICplxTrans rt = mp_red->reduce (for_var * i->complex_trans (*ia));
db::ICplxTrans rt = mp_red->reduce (for_var * mp_red->reduce_trans (i->complex_trans (*ia)));
std::map<db::ICplxTrans, db::cell_index_type>::const_iterator v = vt.find (rt);
tl_assert (v != vt.end ());
@ -419,7 +532,7 @@ VariantsCollectorBase::create_var_instances_tl_invariant (db::Cell &in_cell, std
std::map<db::ICplxTrans, db::cell_index_type>::const_iterator v;
db::ICplxTrans rt = mp_red->reduce (for_var * i->complex_trans ());
db::ICplxTrans rt = mp_red->reduce (for_var * mp_red->reduce_trans (i->complex_trans ()));
v = vt.find (rt);
tl_assert (v != vt.end ());

View File

@ -50,6 +50,8 @@ public:
TransformationReducer () { }
virtual ~TransformationReducer () { }
virtual db::Trans reduce_trans (const db::Trans &trans) const { return reduce (trans); }
virtual db::ICplxTrans reduce_trans (const db::ICplxTrans &trans) const { return reduce (trans); }
virtual db::Trans reduce (const db::Trans &trans) const = 0;
virtual db::ICplxTrans reduce (const db::ICplxTrans &trans) const = 0;
virtual bool is_translation_invariant () const { return true; }
@ -63,18 +65,8 @@ public:
struct DB_PUBLIC OrientationReducer
: public TransformationReducer
{
db::ICplxTrans reduce (const db::ICplxTrans &trans) const
{
db::ICplxTrans res (trans);
res.disp (db::Vector ());
res.mag (1.0);
return res;
}
db::Trans reduce (const db::Trans &trans) const
{
return db::Trans (trans.fp_trans ());
}
db::ICplxTrans reduce (const db::ICplxTrans &trans) const;
db::Trans reduce (const db::Trans &trans) const;
};
/**
@ -85,15 +77,8 @@ struct DB_PUBLIC OrientationReducer
struct DB_PUBLIC MagnificationReducer
: public TransformationReducer
{
db::ICplxTrans reduce (const db::ICplxTrans &trans) const
{
return db::ICplxTrans (trans.mag ());
}
db::Trans reduce (const db::Trans &) const
{
return db::Trans ();
}
db::ICplxTrans reduce (const db::ICplxTrans &trans) const;
db::Trans reduce (const db::Trans &) const;
};
/**
@ -104,17 +89,8 @@ struct DB_PUBLIC MagnificationReducer
struct DB_PUBLIC MagnificationAndOrientationReducer
: public TransformationReducer
{
db::ICplxTrans reduce (const db::ICplxTrans &trans) const
{
db::ICplxTrans res (trans);
res.disp (db::Vector ());
return res;
}
db::Trans reduce (const db::Trans &trans) const
{
return db::Trans (trans.fp_trans ());
}
db::ICplxTrans reduce (const db::ICplxTrans &trans) const;
db::Trans reduce (const db::Trans &trans) const;
};
/**
@ -125,47 +101,39 @@ struct DB_PUBLIC MagnificationAndOrientationReducer
struct DB_PUBLIC GridReducer
: public TransformationReducer
{
GridReducer (db::Coord grid)
: m_grid (grid)
{
// .. nothing yet ..
}
GridReducer (db::Coord grid);
db::ICplxTrans reduce (const db::ICplxTrans &trans) const
{
// NOTE: we need to keep magnification, angle and mirror so when combining the
// reduced transformations, the result will be equivalent to reducing the combined
// transformation.
db::ICplxTrans res (trans);
res.disp (db::Vector (mod (trans.disp ().x ()), mod (trans.disp ().y ())));
return res;
}
db::Trans reduce (const db::Trans &trans) const
{
db::Trans res (trans);
res.disp (db::Vector (mod (trans.disp ().x ()), mod (trans.disp ().y ())));
return res;
}
db::ICplxTrans reduce (const db::ICplxTrans &trans) const;
db::Trans reduce (const db::Trans &trans) const;
bool is_translation_invariant () const { return false; }
private:
db::Coord m_grid;
};
inline db::Coord mod (db::Coord c) const
{
if (c < 0) {
c = m_grid - (-c) % m_grid;
if (c == m_grid) {
return 0;
} else {
return c;
}
} else {
return c % m_grid;
}
}
/**
* @brief A scale+grid reducer
*
* This reducer incarnation reduces the transformation to it's displacement modulo a grid
* after a specified scaling has been applied.
* The scaling is given by a divider and multiplier and is mult / div.
*/
struct DB_PUBLIC ScaleAndGridReducer
: public TransformationReducer
{
ScaleAndGridReducer (db::Coord grid, db::Coord mult, db::Coord div);
virtual db::ICplxTrans reduce_trans (const db::ICplxTrans &trans) const;
virtual db::Trans reduce_trans (const db::Trans &trans) const;
virtual db::ICplxTrans reduce (const db::ICplxTrans &trans) const;
virtual db::Trans reduce (const db::Trans &trans) const;
bool is_translation_invariant () const { return false; }
private:
int64_t m_mult;
int64_t m_grid;
};
/**
@ -225,6 +193,11 @@ public:
*/
bool has_variants () const;
/**
* @brief Utility: copy all shapes from one cell to another
*/
static void copy_shapes (db::Layout &layout, db::cell_index_type ci_to, db::cell_index_type ci_from);
private:
std::map<db::cell_index_type, std::map<db::ICplxTrans, size_t> > m_variants;
const TransformationReducer *mp_red;
@ -233,7 +206,6 @@ private:
void add_variant_non_tl_invariant (std::map<db::ICplxTrans, size_t> &variants, const db::CellInstArray &inst) const;
void add_variant_tl_invariant (std::map<db::ICplxTrans, size_t> &variants, const db::CellInstArray &inst) const;
void product (const std::map<db::ICplxTrans, size_t> &v1, const std::map<db::ICplxTrans, size_t> &v2, std::map<db::ICplxTrans, size_t> &prod) const;
void copy_shapes (db::Layout &layout, db::cell_index_type ci_to, db::cell_index_type ci_from) const;
void create_var_instances (db::Cell &in_cell, std::vector<db::CellInstArrayWithProperties> &inst, const db::ICplxTrans &for_var, const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &var_table, bool tl_invariant) const;
void create_var_instances_non_tl_invariant (db::Cell &in_cell, std::vector<db::CellInstArrayWithProperties> &inst, const db::ICplxTrans &for_var, const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &var_table) const;
void create_var_instances_tl_invariant (db::Cell &in_cell, std::vector<db::CellInstArrayWithProperties> &inst, const db::ICplxTrans &for_var, const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &var_table) const;

View File

@ -889,7 +889,7 @@ DeepShapeStore::issue_variants (unsigned int layout_index, const std::map<db::ce
const db::CellMapping &
DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set<db::cell_index_type> *excluded_cells, const std::set<db::cell_index_type> *included_cells)
{
const db::Layout *source_layout = &m_layouts [layout_index]->layout;
db::Layout *source_layout = &m_layouts [layout_index]->layout;
if (source_layout->begin_top_down () == source_layout->end_top_cells ()) {
// empty source - nothing to do.
static db::CellMapping cm;
@ -910,6 +910,9 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
cm = m_delivery_mapping_cache.insert (std::make_pair (key, db::CellMapping ())).first;
// collects the cell mappings we skip because they are variants (variant building or box variants)
std::map<db::cell_index_type, std::pair<db::cell_index_type, std::set<db::Box> > > cm_skipped_variants;
if (into_layout == original_builder.source ().layout () && &into_layout->cell (into_cell) == original_builder.source ().top_cell ()) {
// This is the case of mapping back to the original. In this case we can use the information
@ -917,22 +920,28 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
// create from them. We need to consider however, that the hierarchy builder is allowed to create
// variants which we cannot map.
for (HierarchyBuilder::cell_map_type::const_iterator m = original_builder.begin_cell_map (); m != original_builder.end_cell_map (); ++m) {
for (HierarchyBuilder::cell_map_type::const_iterator m = original_builder.begin_cell_map (); m != original_builder.end_cell_map (); ) {
HierarchyBuilder::cell_map_type::const_iterator mm = m;
++mm;
bool skip = original_builder.is_variant (m->second); // skip variant cells
while (mm != original_builder.end_cell_map () && mm->first.first == m->first.first && ! skip) {
// we have cell variants and cannot simply map
while (mm != original_builder.end_cell_map () && mm->first.first == m->first.first) {
// we have cell (box) variants and cannot simply map
++mm;
++m;
skip = true;
}
if (! skip) {
cm->second.map (m->second, m->first.first);
} else {
for (HierarchyBuilder::cell_map_type::const_iterator n = m; n != mm; ++n) {
tl_assert (cm_skipped_variants.find (n->second) == cm_skipped_variants.end ());
cm_skipped_variants [n->second] = n->first;
}
}
m = mm;
}
} else if (into_layout->cells () == 1) {
@ -948,7 +957,43 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
// Add new cells for the variants and (possible) devices which are cells added during the device
// extraction process
cm->second.create_missing_mapping (*into_layout, into_cell, *source_layout, source_top, excluded_cells, included_cells);
std::vector<std::pair<db::cell_index_type, db::cell_index_type> > new_pairs = cm->second.create_missing_mapping2 (*into_layout, into_cell, *source_layout, source_top, excluded_cells, included_cells);
// the variant's originals we are going to delete
std::set<db::cell_index_type> cells_to_delete;
// We now need to fix the cell map from the hierarchy builder, so we can import back from the modified layout.
// This is in particular important if we created new cells for known variants.
for (std::vector<std::pair<db::cell_index_type, db::cell_index_type> >::const_iterator np = new_pairs.begin (); np != new_pairs.end (); ++np) {
db::cell_index_type var_org = original_builder.original_target_for_variant (np->first);
std::map<db::cell_index_type, std::pair<db::cell_index_type, std::set<db::Box> > >::const_iterator icm = cm_skipped_variants.find (var_org);
if (icm != cm_skipped_variants.end ()) {
// create the variant clone in the original layout too and delete this cell
VariantsCollectorBase::copy_shapes (*into_layout, np->second, icm->second.first);
cells_to_delete.insert (icm->second.first);
// forget the original cell (now separated into variants) and map the variants back into the
// DSS layout
original_builder.unmap (icm->second);
original_builder.map (std::make_pair (np->second, icm->second.second), np->first);
// forget the variant as now it's a real cell in the source layout
original_builder.unregister_variant (np->first);
// rename the cell because it may be a different one now
source_layout->rename_cell (np->first, into_layout->cell_name (np->second));
}
}
// delete the variant's original cell
if (! cells_to_delete.empty ()) {
into_layout->delete_cells (cells_to_delete);
}
}

View File

@ -72,7 +72,9 @@ public:
virtual EdgePairsDelegate *angle_check (double, double, bool) const;
virtual RegionDelegate *snapped_in_place (db::Coord, db::Coord) { return this; }
virtual RegionDelegate *snapped (db::Coord, db::Coord) { return new EmptyRegion (); }
virtual RegionDelegate *snapped (db::Coord, db::Coord) { return new EmptyRegion (); }
virtual RegionDelegate *scaled_and_snapped_in_place (db::Coord, db::Coord, db::Coord, db::Coord, db::Coord, db::Coord) { return this; }
virtual RegionDelegate *scaled_and_snapped (db::Coord, db::Coord, db::Coord, db::Coord, db::Coord, db::Coord) { return new EmptyRegion (); }
virtual EdgesDelegate *edges (const EdgeFilterBase *) const;
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &) { return this; }

View File

@ -185,6 +185,40 @@ HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_
m_variants_to_original_target_map.insert (std::make_pair (var, non_var));
}
void
HierarchyBuilder::unregister_variant (db::cell_index_type var)
{
variant_to_original_target_map_type::const_iterator v = m_variants_to_original_target_map.find (var);
if (v == m_variants_to_original_target_map.end ()) {
return;
}
original_target_to_variants_map_type::iterator rv = m_original_targets_to_variants_map.find (v->second);
tl_assert (rv != m_original_targets_to_variants_map.end ());
std::vector<db::cell_index_type> &vv = rv->second;
std::vector<db::cell_index_type>::iterator ri = std::find (vv.begin (), vv.end (), var);
tl_assert (ri != vv.end ());
vv.erase (ri);
if (vv.empty ()) {
m_original_targets_to_variants_map.erase (rv);
}
m_variants_to_original_target_map.erase (v);
}
db::cell_index_type
HierarchyBuilder::original_target_for_variant (db::cell_index_type ci) const
{
variant_to_original_target_map_type::const_iterator v = m_variants_to_original_target_map.find (ci);
if (v != m_variants_to_original_target_map.end ()) {
return v->second;
} else {
return ci;
}
}
void
HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
{
@ -269,6 +303,7 @@ HierarchyBuilder::new_inst (const RecursiveShapeIterator *iter, const db::CellIn
if (all) {
std::pair<db::cell_index_type, std::set<db::Box> > key (inst.object ().cell_index (), std::set<db::Box> ());
m_cm_entry = m_cell_map.find (key);
m_cm_new_entry = false;

View File

@ -284,6 +284,24 @@ public:
return m_cell_map.end ();
}
/**
* @brief Unmaps an original cell/clip box version from the original-to-working copy cell map
*
* An unmapped cell is never again considered.
*/
void unmap (const cell_map_type::key_type &k)
{
m_cell_map.erase (k);
}
/**
* @brief Maps an original cell/clip box version to a original-to-working copy cell
*/
void map (const cell_map_type::key_type &k, db::cell_index_type ci)
{
m_cell_map [k] = ci;
}
/**
* @brief Marks a cell as a variant of another
*
@ -292,6 +310,11 @@ public:
*/
void register_variant (db::cell_index_type non_var, db::cell_index_type var);
/**
* @brief Unregisters a cell as a variant
*/
void unregister_variant (db::cell_index_type var);
/**
* @brief Gets a value indicating whether the given cell is a variant cell
*/
@ -300,6 +323,11 @@ public:
return m_variants_to_original_target_map.find (ci) != m_variants_to_original_target_map.end ();
}
/**
* @brief Gets the original target for a variant cell
*/
db::cell_index_type original_target_for_variant (db::cell_index_type ci) const;
private:
tl::weak_ptr<db::Layout> mp_target;
HierarchyBuilderShapeReceiver *mp_pipe;

View File

@ -22,6 +22,8 @@
#include "dbLayoutUtils.h"
#include "dbCellVariants.h"
#include "dbRegionUtils.h"
#include "tlProgress.h"
namespace db
@ -431,5 +433,125 @@ ContextCache::find_layout_context (db::cell_index_type from, db::cell_index_type
return c->second;
}
// ------------------------------------------------------------
// Scale and snap a layout
void
scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db::Coord d)
{
if (g < 0) {
throw tl::Exception (tl::to_string (tr ("Snapping requires a positive grid value")));
}
if (m <= 0 || d <= 0) {
throw tl::Exception (tl::to_string (tr ("Scale and snap requires positive and non-null magnification or divisor values")));
}
if (! g && m == d) {
return;
}
db::cell_variants_collector<db::ScaleAndGridReducer> vars (db::ScaleAndGridReducer (g, m, d));
vars.collect (layout, cell);
vars.separate_variants (layout, cell);
std::set<db::cell_index_type> called_cells;
cell.collect_called_cells (called_cells);
called_cells.insert (cell.cell_index ());
db::LayoutLocker layout_locker (&layout);
layout.update ();
std::vector<db::Point> heap;
unsigned int work_layer = layout.insert_layer ();
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
if (called_cells.find (c->cell_index ()) == called_cells.end ()) {
continue;
}
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
db::ICplxTrans tr = v.begin ()->first;
// NOTE: tr_disp is already multiplied with mag, so it can be an integer
db::Vector tr_disp = tr.disp ();
tr.disp (db::Vector ());
db::ICplxTrans trinv = tr.inverted ();
for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) {
db::Shapes &s = c->shapes ((*l).first);
db::Shapes &out = c->shapes (work_layer);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
poly.transform (tr);
poly = scaled_and_snapped_polygon (poly, g, m, d, tr_disp.x (), g, m, d, tr_disp.y (), heap);
poly.transform (trinv);
out.insert (poly);
}
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Texts); ! si.at_end (); ++si) {
db::Text text;
si->text (text);
text.transform (tr);
text.trans (db::Trans (text.trans ().rot (), scaled_and_snapped_vector (text.trans ().disp (), g, m, d, tr_disp.x (), g, m, d, tr_disp.y ())));
text.transform (trinv);
out.insert (text);
}
s.swap (out);
out.clear ();
}
// Snap instance placements to grid and magnify
// NOTE: we can modify the instances because the ScaleAndGridReducer marked every cell with children
// as a variant cell (an effect of ScaleAndGridReducer::want_variants(cell) == true where cells have children).
// Variant cells are not copied blindly back to the original layout.
std::list<db::CellInstArray> new_insts;
for (db::Cell::const_iterator inst = c->begin (); ! inst.at_end (); ++inst) {
const db::CellInstArray &ia = inst->cell_inst ();
for (db::CellInstArray::iterator i = ia.begin (); ! i.at_end (); ++i) {
db::Trans ti (*i);
db::Vector ti_disp = ti.disp ();
ti_disp.transform (tr);
ti_disp = scaled_and_snapped_vector (ti_disp, g, m, d, tr_disp.x (), g, m, d, tr_disp.y ());
ti_disp.transform (trinv);
ti.disp (ti_disp);
if (ia.is_complex ()) {
new_insts.push_back (db::CellInstArray (ia.object (), ia.complex_trans (ti)));
} else {
new_insts.push_back (db::CellInstArray (ia.object (), ti));
}
}
}
c->clear_insts ();
for (std::list<db::CellInstArray>::const_iterator i = new_insts.begin (); i != new_insts.end (); ++i) {
c->insert (*i);
}
}
}
}

View File

@ -223,6 +223,14 @@ private:
const db::Layout *mp_layout;
};
/**
* @brief Scales and snaps the layout below the given cell
*
* This method will scale and snap all layers from the given cell and below to the
* specified grid. Scaling happens by the rational factor m / d.
*/
DB_PUBLIC void scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db::Coord d);
} // namespace db
#endif

View File

@ -389,6 +389,18 @@ Region::snapped (db::Coord gx, db::Coord gy) const
return Region (mp_delegate->snapped (gx, gy));
}
void
Region::scale_and_snap (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy)
{
set_delegate (mp_delegate->scaled_and_snapped_in_place (gx, mx, dx, gy, my, dy));
}
Region
Region::scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy) const
{
return Region (mp_delegate->scaled_and_snapped (gx, mx, dx, gy, my, dy));
}
Region
Region::strange_polygon_check () const
{

View File

@ -903,6 +903,19 @@ public:
*/
Region snapped (db::Coord gx, db::Coord gy) const;
/**
* @brief Scales and grid-snaps the region
*
* This method will scale the region by mx/dx in horizontal and by my/dy in vertical
* direction and then snape to gx and gy respectively.
*/
void scale_and_snap (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy);
/**
* @brief Returns the scaled and snapped region
*/
Region scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy) const;
/**
* @brief Performs a check for "strange" polygons
*

View File

@ -260,6 +260,8 @@ public:
virtual RegionDelegate *snapped_in_place (db::Coord gx, db::Coord gy) = 0;
virtual RegionDelegate *snapped (db::Coord gx, db::Coord gy) = 0;
virtual RegionDelegate *scaled_and_snapped_in_place (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy) = 0;
virtual RegionDelegate *scaled_and_snapped (db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy) = 0;
virtual EdgesDelegate *edges (const EdgeFilterBase *filter) const = 0;
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter) = 0;

View File

@ -350,5 +350,92 @@ region_to_edge_interaction_filter_base<OutputType>::fill_output ()
template class region_to_edge_interaction_filter_base<db::Polygon>;
template class region_to_edge_interaction_filter_base<db::Edge>;
// -------------------------------------------------------------------------------------
// Polygon snapping
db::Polygon
snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap)
{
db::Polygon pnew;
for (size_t i = 0; i < poly.holes () + 1; ++i) {
heap.clear ();
db::Polygon::polygon_contour_iterator b, e;
if (i == 0) {
b = poly.begin_hull ();
e = poly.end_hull ();
} else {
b = poly.begin_hole ((unsigned int) (i - 1));
e = poly.end_hole ((unsigned int) (i - 1));
}
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
heap.push_back (db::Point (snap_to_grid ((*pt).x (), gx), snap_to_grid ((*pt).y (), gy)));
}
if (i == 0) {
pnew.assign_hull (heap.begin (), heap.end ());
} else {
pnew.insert_hole (heap.begin (), heap.end ());
}
}
return pnew;
}
db::Polygon
scaled_and_snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord mx, db::Coord dx, db::Coord ox, db::Coord gy, db::Coord my, db::Coord dy, db::Coord oy, std::vector<db::Point> &heap)
{
db::Polygon pnew;
int64_t dgx = int64_t (gx) * int64_t (dx);
int64_t dgy = int64_t (gy) * int64_t (dy);
for (size_t i = 0; i < poly.holes () + 1; ++i) {
heap.clear ();
db::Polygon::polygon_contour_iterator b, e;
if (i == 0) {
b = poly.begin_hull ();
e = poly.end_hull ();
} else {
b = poly.begin_hole ((unsigned int) (i - 1));
e = poly.end_hole ((unsigned int) (i - 1));
}
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
int64_t x = snap_to_grid (int64_t ((*pt).x ()) * mx + int64_t (ox), dgx) / int64_t (dx);
int64_t y = snap_to_grid (int64_t ((*pt).y ()) * my + int64_t (oy), dgy) / int64_t (dy);
heap.push_back (db::Point (db::Coord (x), db::Coord (y)));
}
if (i == 0) {
pnew.assign_hull (heap.begin (), heap.end ());
} else {
pnew.insert_hole (heap.begin (), heap.end ());
}
}
return pnew;
}
db::Vector
scaled_and_snapped_vector (const db::Vector &v, db::Coord gx, db::Coord mx, db::Coord dx, db::Coord ox, db::Coord gy, db::Coord my, db::Coord dy, db::Coord oy)
{
int64_t dgx = int64_t (gx) * int64_t (dx);
int64_t dgy = int64_t (gy) * int64_t (dy);
int64_t x = snap_to_grid (int64_t (v.x ()) * mx + int64_t (ox), dgx) / int64_t (dx);
int64_t y = snap_to_grid (int64_t (v.y ()) * my + int64_t (oy), dgy) / int64_t (dy);
return db::Vector (db::Coord (x), db::Coord (y));
}
}

View File

@ -524,6 +524,37 @@ private:
OutputContainer *mp_output;
};
template <class C>
static inline C snap_to_grid (C c, C g)
{
// This form of snapping always snaps g/2 to right/top.
if (c < 0) {
c = -g * ((-c + (g - 1) / 2) / g);
} else {
c = g * ((c + g / 2) / g);
}
return c;
}
/**
* @brief Snaps a polygon to the given grid
* Heap is a vector of points reused for the point list
*/
DB_PUBLIC db::Polygon snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap);
/**
* @brief Scales and snaps a polygon to the given grid
* Heap is a vector of points reused for the point list
* The coordinate transformation is q = ((p * m + o) snap (g * d)) / d.
*/
DB_PUBLIC db::Polygon scaled_and_snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord mx, db::Coord dx, db::Coord ox, db::Coord gy, db::Coord my, db::Coord dy, db::Coord oy, std::vector<db::Point> &heap);
/**
* @brief Scales and snaps a vector to the given grid
* The coordinate transformation is q = ((p * m + o) snap (g * d)) / d.
*/
DB_PUBLIC db::Vector scaled_and_snapped_vector (const db::Vector &v, db::Coord gx, db::Coord mx, db::Coord dx, db::Coord ox, db::Coord gy, db::Coord my, db::Coord dy, db::Coord oy);
} // namespace db
#endif

View File

@ -33,6 +33,7 @@
#include "dbPCellDeclaration.h"
#include "dbHash.h"
#include "dbRegion.h"
#include "dbLayoutUtils.h"
#include "tlStream.h"
namespace gsi
@ -812,6 +813,16 @@ static const std::string &layout_meta_get_description (const db::MetaInfo *mi)
return mi->description;
}
static void scale_and_snap1 (db::Layout *layout, db::Cell &cell, db::Coord g, db::Coord m, db::Coord d)
{
scale_and_snap (*layout, cell, g, m, d);
}
static void scale_and_snap2 (db::Layout *layout, db::cell_index_type ci, db::Coord g, db::Coord m, db::Coord d)
{
scale_and_snap (*layout, layout->cell (ci), g, m, d);
}
Class<db::MetaInfo> decl_LayoutMetaInfo ("db", "LayoutMetaInfo",
gsi::constructor ("new", &layout_meta_info_ctor, gsi::arg ("name"), gsi::arg ("value"), gsi::arg ("description", std::string ()),
"@brief Creates a layout meta info object\n"
@ -1542,6 +1553,25 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"an index in the range of 0 to layers-1 needs to be a valid layer. These layers can be either valid, "
"special or unused. Use \\is_valid_layer? and \\is_special_layer? to test for the first two states.\n"
) +
gsi::method_ext ("scale_and_snap", &scale_and_snap1, gsi::arg ("cell"), gsi::arg ("grid"), gsi::arg ("mult"), gsi::arg ("div"),
"@brief Scales and snaps the layout below a given cell by the given rational factor and snaps to the given grid\n"
"\n"
"This method is useful to scale a layout by a non-integer factor. The "
"scale factor is given by the rational number mult / div. After scaling, the "
"layout will be snapped to the given grid.\n"
"\n"
"Snapping happens 'as-if-flat' - that is, touching edges will stay touching, regardless of their "
"hierarchy path. To achieve this, this method usually needs to produce cell variants.\n"
"\n"
"This method has been introduced in version 0.26.1.\n"
) +
gsi::method_ext ("scale_and_snap", &scale_and_snap2, gsi::arg ("cell_index"), gsi::arg ("grid"), gsi::arg ("mult"), gsi::arg ("div"),
"@brief Scales and snaps the layout below a given cell by the given rational factor and snaps to the given grid\n"
"\n"
"Like the other version of \\scale_and_snap, but taking a cell index for the argument.\n"
"\n"
"This method has been introduced in version 0.26.1.\n"
) +
gsi::method ("transform", (void (db::Layout::*) (const db::Trans &t)) &db::Layout::transform,
"@brief Transforms the layout with the given transformation\n"
"@args trans\n"

View File

@ -949,10 +949,28 @@ Class<db::Region> decl_Region ("db", "Region",
"This method will snap the region to the given grid - each x or y coordinate is brought on the gx or gy grid by rounding "
"to the nearest value which is a multiple of gx or gy.\n"
"\n"
"If gx or gy is 0 or less, no snapping happens in that direction.\n"
"If gx or gy is 0, no snapping happens in that direction.\n"
"\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
) +
method ("scaled_and_snapped", &db::Region::scaled_and_snapped, gsi::arg ("gx"), gsi::arg ("mx"), gsi::arg ("dx"), gsi::arg ("gy"),gsi::arg ("my"), gsi::arg ("dy"),
"@brief Returns the scaled and snapped region\n"
"This method will scale and snap the region to the given grid and return the scaled and snapped region (see \\scale_and_snap). The original region is not modified.\n"
"\n"
"This method has been introduced in version 0.26.1."
) +
method ("scale_and_snap", &db::Region::scale_and_snap, gsi::arg ("gx"), gsi::arg ("mx"), gsi::arg ("dx"), gsi::arg ("gy"),gsi::arg ("my"), gsi::arg ("dy"),
"@brief Scales and snaps the region to the given grid\n"
"This method will first scale the region by a rational factor of mx/dx horizontally and my/dy vertically and then "
"snap the region to the given grid - each x or y coordinate is brought on the gx or gy grid by rounding "
"to the nearest value which is a multiple of gx or gy.\n"
"\n"
"If gx or gy is 0, the result is brought on a grid of 1.\n"
"\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
"\n"
"This method has been introduced in version 0.26.1."
) +
method ("grid_check", &db::Region::grid_check, gsi::arg ("gx"), gsi::arg ("gy"),
"@brief Returns a marker for all vertices not being on the given grid\n"
"This method will return an edge pair object for every vertex whose x coordinate is not a multiple of gx or whose "

View File

@ -1490,6 +1490,114 @@ TEST(26_BreakoutCells)
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au26.gds");
}
TEST(27a_snap)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
r1.set_merged_semantics (false);
db::Region r2 = r1.snapped (19, 19);
r2.insert_into (&ly, top_cell_index, ly.get_layer (db::LayerProperties (100, 0)));
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au27.gds");
}
TEST(27b_snap)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
r1.set_merged_semantics (false);
r1.snap (19, 19);
r1.insert_into (&ly, top_cell_index, ly.get_layer (db::LayerProperties (100, 0)));
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au27.gds");
}
TEST(28a_snap)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
r1.set_merged_semantics (false);
db::Region r2 = r1.scaled_and_snapped (19, 2, 10, 19, 2, 10);
r2.insert_into (&ly, top_cell_index, ly.get_layer (db::LayerProperties (100, 0)));
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au28.gds");
}
TEST(28b_snap)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
r1.set_merged_semantics (false);
r1.scale_and_snap (19, 2, 10, 19, 2, 10);
r1.insert_into (&ly, top_cell_index, ly.get_layer (db::LayerProperties (100, 0)));
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au28.gds");
}
TEST(100_Integration)
{
db::Layout ly;
@ -1641,3 +1749,105 @@ TEST(issue_277)
EXPECT_EQ (r.sized (1).merged (false, 1).to_string (), "");
}
TEST(issue_400)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/gds/t10.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
// keeps a reference to the DSS
db::Region rr (db::RecursiveShapeIterator (ly, top_cell, (*ly.begin_layers ()).first), dss);
for (db::Layout::layer_iterator l = ly.begin_layers (); l != ly.end_layers (); ++l) {
unsigned int li = (*l).first;
db::Region r (db::RecursiveShapeIterator (ly, top_cell, li), dss);
r.set_merged_semantics (false);
r.snap (19, 19);
ly.clear_layer (li);
r.insert_into (&ly, top_cell_index, li);
}
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au400a.gds");
}
TEST(issue_400_dont_keep_regions)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/gds/t10.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
for (db::Layout::layer_iterator l = ly.begin_layers (); l != ly.end_layers (); ++l) {
unsigned int li = (*l).first;
db::Region r (db::RecursiveShapeIterator (ly, top_cell, li), dss);
r.set_merged_semantics (false);
r.snap (19, 19);
ly.clear_layer (li);
r.insert_into (&ly, top_cell_index, li);
}
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au400b.gds");
}
TEST(issue_400_with_region)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/gds/t10.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::DBox rbox (2.61, -1.6, 12.76, 4.7);
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
for (db::Layout::layer_iterator l = ly.begin_layers (); l != ly.end_layers (); ++l) {
unsigned int li = (*l).first;
db::Region r (db::RecursiveShapeIterator (ly, top_cell, li, rbox.transformed (db::CplxTrans (ly.dbu ()).inverted ())), dss);
r.set_merged_semantics (false);
r.snap (19, 19);
ly.clear_layer (li);
r.insert_into (&ly, top_cell_index, li);
}
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au400c.gds");
}

View File

@ -615,3 +615,41 @@ TEST(16)
}
TEST(17_scale_and_snap)
{
db::Layout l1;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (l1);
}
db::scale_and_snap (l1, l1.cell (*l1.begin_top_down ()), 1, 20, 19);
CHECKPOINT();
db::compare_layouts (_this, l1, tl::testsrc () + "/testdata/algo/layout_utils_au_sns1.gds");
db::scale_and_snap (l1, l1.cell (*l1.begin_top_down ()), 1, 19, 20);
CHECKPOINT();
db::compare_layouts (_this, l1, tl::testsrc () + "/testdata/algo/layout_utils_au_sns2.gds");
}
TEST(18_scale_and_snap)
{
db::Layout l1;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (l1);
}
db::scale_and_snap (l1, l1.cell (*l1.begin_top_down ()), 19, 1, 1);
CHECKPOINT();
db::compare_layouts (_this, l1, tl::testsrc () + "/testdata/algo/layout_utils_au_sns3.gds");
}

View File

@ -28,6 +28,10 @@
#include "dbRegionProcessors.h"
#include "dbEdgesUtils.h"
#include "dbBoxScanner.h"
#include "dbReader.h"
#include "dbTestSupport.h"
#include "tlStream.h"
#include <cstdio>
@ -1391,6 +1395,106 @@ TEST(31)
EXPECT_EQ (db::Region (db::Box (db::Point (0, 3999), db::Point (1001, 6000))).pull_overlapping (r).to_string (), "(1000,0;1000,4000;6000,4000;6000,0)");
}
TEST(32a_snap)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1));
r1.set_merged_semantics (false);
db::Region r2 = r1.snapped (19, 19);
r2.insert_into (&ly, top_cell_index, ly.get_layer (db::LayerProperties (100, 0)));
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/region_au32.gds");
}
TEST(32b_snap)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1));
r1.set_merged_semantics (false);
r1.snap (19, 19);
r1.insert_into (&ly, top_cell_index, ly.get_layer (db::LayerProperties (100, 0)));
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/region_au32.gds");
}
TEST(33a_snap)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1));
r1.set_merged_semantics (false);
db::Region r2 = r1.scaled_and_snapped (19, 2, 10, 19, 2, 10);
r2.insert_into (&ly, top_cell_index, ly.get_layer (db::LayerProperties (100, 0)));
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/region_au33.gds");
}
TEST(33b_snap)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/scale_and_snap.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1));
r1.set_merged_semantics (false);
r1.scale_and_snap (19, 2, 10, 19, 2, 10);
r1.insert_into (&ly, top_cell_index, ly.get_layer (db::LayerProperties (100, 0)));
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/region_au33.gds");
}
TEST(100_Processors)
{
db::Region r;

BIN
testdata/algo/deep_region_au27.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au28.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au400a.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au400b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au400c.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/layout_utils_au_sns1.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/layout_utils_au_sns2.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/layout_utils_au_sns3.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/region_au32.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/region_au33.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/scale_and_snap.gds vendored Normal file

Binary file not shown.