mirror of https://github.com/KLayout/klayout.git
WIP: distance parameter for hierarchical processor.
This commit is contained in:
parent
824888aaa6
commit
defbf33d19
|
|
@ -289,8 +289,8 @@ struct InteractionRegistrationShape2Inst
|
|||
: db::box_scanner_receiver2<db::PolygonRef, int, db::CellInstArray, int>
|
||||
{
|
||||
public:
|
||||
InteractionRegistrationShape2Inst (db::Layout *layout, unsigned int intruder_layer, std::map<db::PolygonRef, std::vector<db::PolygonRef> > *result)
|
||||
: mp_layout (layout), m_intruder_layer (intruder_layer), mp_result (result)
|
||||
InteractionRegistrationShape2Inst (db::Layout *layout, unsigned int intruder_layer, db::Coord dist, std::map<db::PolygonRef, std::vector<db::PolygonRef> > *result)
|
||||
: mp_layout (layout), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result)
|
||||
{
|
||||
// nothing yet ..
|
||||
}
|
||||
|
|
@ -300,11 +300,11 @@ public:
|
|||
const db::Cell &intruder_cell = mp_layout->cell (inst->object ().cell_index ());
|
||||
db::box_convert <db::CellInst, true> inst_bc (*mp_layout, m_intruder_layer);
|
||||
|
||||
for (db::CellInstArray::iterator n = inst->begin_touching (ref->box ().enlarged (db::Vector (-1, -1)), inst_bc); !n.at_end (); ++n) {
|
||||
for (db::CellInstArray::iterator n = inst->begin_touching (ref->box ().enlarged (db::Vector (m_dist - 1, m_dist - 1)), inst_bc); !n.at_end (); ++n) {
|
||||
|
||||
db::ICplxTrans tn = inst->complex_trans (*n);
|
||||
|
||||
db::Box region = ref->box ().transformed (tn.inverted ()) & intruder_cell.bbox (m_intruder_layer);
|
||||
db::Box region = ref->box ().transformed (tn.inverted ()).enlarged (db::Vector (m_dist, m_dist)) & intruder_cell.bbox (m_intruder_layer).enlarged (db::Vector (m_dist, m_dist));
|
||||
if (! region.empty ()) {
|
||||
|
||||
// @@@ TODO: should be lighter, cache, handle arrays ..
|
||||
|
|
@ -312,7 +312,7 @@ public:
|
|||
si.shape_flags (polygon_ref_flags ());
|
||||
while (! si.at_end ()) {
|
||||
|
||||
// @@@ should be easier to transform references
|
||||
// @@@ it should be easier to transform references
|
||||
const db::PolygonRef *ref2 = si.shape ().basic_ptr (db::PolygonRef::tag ());
|
||||
db::Polygon poly = ref2->obj ().transformed (tn * si.trans () * db::ICplxTrans (ref2->trans ()));
|
||||
(*mp_result)[*ref].push_back (db::PolygonRef (poly, mp_layout->shape_repository()));
|
||||
|
|
@ -329,11 +329,12 @@ public:
|
|||
private:
|
||||
db::Layout *mp_layout;
|
||||
unsigned int m_intruder_layer;
|
||||
db::Coord m_dist;
|
||||
std::map<db::PolygonRef, std::vector<db::PolygonRef> > *mp_result;
|
||||
};
|
||||
|
||||
static bool
|
||||
instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, unsigned int layer1, const db::Layout *layout2, const db::CellInstArray *inst2, unsigned int layer2)
|
||||
instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, unsigned int layer1, const db::Layout *layout2, const db::CellInstArray *inst2, unsigned int layer2, db::Coord dist)
|
||||
{
|
||||
// TODO: this algorithm is not in particular effective for identical arrays
|
||||
|
||||
|
|
@ -347,7 +348,7 @@ instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, u
|
|||
|
||||
db::ICplxTrans tn1 = inst1->complex_trans (*n);
|
||||
db::ICplxTrans tni1 = tn1.inverted ();
|
||||
db::Box ibox1 = tn1 * cell1.bbox (layer1);
|
||||
db::Box ibox1 = tn1 * cell1.bbox (layer1).enlarged (db::Vector (dist, dist));
|
||||
|
||||
if (! ibox1.empty ()) {
|
||||
|
||||
|
|
@ -361,7 +362,9 @@ instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, u
|
|||
}
|
||||
|
||||
db::ICplxTrans tn2 = inst2->complex_trans (*k);
|
||||
db::Box ibox2 = tn2 * cell2.bbox (layer2);
|
||||
|
||||
// NOTE: we need to enlarge both subject *and* intruder boxes - either ubject comes close to intruder or the other way around
|
||||
db::Box ibox2 = tn2 * cell2.bbox (layer2).enlarged (db::Vector (dist, dist));
|
||||
|
||||
db::ICplxTrans tn21 = tni1 * tn2;
|
||||
if (! relative_trans_seen.insert (tn21).second) {
|
||||
|
|
@ -396,8 +399,8 @@ struct InteractionRegistrationInst2Inst
|
|||
: db::box_scanner_receiver2<db::CellInstArray, int, db::CellInstArray, int>
|
||||
{
|
||||
public:
|
||||
InteractionRegistrationInst2Inst (const db::Layout *subject_layout, unsigned int subject_layer, const db::Layout *intruder_layout, unsigned int intruder_layer, std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > > *result)
|
||||
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_subject_layer (subject_layer), m_intruder_layer (intruder_layer), mp_result (result)
|
||||
InteractionRegistrationInst2Inst (const db::Layout *subject_layout, unsigned int subject_layer, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > > *result)
|
||||
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_subject_layer (subject_layer), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result)
|
||||
{
|
||||
// nothing yet ..
|
||||
}
|
||||
|
|
@ -408,7 +411,7 @@ public:
|
|||
// NOTE: self-interactions are possible for arrays: different elements of the
|
||||
// array may interact which is a cell-external interaction.
|
||||
if ((*inst1 != *inst2 || inst1->size () > 1)
|
||||
&& instances_interact (mp_subject_layout, inst1, m_subject_layer, mp_intruder_layout, inst2, m_intruder_layer)) {
|
||||
&& instances_interact (mp_subject_layout, inst1, m_subject_layer, mp_intruder_layout, inst2, m_intruder_layer, m_dist)) {
|
||||
(*mp_result) [inst1].first.insert (inst2);
|
||||
}
|
||||
}
|
||||
|
|
@ -416,20 +419,21 @@ public:
|
|||
private:
|
||||
const db::Layout *mp_subject_layout, *mp_intruder_layout;
|
||||
unsigned int m_subject_layer, m_intruder_layer;
|
||||
db::Coord m_dist;
|
||||
std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > > *mp_result;
|
||||
};
|
||||
|
||||
static bool
|
||||
instance_shape_interacts (const db::Layout *layout, const db::CellInstArray *inst, unsigned int layer, const db::PolygonRef &ref)
|
||||
instance_shape_interacts (const db::Layout *layout, const db::CellInstArray *inst, unsigned int layer, const db::PolygonRef &ref, db::Coord dist)
|
||||
{
|
||||
const db::Cell &cell = layout->cell (inst->object ().cell_index ());
|
||||
db::box_convert <db::CellInst, true> inst_bc (*layout, layer);
|
||||
db::Box rbox = ref.box ();
|
||||
|
||||
for (db::CellInstArray::iterator n = inst->begin_touching (rbox.enlarged (db::Vector (-1, -1)), inst_bc); ! n.at_end (); ++n) {
|
||||
for (db::CellInstArray::iterator n = inst->begin_touching (rbox.enlarged (db::Vector (dist - 1, dist - 1)), inst_bc); ! n.at_end (); ++n) {
|
||||
|
||||
db::ICplxTrans tn = inst->complex_trans (*n);
|
||||
db::Box cbox = (tn * cell.bbox (layer)) & rbox;
|
||||
db::Box cbox = (tn * cell.bbox (layer)).enlarged (db::Vector (dist, dist)) & rbox.enlarged (db::Vector (dist, dist));
|
||||
|
||||
if (! cbox.empty ()) {
|
||||
|
||||
|
|
@ -452,15 +456,15 @@ struct InteractionRegistrationInst2Shape
|
|||
: db::box_scanner_receiver2<db::CellInstArray, int, db::PolygonRef, int>
|
||||
{
|
||||
public:
|
||||
InteractionRegistrationInst2Shape (const db::Layout *subject_layout, unsigned int subject_layer, std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > > *result)
|
||||
: mp_subject_layout (subject_layout), m_subject_layer (subject_layer), mp_result (result)
|
||||
InteractionRegistrationInst2Shape (const db::Layout *subject_layout, unsigned int subject_layer, db::Coord dist, std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > > *result)
|
||||
: mp_subject_layout (subject_layout), m_subject_layer (subject_layer), m_dist (dist), mp_result (result)
|
||||
{
|
||||
// nothing yet ..
|
||||
}
|
||||
|
||||
void add (const db::CellInstArray *inst, int, const db::PolygonRef *ref, int)
|
||||
{
|
||||
if (instance_shape_interacts (mp_subject_layout, inst, m_subject_layer, *ref)) {
|
||||
if (instance_shape_interacts (mp_subject_layout, inst, m_subject_layer, *ref, m_dist)) {
|
||||
(*mp_result) [inst].second.insert (*ref);
|
||||
}
|
||||
}
|
||||
|
|
@ -468,6 +472,7 @@ public:
|
|||
private:
|
||||
const db::Layout *mp_subject_layout;
|
||||
unsigned int m_subject_layer;
|
||||
db::Coord m_dist;
|
||||
std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > > *mp_result;
|
||||
};
|
||||
|
||||
|
|
@ -482,10 +487,10 @@ LocalProcessor::LocalProcessor (db::Layout *layout, db::Cell *top)
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void LocalProcessor::run (LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer, db::Coord dist)
|
||||
void LocalProcessor::run (LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer)
|
||||
{
|
||||
LocalProcessorContexts contexts;
|
||||
compute_contexts (contexts, op, subject_layer, intruder_layer, dist);
|
||||
compute_contexts (contexts, op, subject_layer, intruder_layer);
|
||||
compute_results (contexts, op, output_layer);
|
||||
}
|
||||
|
||||
|
|
@ -496,7 +501,7 @@ void LocalProcessor::push_results (db::Cell *cell, unsigned int output_layer, co
|
|||
}
|
||||
}
|
||||
|
||||
void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, db::Coord dist)
|
||||
void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Computing contexts for ")) + description ());
|
||||
|
||||
|
|
@ -506,10 +511,10 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, const L
|
|||
contexts.set_description (op->description ());
|
||||
|
||||
std::pair<std::set<db::CellInstArray>, std::set<db::PolygonRef> > intruders;
|
||||
compute_contexts (contexts, 0, 0, mp_top, db::ICplxTrans (), dist, intruders);
|
||||
compute_contexts (contexts, 0, 0, mp_top, db::ICplxTrans (), intruders, op->dist ());
|
||||
}
|
||||
|
||||
void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *parent, db::Cell *cell, const db::ICplxTrans &cell_inst, db::Coord dist, const std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders)
|
||||
void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *parent, db::Cell *cell, const db::ICplxTrans &cell_inst, const std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders, db::Coord dist)
|
||||
{
|
||||
if (tl::verbosity () >= 30) {
|
||||
if (! parent) {
|
||||
|
|
@ -549,7 +554,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc
|
|||
|
||||
{
|
||||
db::box_scanner2<db::CellInstArray, int, db::CellInstArray, int> scanner;
|
||||
InteractionRegistrationInst2Inst rec (mp_layout, contexts.subject_layer (), mp_layout, contexts.intruder_layer (), &interactions);
|
||||
InteractionRegistrationInst2Inst rec (mp_layout, contexts.subject_layer (), mp_layout, contexts.intruder_layer (), dist, &interactions);
|
||||
|
||||
for (db::Cell::const_iterator i = cell->begin (); !i.at_end (); ++i) {
|
||||
if (! inst_bcs (i->cell_inst ()).empty ()) {
|
||||
|
|
@ -566,12 +571,12 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc
|
|||
}
|
||||
}
|
||||
|
||||
scanner.process (rec, 0, inst_bcs, inst_bci);
|
||||
scanner.process (rec, dist, inst_bcs, inst_bci);
|
||||
}
|
||||
|
||||
{
|
||||
db::box_scanner2<db::CellInstArray, int, db::PolygonRef, int> scanner;
|
||||
InteractionRegistrationInst2Shape rec (mp_layout, contexts.subject_layer (), &interactions);
|
||||
InteractionRegistrationInst2Shape rec (mp_layout, contexts.subject_layer (), dist, &interactions);
|
||||
|
||||
for (db::Cell::const_iterator i = cell->begin (); !i.at_end (); ++i) {
|
||||
if (! inst_bcs (i->cell_inst ()).empty ()) {
|
||||
|
|
@ -586,7 +591,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc
|
|||
scanner.insert2 (i->basic_ptr (db::PolygonRef::tag ()), 0);
|
||||
}
|
||||
|
||||
scanner.process (rec, 0, inst_bcs, db::box_convert<db::PolygonRef> ());
|
||||
scanner.process (rec, dist, inst_bcs, db::box_convert<db::PolygonRef> ());
|
||||
}
|
||||
|
||||
for (std::map<const db::CellInstArray *, std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > >::const_iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
|
@ -597,7 +602,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc
|
|||
|
||||
db::ICplxTrans tn = i->first->complex_trans (*n);
|
||||
db::ICplxTrans tni = tn.inverted ();
|
||||
db::Box nbox = tn * child_cell.bbox (contexts.subject_layer ());
|
||||
db::Box nbox = tn * child_cell.bbox (contexts.subject_layer ()).enlarged (db::Vector (dist, dist));
|
||||
|
||||
if (! nbox.empty ()) {
|
||||
|
||||
|
|
@ -619,7 +624,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Loc
|
|||
}
|
||||
}
|
||||
|
||||
compute_contexts (contexts, context, cell, &child_cell, tn, dist, intruders_below);
|
||||
compute_contexts (contexts, context, cell, &child_cell, tn, intruders_below, dist);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -684,14 +689,14 @@ LocalProcessor::compute_local_cell (LocalProcessorContexts &contexts, db::Cell *
|
|||
scanner.insert2 (i->basic_ptr (db::PolygonRef::tag ()), 0);
|
||||
}
|
||||
|
||||
scanner.process (rec, 0, db::box_convert<db::PolygonRef> (), db::box_convert<db::PolygonRef> ());
|
||||
scanner.process (rec, op->dist (), db::box_convert<db::PolygonRef> (), db::box_convert<db::PolygonRef> ());
|
||||
|
||||
}
|
||||
|
||||
if (! shapes_subject.empty () && ! (cell->begin ().at_end () && intruders.first.empty ())) {
|
||||
|
||||
db::box_scanner2<db::PolygonRef, int, db::CellInstArray, int> scanner;
|
||||
InteractionRegistrationShape2Inst rec (mp_layout, contexts.intruder_layer (), &interactions);
|
||||
InteractionRegistrationShape2Inst rec (mp_layout, contexts.intruder_layer (), op->dist (), &interactions);
|
||||
|
||||
for (db::Shapes::shape_iterator i = shapes_subject.begin (polygon_ref_flags ()); !i.at_end (); ++i) {
|
||||
scanner.insert1 (i->basic_ptr (db::PolygonRef::tag ()), 0);
|
||||
|
|
@ -708,7 +713,7 @@ LocalProcessor::compute_local_cell (LocalProcessorContexts &contexts, db::Cell *
|
|||
}
|
||||
}
|
||||
|
||||
scanner.process (rec, 0, db::box_convert<db::PolygonRef> (), inst_bci);
|
||||
scanner.process (rec, op->dist (), db::box_convert<db::PolygonRef> (), inst_bci);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public:
|
|||
virtual void compute_local (db::Layout *layout, const std::map<db::PolygonRef, std::vector<db::PolygonRef> > &interactions, std::set<db::PolygonRef> &result) const = 0;
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const = 0;
|
||||
virtual std::string description () const = 0;
|
||||
virtual db::Coord dist () const { return 0; }
|
||||
};
|
||||
|
||||
class DB_PLUGIN_PUBLIC BoolAndOrNotLocalOperation
|
||||
|
|
@ -212,8 +213,8 @@ class DB_PLUGIN_PUBLIC LocalProcessor
|
|||
{
|
||||
public:
|
||||
LocalProcessor (db::Layout *layout, db::Cell *top);
|
||||
void run (LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer, db::Coord dist = 0);
|
||||
void compute_contexts (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, db::Coord dist = 0);
|
||||
void run (LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer);
|
||||
void compute_contexts (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int subject_layer, unsigned int intruder_layer);
|
||||
void compute_results (LocalProcessorContexts &contexts, const LocalOperation *op, unsigned int output_layer);
|
||||
|
||||
void set_description (const std::string &d)
|
||||
|
|
@ -233,7 +234,7 @@ private:
|
|||
db::Cell *mp_top;
|
||||
std::string m_description;
|
||||
|
||||
void compute_contexts (LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *parent, db::Cell *cell, const db::ICplxTrans &cell_inst, db::Coord dist, const std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders);
|
||||
void compute_contexts (LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *parent, db::Cell *cell, const db::ICplxTrans &cell_inst, const std::pair<std::set<CellInstArray>, std::set<PolygonRef> > &intruders, db::Coord dist);
|
||||
void push_results (db::Cell *cell, unsigned int output_layer, const std::set<db::PolygonRef> &result) const;
|
||||
void compute_local_cell (LocalProcessorContexts &contexts, db::Cell *cell, const LocalOperation *op, const std::pair<std::set<CellInstArray>, std::set<db::PolygonRef> > &intruders, std::set<db::PolygonRef> &result);
|
||||
};
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -39,6 +39,41 @@ enum TestMode
|
|||
TMNot = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A new processor class which and/nots with a sized version of the intruder
|
||||
*/
|
||||
class BoolAndOrNotWithSizedLocalOperation
|
||||
: public db::BoolAndOrNotLocalOperation
|
||||
{
|
||||
public:
|
||||
BoolAndOrNotWithSizedLocalOperation (bool is_and, db::Coord dist)
|
||||
: BoolAndOrNotLocalOperation (is_and), m_dist (dist)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const std::map<db::PolygonRef, std::vector<db::PolygonRef> > &interactions, std::set<db::PolygonRef> &result) const
|
||||
{
|
||||
std::map<db::PolygonRef, std::vector<db::PolygonRef> > sized_interactions = interactions;
|
||||
for (std::map<db::PolygonRef, std::vector<db::PolygonRef> >::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) {
|
||||
for (std::vector<db::PolygonRef>::iterator j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
db::Polygon poly = j->obj ().transformed (j->trans ());
|
||||
poly.size (m_dist, m_dist);
|
||||
*j = db::PolygonRef (poly, layout->shape_repository ());
|
||||
}
|
||||
}
|
||||
BoolAndOrNotLocalOperation::compute_local (layout, sized_interactions, result);
|
||||
}
|
||||
|
||||
db::Coord dist () const
|
||||
{
|
||||
return m_dist;
|
||||
}
|
||||
|
||||
private:
|
||||
db::Coord m_dist;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Turns a layer into polygons and polygon references
|
||||
* The hierarchical processor needs polygon references and can't work on polygons directly.
|
||||
|
|
@ -75,7 +110,7 @@ std::string contexts_to_s (db::Layout *layout, db::LocalProcessorContexts &conte
|
|||
return res;
|
||||
}
|
||||
|
||||
void run_test_bool (tl::TestBase *_this, const char *file, TestMode mode, int out_layer_num, db::Coord enl = 0, std::string *context_doc = 0)
|
||||
void run_test_bool (tl::TestBase *_this, const char *file, TestMode mode, int out_layer_num, std::string *context_doc = 0)
|
||||
{
|
||||
db::Layout layout_org;
|
||||
|
||||
|
|
@ -120,7 +155,60 @@ void run_test_bool (tl::TestBase *_this, const char *file, TestMode mode, int ou
|
|||
proc.run (&op, l1, l2, lout);
|
||||
} else {
|
||||
db::LocalProcessorContexts contexts;
|
||||
proc.compute_contexts (contexts, &op, l1, l2, enl);
|
||||
proc.compute_contexts (contexts, &op, l1, l2);
|
||||
*context_doc = contexts_to_s (&layout_org, contexts);
|
||||
proc.compute_results (contexts, &op, lout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout_org, testdata (file), lmap, false /*skip other layers*/, db::AsPolygons);
|
||||
}
|
||||
|
||||
void run_test_bool_with_size (tl::TestBase *_this, const char *file, TestMode mode, db::Coord dist, int out_layer_num, std::string *context_doc = 0)
|
||||
{
|
||||
db::Layout layout_org;
|
||||
|
||||
unsigned int l1 = 0, l2 = 0, lout = 0;
|
||||
db::LayerMap lmap;
|
||||
|
||||
{
|
||||
tl::InputStream stream (testdata (file));
|
||||
db::Reader reader (stream);
|
||||
|
||||
db::LayerProperties p;
|
||||
|
||||
p.layer = 1;
|
||||
p.datatype = 0;
|
||||
lmap.map (db::LDPair (1, 0), l1 = layout_org.insert_layer ());
|
||||
layout_org.set_properties (l1, p);
|
||||
|
||||
p.layer = 2;
|
||||
p.datatype = 0;
|
||||
lmap.map (db::LDPair (2, 0), l2 = layout_org.insert_layer ());
|
||||
layout_org.set_properties (l2, p);
|
||||
|
||||
p.layer = out_layer_num;
|
||||
p.datatype = 0;
|
||||
lmap.map (db::LDPair (out_layer_num, 0), lout = layout_org.insert_layer ());
|
||||
layout_org.set_properties (lout, 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);
|
||||
}
|
||||
|
||||
layout_org.clear_layer (lout);
|
||||
normalize_layer (layout_org, l1);
|
||||
normalize_layer (layout_org, l2);
|
||||
|
||||
BoolAndOrNotWithSizedLocalOperation op (mode == TMAnd, dist);
|
||||
db::LocalProcessor proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ()));
|
||||
|
||||
if (! context_doc) {
|
||||
proc.run (&op, l1, l2, lout);
|
||||
} else {
|
||||
db::LocalProcessorContexts contexts;
|
||||
proc.compute_contexts (contexts, &op, l1, l2);
|
||||
*context_doc = contexts_to_s (&layout_org, contexts);
|
||||
proc.compute_results (contexts, &op, lout);
|
||||
}
|
||||
|
|
@ -228,7 +316,7 @@ TEST(BasicAnd9)
|
|||
{
|
||||
// Top-level ring structure, AND
|
||||
std::string doc;
|
||||
run_test_bool (_this, "hlp9.oas", TMAnd, 100, 0, &doc);
|
||||
run_test_bool (_this, "hlp9.oas", TMAnd, 100, &doc);
|
||||
EXPECT_EQ (doc,
|
||||
// This means: the interaction test is strong enough, so it does not see interactions between the
|
||||
// ring and the cells embedded inside the ring. So there is only one cell context. Some shapes
|
||||
|
|
@ -244,7 +332,7 @@ TEST(BasicNot9)
|
|||
{
|
||||
// Top-level ring structure, NOT
|
||||
std::string doc;
|
||||
run_test_bool (_this, "hlp9.oas", TMNot, 101, 0, &doc);
|
||||
run_test_bool (_this, "hlp9.oas", TMNot, 101, &doc);
|
||||
EXPECT_EQ (doc,
|
||||
// This means: the interaction test is strong enough, so it does not see interactions between the
|
||||
// ring and the cells embedded inside the ring. So there is only one cell context. Some shapes
|
||||
|
|
@ -268,3 +356,143 @@ TEST(BasicNot10)
|
|||
run_test_bool (_this, "hlp10.oas", TMNot, 101);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize1)
|
||||
{
|
||||
// Simple flat AND
|
||||
run_test_bool_with_size (_this, "hlp1.oas", TMAnd, 1500, 102);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize1)
|
||||
{
|
||||
// Simple flat NOT
|
||||
run_test_bool_with_size (_this, "hlp1.oas", TMNot, 1500, 103);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize2)
|
||||
{
|
||||
// Up/down and down/up interactions, AND
|
||||
run_test_bool_with_size (_this, "hlp2.oas", TMAnd, 1500, 102);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize2)
|
||||
{
|
||||
// Up/down and down/up interactions, NOT
|
||||
run_test_bool_with_size (_this, "hlp2.oas", TMNot, 1500, 103);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize3)
|
||||
{
|
||||
// Variant building, AND
|
||||
run_test_bool_with_size (_this, "hlp3.oas", TMAnd, 1500, 102);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize3)
|
||||
{
|
||||
// Variant building, NOT
|
||||
run_test_bool_with_size (_this, "hlp3.oas", TMNot, 1500, 103);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize4)
|
||||
{
|
||||
// Sibling interactions, variant building, AND
|
||||
run_test_bool_with_size (_this, "hlp4.oas", TMAnd, 1500, 102);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize4)
|
||||
{
|
||||
// Sibling interactions, variant building, NOT
|
||||
run_test_bool_with_size (_this, "hlp4.oas", TMNot, 1500, 103);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize5)
|
||||
{
|
||||
// Variant building with intermediate hierarchy, AND
|
||||
run_test_bool_with_size (_this, "hlp5.oas", TMAnd, 1500, 102);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize5)
|
||||
{
|
||||
// Variant building with intermediate hierarchy, NOT
|
||||
run_test_bool_with_size (_this, "hlp5.oas", TMNot, 1500, 103);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize6)
|
||||
{
|
||||
// Extreme variants (copy, vanishing), AND
|
||||
run_test_bool_with_size (_this, "hlp6.oas", TMAnd, 1500, 102);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize6)
|
||||
{
|
||||
// Extreme variants (copy, vanishing), NOT
|
||||
run_test_bool_with_size (_this, "hlp6.oas", TMNot, 1500, 103);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize7)
|
||||
{
|
||||
// Context replication - direct and indirect, AND
|
||||
run_test_bool_with_size (_this, "hlp7.oas", TMAnd, 1500, 102);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize7)
|
||||
{
|
||||
// Context replication - direct and indirect, NOT
|
||||
run_test_bool_with_size (_this, "hlp7.oas", TMNot, 1500, 103);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize8)
|
||||
{
|
||||
// Mixed sibling-parent contexts, AND
|
||||
run_test_bool_with_size (_this, "hlp8.oas", TMAnd, 1500, 102);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize8)
|
||||
{
|
||||
// Mixed sibling-parent contexts, NOT
|
||||
run_test_bool_with_size (_this, "hlp8.oas", TMNot, 1500, 103);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize9)
|
||||
{
|
||||
// Top-level ring structure, AND
|
||||
std::string doc;
|
||||
run_test_bool_with_size (_this, "hlp9.oas", TMAnd, 1500, 102, &doc);
|
||||
EXPECT_EQ (doc,
|
||||
// This means: the interaction test is strong enough, so it does not see interactions between the
|
||||
// ring and the cells embedded inside the ring. So there is only one cell context. Some shapes
|
||||
// from atop the CHILD cell don't interact with shapes inside CHILD, so there are 4 shapes rather than
|
||||
// 6. And the shapes from top inside the ring are not seen by the RING's subject shapes.
|
||||
"TOP[1] 0 insts, 0 shapes (1 times)\n"
|
||||
"RING[1] 0 insts, 0 shapes (1 times)\n"
|
||||
"CHILD1[1] 0 insts, 6 shapes (2 times)\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize9)
|
||||
{
|
||||
// Top-level ring structure, NOT
|
||||
std::string doc;
|
||||
run_test_bool_with_size (_this, "hlp9.oas", TMNot, 1500, 103, &doc);
|
||||
EXPECT_EQ (doc,
|
||||
// This means: the interaction test is strong enough, so it does not see interactions between the
|
||||
// ring and the cells embedded inside the ring. So there is only one cell context. Some shapes
|
||||
// from atop the CHILD cell don't interact with shapes inside CHILD, so there are 4 shapes rather than
|
||||
// 6. And the shapes from top inside the ring are not seen by the RING's subject shapes.
|
||||
"TOP[1] 0 insts, 0 shapes (1 times)\n"
|
||||
"RING[1] 0 insts, 0 shapes (1 times)\n"
|
||||
"CHILD1[1] 0 insts, 6 shapes (2 times)\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(BasicAndWithSize10)
|
||||
{
|
||||
// Array instances, AND
|
||||
run_test_bool_with_size (_this, "hlp10.oas", TMAnd, 150, 102);
|
||||
}
|
||||
|
||||
TEST(BasicNotWithSize10)
|
||||
{
|
||||
// Array instances, NOT
|
||||
run_test_bool_with_size (_this, "hlp10.oas", TMNot, 150, 103);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue