Fixed 'scale_and_snap' feature

This commit is contained in:
Matthias Koefferlein 2019-11-07 22:54:16 +01:00
parent 4924d0269c
commit 318efbf7b0
11 changed files with 201 additions and 120 deletions

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 ();
}
}
@ -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,15 @@ 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;
}
}
};
/**
@ -178,49 +122,18 @@ private:
struct DB_PUBLIC ScaleAndGridReducer
: public TransformationReducer
{
ScaleAndGridReducer (db::Coord grid, db::Coord mult, db::Coord div)
: m_mult (mult), m_grid (int64_t (grid) * int64_t (div))
{
// .. nothing yet ..
}
ScaleAndGridReducer (db::Coord grid, db::Coord mult, db::Coord div);
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;
}
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;
inline db::Coord mod (db::Coord c) const
{
int64_t cc = int64_t (c) * m_mult;
if (cc < 0) {
cc = m_grid - (-cc) % m_grid;
if (cc == m_grid) {
return 0;
} else {
return db::Coord (cc);
}
} else {
return db::Coord (cc % m_grid);
}
}
};
/**

View File

@ -493,7 +493,20 @@ scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db
db::Polygon poly;
si->polygon (poly);
poly.transform (tr);
out.insert (scaled_and_snapped_polygon (poly, g, m, d, tr_disp.x (), g, m, d, tr_disp.y (), heap).transformed (trinv));
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);
}
@ -515,7 +528,11 @@ scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db
for (db::CellInstArray::iterator i = ia.begin (); ! i.at_end (); ++i) {
db::Trans ti (*i);
ti.disp (scaled_and_snapped_vector (ti.disp (), g, m, d, g, m, d));
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)));

View File

@ -229,7 +229,7 @@ private:
* 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.
*/
void scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db::Coord d);
DB_PUBLIC void scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db::Coord d);
} // namespace db

View File

@ -427,13 +427,13 @@ scaled_and_snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord mx,
}
db::Vector
scaled_and_snapped_vector (const db::Vector &v, db::Coord gx, db::Coord mx, db::Coord dx, db::Coord gy, db::Coord my, db::Coord dy)
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, dgx) / int64_t (dx);
int64_t y = snap_to_grid (int64_t (v.y ()) * my, dgy) / 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

@ -545,15 +545,15 @@ DB_PUBLIC db::Polygon snapped_polygon (const db::Polygon &poly, db::Coord gx, db
/**
* @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) % (g * d)) / d.
* 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) % (g * d)) / d.
* 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 gy, db::Coord my, db::Coord dy);
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

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");
}

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/scale_and_snap.gds vendored Normal file

Binary file not shown.