mirror of https://github.com/KLayout/klayout.git
Bug fixes, enhancements, tests for snap and scale improvements.
This commit is contained in:
parent
e9d86822df
commit
834dfa6614
|
|
@ -511,19 +511,52 @@ VariantsCollectorBase::create_var_instances_non_tl_invariant (db::Cell &in_cell,
|
|||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> >::const_iterator f = var_table.find (i->object ().cell_index ());
|
||||
if (f == var_table.end ()) {
|
||||
|
||||
in_cell.insert (*i);
|
||||
in_cell.insert (*i);
|
||||
|
||||
} else {
|
||||
|
||||
const std::map<db::ICplxTrans, db::cell_index_type> &vt = f->second;
|
||||
|
||||
for (db::CellInstArray::iterator ia = i->begin (); ! ia.at_end (); ++ia) {
|
||||
bool need_explode = false;
|
||||
bool first = true;
|
||||
db::cell_index_type ci = 0;
|
||||
|
||||
for (db::CellInstArray::iterator ia = i->begin (); ! ia.at_end () && ! need_explode; ++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 ());
|
||||
|
||||
in_cell.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (v->second), i->complex_trans (*ia)), i->properties_id ()));
|
||||
if (first) {
|
||||
ci = v->second;
|
||||
first = false;
|
||||
} else {
|
||||
need_explode = (ci != v->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (need_explode) {
|
||||
|
||||
for (db::CellInstArray::iterator ia = i->begin (); ! ia.at_end (); ++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 ());
|
||||
|
||||
in_cell.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (v->second), i->complex_trans (*ia)), i->properties_id ()));
|
||||
|
||||
}
|
||||
|
||||
} else if (ci != i->object ().cell_index ()) {
|
||||
|
||||
db::CellInstArray new_array = *i;
|
||||
new_array.object () = db::CellInst (ci);
|
||||
in_cell.insert (db::CellInstArrayWithProperties (new_array, i->properties_id ()));
|
||||
|
||||
} else {
|
||||
|
||||
in_cell.insert (*i);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -287,6 +287,32 @@ private:
|
|||
db::Coord m_tolerance;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A fuzzy compare operator for edge pairs
|
||||
* Compares two edge pair objects applying a tolerance between them. The tolerance is the allowed deviation
|
||||
* of points in database units.
|
||||
*/
|
||||
struct EdgePairCompareOpWithTolerance
|
||||
{
|
||||
EdgePairCompareOpWithTolerance (db::Coord tolerance)
|
||||
: m_ec (tolerance)
|
||||
{ }
|
||||
|
||||
bool operator() (const db::EdgePair &a, const db::EdgePair &b) const
|
||||
{
|
||||
if (m_ec (a.first (), b.first ())) {
|
||||
return true;
|
||||
} else if (m_ec (b.first (), a.first ())) {
|
||||
return false;
|
||||
} else {
|
||||
return m_ec (a.second (), b.second ());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EdgeCompareOpWithTolerance m_ec;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A fuzzy compare operator for boxes
|
||||
* Compares two box objects applying a tolerance between them. The tolerance is the allowed deviation
|
||||
|
|
@ -492,6 +518,12 @@ make_edge_compare_func (db::Coord tolerance)
|
|||
return pair_compare_func<db::Edge, db::properties_id_type, EdgeCompareOpWithTolerance, std_compare_func<db::properties_id_type> > (EdgeCompareOpWithTolerance (tolerance), std_compare_func<db::properties_id_type> ());
|
||||
}
|
||||
|
||||
pair_compare_func<db::EdgePair, db::properties_id_type, EdgePairCompareOpWithTolerance, std_compare_func<db::properties_id_type> >
|
||||
make_edge_pair_compare_func (db::Coord tolerance)
|
||||
{
|
||||
return pair_compare_func<db::EdgePair, db::properties_id_type, EdgePairCompareOpWithTolerance, std_compare_func<db::properties_id_type> > (EdgePairCompareOpWithTolerance (tolerance), std_compare_func<db::properties_id_type> ());
|
||||
}
|
||||
|
||||
pair_compare_func<db::Box, db::properties_id_type, BoxCompareOpWithTolerance, std_compare_func<db::properties_id_type> >
|
||||
make_box_compare_func (db::Coord tolerance)
|
||||
{
|
||||
|
|
@ -540,6 +572,21 @@ collect_edges (const db::Layout & /*l*/, const db::Cell *c, unsigned int layer,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
collect_edge_pairs (const db::Layout & /*l*/, const db::Cell *c, unsigned int layer, unsigned int flags, std::vector< std::pair<db::EdgePair, db::properties_id_type> > &shapes, PropertyMapper &pn)
|
||||
{
|
||||
shapes.clear ();
|
||||
|
||||
for (db::ShapeIterator s = c->shapes (layer).begin (db::ShapeIterator::EdgePairs); !s.at_end (); ++s) {
|
||||
db::properties_id_type prop_id = 0;
|
||||
if (! (flags & layout_diff::f_no_properties)) {
|
||||
prop_id = pn (s->prop_id ());
|
||||
}
|
||||
shapes.push_back (std::make_pair (db::EdgePair (), prop_id));
|
||||
s->edge_pair (shapes.back ().first);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
collect_boxes (const db::Layout &, const db::Cell *c, unsigned int layer, unsigned int flags, std::vector< std::pair<db::Box, db::properties_id_type> > &shapes, PropertyMapper &pn)
|
||||
{
|
||||
|
|
@ -828,6 +875,8 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
std::vector <std::pair <db::Box, db::properties_id_type> > boxes_b;
|
||||
std::vector <std::pair <db::Edge, db::properties_id_type> > edges_a;
|
||||
std::vector <std::pair <db::Edge, db::properties_id_type> > edges_b;
|
||||
std::vector <std::pair <db::EdgePair, db::properties_id_type> > edge_pairs_a;
|
||||
std::vector <std::pair <db::EdgePair, db::properties_id_type> > edge_pairs_b;
|
||||
|
||||
for (unsigned int cci = 0; cci < common_cells.size (); ++cci) {
|
||||
|
||||
|
|
@ -1053,6 +1102,31 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
r.end_edge_differences ();
|
||||
}
|
||||
|
||||
// compare edge pairs
|
||||
|
||||
edge_pairs_a.clear();
|
||||
edge_pairs_b.clear();
|
||||
if (is_valid_a) {
|
||||
collect_edge_pairs (a, cell_a, layer_a, flags, edge_pairs_a, prop_normalize_a);
|
||||
}
|
||||
if (is_valid_b) {
|
||||
collect_edge_pairs (b, cell_b, layer_b, flags, edge_pairs_b, prop_normalize_b);
|
||||
}
|
||||
|
||||
reduce (edge_pairs_a, edge_pairs_b, make_edge_pair_compare_func (tolerance), tolerance > 0);
|
||||
|
||||
if (!edge_pairs_a.empty () || !edge_pairs_b.empty ()) {
|
||||
differs = true;
|
||||
if (flags & layout_diff::f_silent) {
|
||||
return false;
|
||||
}
|
||||
r.begin_edge_pair_differences ();
|
||||
if (verbose) {
|
||||
r.detailed_diff (n.properties_repository (), edge_pairs_a, edge_pairs_b);
|
||||
}
|
||||
r.end_edge_pair_differences ();
|
||||
}
|
||||
|
||||
r.end_layer ();
|
||||
|
||||
}
|
||||
|
|
@ -1130,6 +1204,9 @@ public:
|
|||
void begin_edge_differences ();
|
||||
void detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Edge, db::properties_id_type> > &a, const std::vector <std::pair <db::Edge, db::properties_id_type> > &b);
|
||||
void end_edge_differences ();
|
||||
void begin_edge_pair_differences ();
|
||||
void detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::EdgePair, db::properties_id_type> > &a, const std::vector <std::pair <db::EdgePair, db::properties_id_type> > &b);
|
||||
void end_edge_pair_differences ();
|
||||
void begin_text_differences ();
|
||||
void detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::Text, db::properties_id_type> > &a, const std::vector <std::pair <db::Text, db::properties_id_type> > &b);
|
||||
void end_text_differences ();
|
||||
|
|
@ -1525,6 +1602,34 @@ PrintingDifferenceReceiver::end_edge_differences ()
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::begin_edge_pair_differences ()
|
||||
{
|
||||
try {
|
||||
enough (tl::error) << "Edge pairs differ for layer " << m_layer.to_string () << " in cell " << m_cellname;
|
||||
} catch (tl::CancelException &) {
|
||||
// ignore cancel exceptions
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::detailed_diff (const db::PropertiesRepository &pr, const std::vector <std::pair <db::EdgePair, db::properties_id_type> > &a, const std::vector <std::pair <db::EdgePair, db::properties_id_type> > &b)
|
||||
{
|
||||
try {
|
||||
enough (tl::info) << "Not in b but in a:";
|
||||
print_diffs (pr, a, b);
|
||||
enough (tl::info) << "Not in a but in b:";
|
||||
print_diffs (pr, b, a);
|
||||
} catch (tl::CancelException &) {
|
||||
// ignore cancel exceptions
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::end_edge_pair_differences ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::begin_text_differences ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,6 +119,9 @@ public:
|
|||
virtual void begin_edge_differences () { }
|
||||
virtual void detailed_diff (const db::PropertiesRepository & /*pr*/, const std::vector <std::pair <db::Edge, db::properties_id_type> > & /*a*/, const std::vector <std::pair <db::Edge, db::properties_id_type> > & /*b*/) { }
|
||||
virtual void end_edge_differences () { }
|
||||
virtual void begin_edge_pair_differences () { }
|
||||
virtual void detailed_diff (const db::PropertiesRepository & /*pr*/, const std::vector <std::pair <db::EdgePair, db::properties_id_type> > & /*a*/, const std::vector <std::pair <db::EdgePair, db::properties_id_type> > & /*b*/) { }
|
||||
virtual void end_edge_pair_differences () { }
|
||||
virtual void begin_text_differences () { }
|
||||
virtual void detailed_diff (const db::PropertiesRepository & /*pr*/, const std::vector <std::pair <db::Text, db::properties_id_type> > & /*a*/, const std::vector <std::pair <db::Text, db::properties_id_type> > & /*b*/) { }
|
||||
virtual void end_text_differences () { }
|
||||
|
|
|
|||
|
|
@ -507,9 +507,6 @@ scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db
|
|||
|
||||
std::vector<db::Point> heap;
|
||||
std::vector<db::Vector> iterated_array_vectors;
|
||||
std::vector<db::CellInstArrayWithProperties> new_insts_with_props;
|
||||
std::vector<db::CellInstArray> new_insts;
|
||||
std::vector<db::Instance> instances_to_replace;
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
|
|
@ -530,8 +527,7 @@ scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db
|
|||
for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) {
|
||||
|
||||
db::Shapes &s = c->shapes ((*l).first);
|
||||
|
||||
// TODO: properties, edges, edge pairs
|
||||
db::Shapes new_shapes;
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes); ! si.at_end (); ++si) {
|
||||
|
||||
|
|
@ -541,7 +537,11 @@ scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db
|
|||
poly = scaled_and_snapped_polygon (poly, g, m, d, tr_disp.x (), g, m, d, tr_disp.y (), heap);
|
||||
poly.transform (trinv);
|
||||
|
||||
s.replace (*si, poly);
|
||||
if (si->is_box () && poly.is_box ()) {
|
||||
new_shapes.insert (db::BoxWithProperties (poly.box (), si->prop_id ()));
|
||||
} else {
|
||||
new_shapes.insert (db::PolygonWithProperties (poly, si->prop_id ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -553,7 +553,7 @@ scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db
|
|||
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);
|
||||
|
||||
s.replace (*si, text);
|
||||
new_shapes.insert (db::TextWithProperties (text, si->prop_id ()));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -565,7 +565,7 @@ scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db
|
|||
edge = scaled_and_snapped_edge (edge, g, m , d, tr_disp.x (), tr_disp.y ());
|
||||
edge.transform (trinv);
|
||||
|
||||
s.replace (*si, edge);
|
||||
new_shapes.insert (db::EdgeWithProperties (edge, si->prop_id ()));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -578,127 +578,56 @@ scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db
|
|||
scaled_and_snapped_edge (edge_pair.second (), g, m , d, tr_disp.x (), tr_disp.y ()));
|
||||
edge_pair.transform (trinv);
|
||||
|
||||
s.replace (*si, edge_pair);
|
||||
new_shapes.insert (db::EdgePairWithProperties (edge_pair, si->prop_id ()));
|
||||
|
||||
}
|
||||
|
||||
s.swap (new_shapes);
|
||||
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
new_insts.clear ();
|
||||
new_insts_with_props.clear ();
|
||||
instances_to_replace.clear ();
|
||||
// The variant formation also made sure the iterated and regular arrays are exploded where required.
|
||||
|
||||
for (db::Cell::const_iterator inst = c->begin (); ! inst.at_end (); ++inst) {
|
||||
|
||||
const db::CellInstArray &ia = inst->cell_inst ();
|
||||
|
||||
// shortcut if we do not need to explode the array
|
||||
|
||||
iterated_array_vectors.clear ();
|
||||
db::Vector a, b;
|
||||
unsigned long na, nb;
|
||||
|
||||
bool need_explode = false;
|
||||
db::CellInstArray new_array (ia);
|
||||
|
||||
if (tr.is_complex ()) {
|
||||
if (ia.is_iterated_array (&iterated_array_vectors)) {
|
||||
|
||||
need_explode = ia.size () > 1;
|
||||
|
||||
} else if (ia.is_iterated_array (&iterated_array_vectors)) {
|
||||
|
||||
for (std::vector<db::Vector>::const_iterator i = iterated_array_vectors.begin (); ! need_explode && i != iterated_array_vectors.end (); ++i) {
|
||||
need_explode = ! is_on_grid (*i, g, m, d);
|
||||
bool needs_update = false;
|
||||
for (std::vector<db::Vector>::iterator i = iterated_array_vectors.begin (); i != iterated_array_vectors.end (); ++i) {
|
||||
db::Vector v = scaled_and_snapped_vector (*i, g, m, d, tr_disp.x (), g, m, d, tr_disp.y ());
|
||||
if (v != *i) {
|
||||
needs_update = true;
|
||||
*i = v;
|
||||
}
|
||||
}
|
||||
|
||||
if (! need_explode) {
|
||||
|
||||
bool needs_update = false;
|
||||
for (std::vector<db::Vector>::iterator i = iterated_array_vectors.begin (); ! need_explode && i != iterated_array_vectors.end (); ++i) {
|
||||
db::Vector v = scaled_and_snapped_vector (*i, g, m, d, tr_disp.x (), g, m, d, tr_disp.y ());
|
||||
if (v != *i) {
|
||||
needs_update = true;
|
||||
*i = v;
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_update) {
|
||||
if (ia.is_complex ()) {
|
||||
new_array = db::CellInstArray (ia.object (), ia.complex_trans (ia.front ()), iterated_array_vectors.begin (), iterated_array_vectors.end ());
|
||||
} else {
|
||||
new_array = db::CellInstArray (ia.object (), ia.front (), iterated_array_vectors.begin (), iterated_array_vectors.end ());
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_update) {
|
||||
new_array = db::CellInstArray (ia.object (), ia.complex_trans (ia.front ()), iterated_array_vectors.begin (), iterated_array_vectors.end ());
|
||||
}
|
||||
|
||||
} else if (ia.is_regular_array (a, b, na, nb)) {
|
||||
|
||||
need_explode = (na > 1 && ! is_on_grid (a, g, m, d)) && (nb > 1 && ! is_on_grid (b, g, m, d));
|
||||
a = scaled_and_snapped_vector (a, g, m, d, tr_disp.x (), g, m, d, tr_disp.y ());
|
||||
b = scaled_and_snapped_vector (b, g, m, d, tr_disp.x (), g, m, d, tr_disp.y ());
|
||||
|
||||
if (! need_explode) {
|
||||
|
||||
a = scaled_and_snapped_vector (a, g, m, d, tr_disp.x (), g, m, d, tr_disp.y ());
|
||||
b = scaled_and_snapped_vector (b, g, m, d, tr_disp.x (), g, m, d, tr_disp.y ());
|
||||
|
||||
if (ia.is_complex ()) {
|
||||
new_array = db::CellInstArray (ia.object (), ia.complex_trans (ia.front ()), a, b, na, nb);
|
||||
} else {
|
||||
new_array = db::CellInstArray (ia.object (), ia.front (), a, b, na, nb);
|
||||
}
|
||||
|
||||
}
|
||||
new_array = db::CellInstArray (ia.object (), ia.complex_trans (ia.front ()), a, b, na, nb);
|
||||
|
||||
}
|
||||
|
||||
if (! need_explode) {
|
||||
scale_and_snap_cell_instance (new_array, tr, trinv, tr_disp, g, m, d);
|
||||
c->replace (*inst, new_array);
|
||||
|
||||
scale_and_snap_cell_instance (new_array, tr, trinv, tr_disp, g, m, d);
|
||||
c->replace (*inst, new_array);
|
||||
|
||||
} else {
|
||||
|
||||
instances_to_replace.push_back (*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);
|
||||
|
||||
db::CellInstArray new_array;
|
||||
if (ia.is_complex ()) {
|
||||
new_array = db::CellInstArray (ia.object (), ia.complex_trans (ti));
|
||||
} else {
|
||||
new_array = db::CellInstArray (ia.object (), ti);
|
||||
}
|
||||
|
||||
if (inst->prop_id () > 0) {
|
||||
new_insts_with_props.push_back (db::CellInstArrayWithProperties (new_array, inst->prop_id ()));
|
||||
} else {
|
||||
new_insts.push_back (new_array);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
c->erase_insts (instances_to_replace);
|
||||
for (std::vector<db::CellInstArray>::const_iterator i = new_insts.begin (); i != new_insts.end (); ++i) {
|
||||
c->insert (*i);
|
||||
}
|
||||
for (std::vector<db::CellInstArrayWithProperties>::const_iterator i = new_insts_with_props.begin (); i != new_insts_with_props.end (); ++i) {
|
||||
c->insert (*i);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ void compare_layouts (tl::TestBase *_this, const db::Layout &layout, const std::
|
|||
equal = db::compare_layouts (*subject, layout_au,
|
||||
(n > 0 ? db::layout_diff::f_silent : db::layout_diff::f_verbose)
|
||||
| ((norm & AsPolygons) != 0 ? db::layout_diff::f_boxes_as_polygons + db::layout_diff::f_paths_as_polygons : 0)
|
||||
| db::layout_diff::f_flatten_array_insts
|
||||
| ((norm & WithArrays) != 0 ? 0 : db::layout_diff::f_flatten_array_insts)
|
||||
/*| db::layout_diff::f_no_text_details | db::layout_diff::f_no_text_orientation*/
|
||||
, tolerance, 100 /*max diff lines*/);
|
||||
if (equal && n > 0) {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ enum NormalizationMode
|
|||
WriteOAS = 2, // normalize subject by writing to OASIS and reading back
|
||||
NormFileMask = 7, // bits the extract for file mode
|
||||
NoContext = 8, // write tmp file without context
|
||||
AsPolygons = 16 // paths and boxes are treated as polygons
|
||||
AsPolygons = 16, // paths and boxes are treated as polygons
|
||||
WithArrays = 32 // do not flatten arrays
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include "dbCellMapping.h"
|
||||
#include "dbTestSupport.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbLayoutDiff.h"
|
||||
#include "dbPropertiesRepository.h"
|
||||
#include "tlString.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
|
|
@ -653,3 +655,127 @@ TEST(18_scale_and_snap)
|
|||
CHECKPOINT();
|
||||
db::compare_layouts (_this, l1, tl::testdata () + "/algo/layout_utils_au_sns3.gds");
|
||||
}
|
||||
|
||||
TEST(19_scale_and_snap_basic)
|
||||
{
|
||||
db::Layout l1;
|
||||
db::Layout l2;
|
||||
|
||||
db::PropertiesRepository::properties_set ps1;
|
||||
ps1.insert (std::make_pair (l1.properties_repository ().prop_name_id (tl::Variant ("p")), tl::Variant (17)));
|
||||
db::properties_id_type pid1 = l1.properties_repository ().properties_id (ps1);
|
||||
|
||||
db::PropertiesRepository::properties_set ps2;
|
||||
ps2.insert (std::make_pair (l2.properties_repository ().prop_name_id (tl::Variant ("p")), tl::Variant (17)));
|
||||
db::properties_id_type pid2 = l2.properties_repository ().properties_id (ps2);
|
||||
|
||||
db::Cell &top1 = l1.cell (l1.add_cell ("TOP"));
|
||||
db::Cell &top2 = l2.cell (l2.add_cell ("TOP"));
|
||||
|
||||
db::Cell &a1 = l1.cell (l1.add_cell ("A"));
|
||||
db::Cell &a2a = l2.cell (l2.add_cell ("A"));
|
||||
|
||||
unsigned int layer1 = l1.insert_layer (db::LayerProperties (1, 0));
|
||||
unsigned int layer2 = l2.insert_layer (db::LayerProperties (1, 0));
|
||||
|
||||
a1.shapes (layer1).insert (db::Box (0, 0, 100, 100));
|
||||
a2a.shapes (layer2).insert (db::Box (0, 0, 100, 100));
|
||||
|
||||
top1.shapes (layer1).insert (db::Box (11, 21, 31, 41));
|
||||
top2.shapes (layer2).insert (db::Box (10, 20, 30, 40));
|
||||
|
||||
top1.shapes (layer1).insert (db::BoxWithProperties (db::Box (11, 21, 31, 41), pid1));
|
||||
top2.shapes (layer2).insert (db::BoxWithProperties (db::Box (10, 20, 30, 40), pid2));
|
||||
|
||||
top1.shapes (layer1).insert (db::Edge (11, 21, 31, 41));
|
||||
top2.shapes (layer2).insert (db::Edge (10, 20, 30, 40));
|
||||
|
||||
top1.shapes (layer1).insert (db::EdgeWithProperties (db::Edge (11, 21, 31, 41), pid1));
|
||||
top2.shapes (layer2).insert (db::EdgeWithProperties (db::Edge (10, 20, 30, 40), pid2));
|
||||
|
||||
top1.shapes (layer1).insert (db::EdgePair (db::Edge (11, 21, 31, 41), db::Edge (111, 121, 131, 141)));
|
||||
top2.shapes (layer2).insert (db::EdgePair (db::Edge (10, 20, 30, 40), db::Edge (110, 120, 130, 140)));
|
||||
|
||||
top1.shapes (layer1).insert (db::EdgePairWithProperties (db::EdgePair (db::Edge (11, 21, 31, 41), db::Edge (111, 121, 131, 141)), pid1));
|
||||
top2.shapes (layer2).insert (db::EdgePairWithProperties (db::EdgePair (db::Edge (10, 20, 30, 40), db::Edge (110, 120, 130, 140)), pid2));
|
||||
|
||||
top1.shapes (layer1).insert (db::Polygon (db::Box (11, 21, 31, 41)));
|
||||
top2.shapes (layer2).insert (db::Polygon (db::Box (10, 20, 30, 40)));
|
||||
|
||||
top1.shapes (layer1).insert (db::PolygonWithProperties (db::Polygon (db::Box (11, 21, 31, 41)), pid1));
|
||||
top2.shapes (layer2).insert (db::PolygonWithProperties (db::Polygon (db::Box (10, 20, 30, 40)), pid2));
|
||||
|
||||
db::Point pts1[] = {
|
||||
db::Point (1, 101),
|
||||
db::Point (101, 101),
|
||||
db::Point (101, 201)
|
||||
};
|
||||
|
||||
db::Point pts2[] = {
|
||||
db::Point (0, 100),
|
||||
db::Point (100, 100),
|
||||
db::Point (100, 200)
|
||||
};
|
||||
|
||||
top1.shapes (layer1).insert (db::Path (&pts1 [0], &pts1 [sizeof (pts1) / sizeof(pts1 [0])], 20));
|
||||
top2.shapes (layer2).insert (db::Path (&pts2 [0], &pts2 [sizeof (pts2) / sizeof(pts2 [0])], 20));
|
||||
|
||||
top1.shapes (layer1).insert (db::PathWithProperties (db::Path (&pts1 [0], &pts1 [sizeof (pts1) / sizeof(pts1 [0])], 20), pid1));
|
||||
top2.shapes (layer2).insert (db::PathWithProperties (db::Path (&pts2 [0], &pts2 [sizeof (pts2) / sizeof(pts2 [0])], 20), pid2));
|
||||
|
||||
top1.shapes (layer1).insert (db::Text ("t1", db::Trans (db::Vector (11, 21))));
|
||||
top2.shapes (layer2).insert (db::Text ("t1", db::Trans (db::Vector (10, 20))));
|
||||
|
||||
top1.shapes (layer1).insert (db::TextWithProperties (db::Text ("t1", db::Trans (db::Vector (11, 21))), pid1));
|
||||
top2.shapes (layer2).insert (db::TextWithProperties (db::Text ("t1", db::Trans (db::Vector (10, 20))), pid2));
|
||||
|
||||
top1.insert (db::CellInstArray (db::CellInst (a1.cell_index ()), db::Trans (db::Vector (11, 21))));
|
||||
top2.insert (db::CellInstArray (db::CellInst (a2a.cell_index ()), db::Trans (db::Vector (10, 20))));
|
||||
|
||||
top1.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (a1.cell_index ()), db::Trans (db::Vector (11, 21))), pid1));
|
||||
top2.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (a2a.cell_index ()), db::Trans (db::Vector (10, 20))), pid2));
|
||||
|
||||
top1.insert (db::CellInstArray (db::CellInst (a1.cell_index ()), db::Trans (db::Vector (11, 21)), db::Vector (0, 10), db::Vector (10, 0), 2, 3));
|
||||
top2.insert (db::CellInstArray (db::CellInst (a2a.cell_index ()), db::Trans (db::Vector (10, 20)), db::Vector (0, 10), db::Vector (10, 0), 2, 3));
|
||||
|
||||
top1.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (a1.cell_index ()), db::Trans (db::Vector (11, 21)), db::Vector (0, 10), db::Vector (10, 0), 2, 3), pid1));
|
||||
top2.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (a2a.cell_index ()), db::Trans (db::Vector (10, 20)), db::Vector (0, 10), db::Vector (10, 0), 2, 3), pid2));
|
||||
|
||||
std::vector<db::Vector> ia;
|
||||
ia.push_back (db::Vector (0, 0));
|
||||
ia.push_back (db::Vector (10, 0));
|
||||
ia.push_back (db::Vector (0, 10));
|
||||
|
||||
top1.insert (db::CellInstArray (db::CellInst (a1.cell_index ()), db::Trans (db::Vector (11, 21)), ia.begin (), ia.end ()));
|
||||
top2.insert (db::CellInstArray (db::CellInst (a2a.cell_index ()), db::Trans (db::Vector (10, 20)), ia.begin (), ia.end ()));
|
||||
|
||||
top1.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (a1.cell_index ()), db::Trans (db::Vector (11, 21)), ia.begin (), ia.end ()), pid1));
|
||||
top2.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (a2a.cell_index ()), db::Trans (db::Vector (10, 20)), ia.begin (), ia.end ()), pid2));
|
||||
|
||||
db::scale_and_snap (l1, top1, 10, 1, 1);
|
||||
|
||||
bool equal = db::compare_layouts (l1, l2,
|
||||
db::layout_diff::f_verbose
|
||||
| db::layout_diff::f_boxes_as_polygons
|
||||
| db::layout_diff::f_paths_as_polygons
|
||||
, 0, 100 /*max diff lines*/);
|
||||
EXPECT_EQ (equal, true);
|
||||
}
|
||||
|
||||
TEST(20_scale_and_snap)
|
||||
{
|
||||
db::Layout l1;
|
||||
{
|
||||
std::string fn (tl::testdata ());
|
||||
fn += "/algo/scale_and_snap4.oas";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (l1);
|
||||
}
|
||||
|
||||
db::scale_and_snap (l1, l1.cell (*l1.begin_top_down ()), 10, 95, 100);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, l1, tl::testdata () + "/algo/layout_utils_au_sns4.oas", db::NormalizationMode (db::WriteOAS + db::WithArrays));
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue