mirror of https://github.com/KLayout/klayout.git
WIP: tests for local processor flat mode
This commit is contained in:
parent
00ae88a5d4
commit
ec01c9b72b
|
|
@ -1655,6 +1655,13 @@ struct scan_shape2shape_same_layer
|
|||
|
||||
scanner.process (rec, dist, db::box_convert<TS> (), db::box_convert<TI> ());
|
||||
}
|
||||
|
||||
void
|
||||
operator () (const db::Shapes *, unsigned int, unsigned int, shape_interactions<TS, TI> &, db::Coord) const
|
||||
{
|
||||
// cannot have different types on the same layer
|
||||
tl_assert (false);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
|
@ -1679,13 +1686,28 @@ struct scan_shape2shape_same_layer<T, T>
|
|||
|
||||
scanner.process (rec, dist, db::box_convert<T> ());
|
||||
}
|
||||
|
||||
void
|
||||
operator () (const db::Shapes *shapes, unsigned int subject_id0, unsigned int intruder_layer, shape_interactions<T, T> &interactions, db::Coord dist) const
|
||||
{
|
||||
db::box_scanner<T, int> scanner;
|
||||
interaction_registration_shape1<T, T> rec (&interactions, intruder_layer);
|
||||
|
||||
unsigned int id = subject_id0;
|
||||
for (db::Shapes::shape_iterator i = shapes->begin (shape_flags<T> ()); !i.at_end (); ++i) {
|
||||
const T *ref = i->basic_ptr (typename T::tag ());
|
||||
scanner.insert (ref, id++);
|
||||
}
|
||||
|
||||
scanner.process (rec, dist, db::box_convert<T> ());
|
||||
}
|
||||
};
|
||||
|
||||
template <class TS, class TI>
|
||||
struct scan_shape2shape_different_layers
|
||||
{
|
||||
void
|
||||
operator () (db::Layout *layout, const db::Shapes *subject_shapes, const db::Shapes *intruder_shapes, unsigned int subject_id0, const std::set<TI> &intruders, unsigned int intruder_layer, shape_interactions<TS, TI> &interactions, db::Coord dist)
|
||||
operator () (db::Layout *layout, const db::Shapes *subject_shapes, const db::Shapes *intruder_shapes, unsigned int subject_id0, const std::set<TI> *intruders, unsigned int intruder_layer, shape_interactions<TS, TI> &interactions, db::Coord dist) const
|
||||
{
|
||||
db::box_scanner2<TS, int, TI, int> scanner;
|
||||
interaction_registration_shape2shape<TS, TI> rec (layout, &interactions, intruder_layer);
|
||||
|
|
@ -1697,9 +1719,11 @@ struct scan_shape2shape_different_layers
|
|||
}
|
||||
|
||||
// TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
for (typename std::set<TI>::const_iterator i = intruders.begin (); i != intruders.end (); ++i) {
|
||||
if (intruders) {
|
||||
for (typename std::set<TI>::const_iterator i = intruders->begin (); i != intruders->end (); ++i) {
|
||||
scanner.insert2 (i.operator-> (), interactions.next_id ());
|
||||
}
|
||||
}
|
||||
|
||||
if (intruder_shapes) {
|
||||
// TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
|
|
@ -1763,7 +1787,7 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
|
|||
} else {
|
||||
|
||||
db::Layout *target_layout = (mp_subject_layout == mp_intruder_layout ? 0 : mp_subject_layout);
|
||||
scan_shape2shape_different_layers<TS, TI> () (target_layout, subject_shapes, intruder_shapes, subject_id0, ipl == intruders.second.end () ? empty_intruders : ipl->second, *il, interactions, op->dist ());
|
||||
scan_shape2shape_different_layers<TS, TI> () (target_layout, subject_shapes, intruder_shapes, subject_id0, &(ipl == intruders.second.end () ? empty_intruders : ipl->second), *il, interactions, op->dist ());
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1825,6 +1849,88 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
|
|||
}
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void
|
||||
local_processor<TS, TI, TR>::run_flat (const db::Shapes *subject_shapes, const db::Shapes *intruders, const local_operation<TS, TI, TR> *op, db::Shapes *result_shapes) const
|
||||
{
|
||||
std::vector<const db::Shapes *> is;
|
||||
is.push_back (intruders);
|
||||
|
||||
std::vector<db::Shapes *> os;
|
||||
os.push_back (result_shapes);
|
||||
|
||||
run_flat (subject_shapes, is, op, os);
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void
|
||||
local_processor<TS, TI, TR>::run_flat (const db::Shapes *subject_shapes, const std::vector<const db::Shapes *> &intruders, const local_operation<TS, TI, TR> *op, const std::vector<db::Shapes *> &result_shapes) const
|
||||
{
|
||||
tl_assert (mp_subject_top == 0);
|
||||
tl_assert (mp_intruder_top == 0);
|
||||
|
||||
shape_interactions<TS, TI> interactions;
|
||||
|
||||
for (std::vector<const db::Shapes *>::const_iterator il = intruders.begin (); il != intruders.end (); ++il) {
|
||||
|
||||
const db::Shapes *intruder_shapes = *il;
|
||||
|
||||
// insert dummy interactions to accommodate subject vs. nothing and assign an ID
|
||||
// range for the subject shapes.
|
||||
unsigned int subject_id0 = 0;
|
||||
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
|
||||
|
||||
unsigned int id = interactions.next_id ();
|
||||
if (subject_id0 == 0) {
|
||||
subject_id0 = id;
|
||||
}
|
||||
|
||||
if (op->on_empty_intruder_hint () != local_operation<TS, TI, TR>::Drop) {
|
||||
const TS *ref = i->basic_ptr (typename TS::tag ());
|
||||
interactions.add_subject (id, *ref);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static std::set<TI> empty_intruders;
|
||||
|
||||
if (! subject_shapes->empty () && intruder_shapes) {
|
||||
|
||||
if (intruder_shapes == subject_shapes) {
|
||||
scan_shape2shape_same_layer<TS, TI> () (subject_shapes, subject_id0, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
|
||||
} else {
|
||||
scan_shape2shape_different_layers<TS, TI> () (0 /*layout*/, subject_shapes, intruder_shapes, subject_id0, 0 /*ext. intruders*/, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (interactions.begin () != interactions.end ()) {
|
||||
|
||||
if (interactions.begin_intruders () == interactions.end_intruders ()) {
|
||||
|
||||
typename local_operation<TS, TI, TR>::on_empty_intruder_mode eh = op->on_empty_intruder_hint ();
|
||||
if (eh == local_operation<TS, TI, TR>::Drop) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::unordered_set<TR> > result;
|
||||
result.resize (result_shapes.size ());
|
||||
op->compute_local (mp_subject_layout, interactions, result, m_max_vertex_count, m_area_ratio);
|
||||
|
||||
for (std::vector<db::Shapes *>::const_iterator r = result_shapes.begin (); r != result_shapes.end (); ++r) {
|
||||
if (*r) {
|
||||
const std::unordered_set<TR> rs = result [r - result_shapes.begin ()];
|
||||
(*r)->insert (rs.begin (), rs.end ());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::Edge>;
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ template <class TS, class TI, class TR>
|
|||
class DB_PUBLIC local_processor
|
||||
{
|
||||
public:
|
||||
local_processor (db::Layout *layout, db::Cell *top, const std::set<db::cell_index_type> *breakout_cells = 0);
|
||||
local_processor (db::Layout *layout = 0, db::Cell *top = 0, const std::set<db::cell_index_type> *breakout_cells = 0);
|
||||
local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set<db::cell_index_type> *subject_breakout_cells = 0, const std::set<db::cell_index_type> *intruder_breakout_cells = 0);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layers);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, const std::vector<unsigned int> &output_layers);
|
||||
|
|
@ -383,6 +383,9 @@ public:
|
|||
void compute_contexts (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers) const;
|
||||
void compute_results (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, const std::vector<unsigned int> &output_layers) const;
|
||||
|
||||
void run_flat (const db::Shapes *subject_shapes, const db::Shapes *intruders, const local_operation<TS, TI, TR> *op, db::Shapes *result_shapes) const;
|
||||
void run_flat (const db::Shapes *subjects, const std::vector<const db::Shapes *> &intruders, const local_operation<TS, TI, TR> *op, const std::vector<db::Shapes *> &result_shapes) const;
|
||||
|
||||
void set_description (const std::string &d)
|
||||
{
|
||||
m_description = d;
|
||||
|
|
|
|||
|
|
@ -323,6 +323,110 @@ static void run_test_bool22 (tl::TestBase *_this, const char *file, TestMode mod
|
|||
run_test_bool_gen (_this, file, mode, out_layer_num1, out_layer_num2, context_doc, false, 0, nthreads);
|
||||
}
|
||||
|
||||
static void run_test_bool_gen_flat (tl::TestBase *_this, const char *file, TestMode mode, int out_layer_num1, int out_layer_num2, db::Coord dist)
|
||||
{
|
||||
db::Layout layout_org;
|
||||
|
||||
unsigned int l1 = 0, l2 = 0, lout1 = 0, lout2 = 0;
|
||||
db::LayerMap lmap;
|
||||
bool swap = (mode == TMAndSwapped || mode == TMNotSwapped);
|
||||
|
||||
{
|
||||
tl::InputStream stream (testdata (file));
|
||||
db::Reader reader (stream);
|
||||
|
||||
db::LayerProperties p;
|
||||
|
||||
p.layer = swap ? 2 : 1;
|
||||
p.datatype = 0;
|
||||
lmap.map (db::LDPair (p.layer, p.datatype), l1 = layout_org.insert_layer ());
|
||||
layout_org.set_properties (l1, p);
|
||||
|
||||
p.layer = swap ? 1 : 2;
|
||||
p.datatype = 0;
|
||||
if (mode == TMSelfOverlap) {
|
||||
lmap.map (db::LDPair (p.layer, p.datatype), l2 = l1);
|
||||
} else {
|
||||
lmap.map (db::LDPair (p.layer, p.datatype), l2 = layout_org.insert_layer ());
|
||||
layout_org.set_properties (l2, p);
|
||||
}
|
||||
|
||||
p.layer = out_layer_num1;
|
||||
p.datatype = 0;
|
||||
lmap.map (db::LDPair (out_layer_num1, 0), lout1 = layout_org.insert_layer ());
|
||||
layout_org.set_properties (lout1, p);
|
||||
|
||||
if (out_layer_num2 >= 0) {
|
||||
p.layer = out_layer_num2;
|
||||
p.datatype = 0;
|
||||
lmap.map (db::LDPair (out_layer_num2, 0), lout2 = layout_org.insert_layer ());
|
||||
layout_org.set_properties (lout2, p);
|
||||
}
|
||||
|
||||
db::LoadLayoutOptions options;
|
||||
options.get_options<db::CommonReaderOptions> ().layer_map = lmap;
|
||||
options.get_options<db::CommonReaderOptions> ().create_other_layers = false;
|
||||
reader.read (layout_org, options);
|
||||
}
|
||||
|
||||
db::Cell &top_cell = layout_org.cell (*layout_org.begin_top_down ());
|
||||
layout_org.flatten (top_cell, -1, true);
|
||||
|
||||
layout_org.clear_layer (lout1);
|
||||
if (out_layer_num2 >= 0) {
|
||||
layout_org.clear_layer (lout2);
|
||||
}
|
||||
normalize_layer (layout_org, l1);
|
||||
if (l1 != l2) {
|
||||
normalize_layer (layout_org, l2);
|
||||
}
|
||||
|
||||
db::local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> *lop = 0;
|
||||
db::BoolAndOrNotLocalOperation bool_op (mode == TMAnd || mode == TMAndSwapped);
|
||||
db::SelfOverlapMergeLocalOperation self_intersect_op (2);
|
||||
BoolAndOrNotWithSizedLocalOperation sized_bool_op (mode == TMAnd || mode == TMAndSwapped, dist);
|
||||
SelfOverlapWithSizedLocalOperation sized_self_intersect_op (2, dist);
|
||||
db::TwoBoolAndNotLocalOperation andnot;
|
||||
|
||||
if (mode == TMAndNot) {
|
||||
lop = &andnot;
|
||||
} else if (mode == TMSelfOverlap) {
|
||||
if (dist > 0) {
|
||||
lop = &sized_self_intersect_op;
|
||||
} else {
|
||||
lop = &self_intersect_op;
|
||||
}
|
||||
} else {
|
||||
if (dist > 0) {
|
||||
lop = &sized_bool_op;
|
||||
} else {
|
||||
lop = &bool_op;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const db::Shapes *> ilv;
|
||||
std::vector<db::Shapes *> olv;
|
||||
ilv.push_back (&top_cell.shapes (l2));
|
||||
olv.push_back (&top_cell.shapes (lout1));
|
||||
if (out_layer_num2 >= 0) {
|
||||
olv.push_back (&top_cell.shapes (lout2));
|
||||
}
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (&layout_org);
|
||||
proc.set_area_ratio (3.0);
|
||||
proc.set_max_vertex_count (16);
|
||||
|
||||
proc.run_flat (&top_cell.shapes (l1), ilv, lop, olv);
|
||||
|
||||
db::compare_layouts (_this, layout_org, testdata (file), lmap, false /*skip other layers*/, db::AsPolygons);
|
||||
}
|
||||
|
||||
static void run_test_bool22_flat (tl::TestBase *_this, const char *file, TestMode mode, int out_layer_num1, int out_layer_num2)
|
||||
{
|
||||
run_test_bool_gen_flat (_this, file, mode, out_layer_num1, out_layer_num2, 0);
|
||||
}
|
||||
|
||||
|
||||
TEST(BasicAnd1)
|
||||
{
|
||||
// Simple flat AND
|
||||
|
|
@ -1167,3 +1271,9 @@ TEST(MultipleOutputs)
|
|||
run_test_bool22 (_this, "hlp17.oas", TMAndNot, 100, 101);
|
||||
}
|
||||
|
||||
TEST(FlatOperation)
|
||||
{
|
||||
// Redundant hierarchy, NOT
|
||||
run_test_bool22_flat (_this, "hlp17_flat.oas", TMAndNot, 100, 101);
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue