diff --git a/src/db/db/dbCellVariants.cc b/src/db/db/dbCellVariants.cc index adb5b6e97..38456de6b 100644 --- a/src/db/db/dbCellVariants.cc +++ b/src/db/db/dbCellVariants.cc @@ -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::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::const_iterator v = vt.find (rt); if (v != vt.end ()) { @@ -325,11 +438,11 @@ VariantsCollectorBase::add_variant_non_tl_invariant (std::mapreduce (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 &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::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::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 ()); diff --git a/src/db/db/dbCellVariants.h b/src/db/db/dbCellVariants.h index 34775bc4a..965bdae5f 100644 --- a/src/db/db/dbCellVariants.h +++ b/src/db/db/dbCellVariants.h @@ -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); - } - } }; /** diff --git a/src/db/db/dbLayoutUtils.cc b/src/db/db/dbLayoutUtils.cc index 0b8bc636c..580c4066d 100644 --- a/src/db/db/dbLayoutUtils.cc +++ b/src/db/db/dbLayoutUtils.cc @@ -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))); diff --git a/src/db/db/dbLayoutUtils.h b/src/db/db/dbLayoutUtils.h index 44e176ad6..2c6cbd1ae 100644 --- a/src/db/db/dbLayoutUtils.h +++ b/src/db/db/dbLayoutUtils.h @@ -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 diff --git a/src/db/db/dbRegionUtils.cc b/src/db/db/dbRegionUtils.cc index 98475d9a0..e2b975f2f 100644 --- a/src/db/db/dbRegionUtils.cc +++ b/src/db/db/dbRegionUtils.cc @@ -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)); } diff --git a/src/db/db/dbRegionUtils.h b/src/db/db/dbRegionUtils.h index 95fd8e5ea..dd59d41f6 100644 --- a/src/db/db/dbRegionUtils.h +++ b/src/db/db/dbRegionUtils.h @@ -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 &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 diff --git a/src/db/unit_tests/dbLayoutUtils.cc b/src/db/unit_tests/dbLayoutUtils.cc index 57b73bb94..1c7ce3825 100644 --- a/src/db/unit_tests/dbLayoutUtils.cc +++ b/src/db/unit_tests/dbLayoutUtils.cc @@ -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"); +} diff --git a/testdata/algo/layout_utils_au_sns1.gds b/testdata/algo/layout_utils_au_sns1.gds new file mode 100644 index 000000000..372770c61 Binary files /dev/null and b/testdata/algo/layout_utils_au_sns1.gds differ diff --git a/testdata/algo/layout_utils_au_sns2.gds b/testdata/algo/layout_utils_au_sns2.gds new file mode 100644 index 000000000..1a69e3ee5 Binary files /dev/null and b/testdata/algo/layout_utils_au_sns2.gds differ diff --git a/testdata/algo/layout_utils_au_sns3.gds b/testdata/algo/layout_utils_au_sns3.gds new file mode 100644 index 000000000..d6bc61269 Binary files /dev/null and b/testdata/algo/layout_utils_au_sns3.gds differ diff --git a/testdata/algo/scale_and_snap.gds b/testdata/algo/scale_and_snap.gds new file mode 100644 index 000000000..9a1972426 Binary files /dev/null and b/testdata/algo/scale_and_snap.gds differ