WIP: interactions with same layer (needs finishing)

This commit is contained in:
Matthias Koefferlein 2018-10-06 01:40:01 +02:00
parent c380b9c4bf
commit 2e61998372
11 changed files with 533 additions and 90 deletions

View File

@ -72,6 +72,8 @@ BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and)
// .. nothing yet ..
}
// ---------------------------------------------------------------------------------------------
LocalOperation::on_empty_intruder_mode
BoolAndOrNotLocalOperation::on_empty_intruder_hint () const
{
@ -85,36 +87,36 @@ BoolAndOrNotLocalOperation::description () const
}
void
BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const std::map<db::PolygonRef, std::vector<db::PolygonRef> > &interactions, std::set<db::PolygonRef> &result) const
BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const
{
db::EdgeProcessor ep;
size_t p1 = 0, p2 = 1;
std::set<db::PolygonRef> others;
for (std::map<db::PolygonRef, std::vector<db::PolygonRef> >::const_iterator r = interactions.begin (); r != interactions.end (); ++r) {
// TODO: vector could be set
bool found = false;
for (std::vector<db::PolygonRef>::const_iterator i = r->second.begin (); i != r->second.end () && ! found; ++i) {
found = (*i == r->first);
for (ShapeInteractions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (ShapeInteractions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.shape (*j));
}
if (found) {
// shortcut (and: keep, not: drop)
}
for (ShapeInteractions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::PolygonRef &subject = interactions.shape (i->first);
if (others.find (subject) != others.end ()) {
if (m_is_and) {
result.insert (r->first);
result.insert (subject);
}
} else if (r->second.empty ()) {
} else if (i->second.empty ()) {
// shortcut (not: keep, and: drop)
if (! m_is_and) {
result.insert (r->first);
result.insert (subject);
}
} else {
for (db::PolygonRef::polygon_edge_iterator e = r->first.begin_edge (); ! e.at_end(); ++e) {
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p1);
}
p1 += 2;
others.insert (r->second.begin (), r->second.end ());
}
}
@ -136,6 +138,64 @@ BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const std::map<db
}
}
// ---------------------------------------------------------------------------------------------
SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wrap_count)
: m_wrap_count (wrap_count)
{
// .. nothing yet ..
}
void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const
{
if (m_wrap_count == 0) {
return;
}
db::EdgeProcessor ep;
size_t p1 = 0, p2 = 1;
std::set<unsigned int> seen2;
for (ShapeInteractions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::PolygonRef &subject = interactions.shape (i->first);
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p1);
}
p1 += 2;
for (db::ShapeInteractions::iterator2 o = i->second.begin (); o != i->second.end (); ++o) {
// don't take the same (really the same, not an identical one) shape twice - the interaction
// set does not take care to list just one copy of the same item on the intruder side.
if (seen2.find (*o) == seen2.end ()) {
seen2.insert (*o);
const db::PolygonRef &intruder = interactions.shape (*o);
for (db::PolygonRef::polygon_edge_iterator e = intruder.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, p2);
}
p2 += 2;
}
}
}
db::MergeOp op (m_wrap_count - 1);
db::PolygonRefGenerator pr (layout, result);
db::PolygonGenerator pg (pr, true, true);
ep.process (pg, op);
}
SelfOverlapMergeLocalOperation::on_empty_intruder_mode SelfOverlapMergeLocalOperation::on_empty_intruder_hint () const
{
return m_wrap_count > 1 ? LocalOperation::Drop : LocalOperation::Copy;
}
std::string SelfOverlapMergeLocalOperation::description () const
{
return tl::sprintf (tl::to_string (tr ("Self-overlap (wrap count %d)")), int (m_wrap_count));
}
// ---------------------------------------------------------------------------------------------
// LocalProcessorCellContext implementation
@ -262,6 +322,63 @@ LocalProcessorCellContexts::compute_results (LocalProcessorContexts &contexts, d
proc->push_results (cell, output_layer, common);
}
// ---------------------------------------------------------------------------------------------
ShapeInteractions::ShapeInteractions ()
: m_id (0)
{
// .. nothing yet ..
}
bool
ShapeInteractions::has_shape_id (unsigned int id) const
{
return m_shapes.find (id) != m_shapes.end ();
}
void
ShapeInteractions::add_shape (unsigned int id, const db::PolygonRef &shape)
{
m_shapes [id] = shape;
}
void
ShapeInteractions::add_subject (unsigned int id, const db::PolygonRef &shape)
{
add_shape (id, shape);
m_interactions.insert (std::make_pair (id, container::value_type::second_type ()));
}
void
ShapeInteractions::add_interaction (unsigned int subject_id, unsigned int intruder_id)
{
m_interactions [subject_id].push_back (intruder_id);
}
const std::vector<unsigned int> &
ShapeInteractions::intruders_for (unsigned int subject_id) const
{
iterator i = m_interactions.find (subject_id);
if (i == m_interactions.end ()) {
static std::vector<unsigned int> empty;
return empty;
} else {
return i->second;
}
}
const db::PolygonRef &
ShapeInteractions::shape (unsigned int id) const
{
std::map<unsigned int, db::PolygonRef>::const_iterator i = m_shapes.find (id);
if (i == m_shapes.end ()) {
static db::PolygonRef s;
return s;
} else {
return i->second;
}
}
// ---------------------------------------------------------------------------------------------
// Helper classes for the LocalProcessor
@ -274,46 +391,73 @@ inline unsigned int polygon_ref_flags ()
}
struct InteractionRegistrationShape2Shape
: db::box_scanner_receiver2<db::PolygonRef, int, db::PolygonRef, int>
: db::box_scanner_receiver2<db::PolygonRef, unsigned int, db::PolygonRef, unsigned int>
{
public:
InteractionRegistrationShape2Shape (db::Layout *layout, std::map<db::PolygonRef, std::vector<db::PolygonRef> > *result)
InteractionRegistrationShape2Shape (db::Layout *layout, ShapeInteractions *result)
: mp_result (result), mp_layout (layout)
{
// nothing yet ..
}
void add (const db::PolygonRef *ref1, int, const db::PolygonRef *ref2, int)
void add (const db::PolygonRef *ref1, unsigned int id1, const db::PolygonRef *ref2, unsigned int id2)
{
mp_result->add_shape (id1, *ref1);
if (mp_layout) {
// In order to guarantee the refs come from the subject layout, we'd need to
// rewrite them to the subject layout if required.
db::Polygon poly = ref2->obj ().transformed (ref2->trans ());
(*mp_result) [*ref1].push_back (db::PolygonRef (poly, mp_layout->shape_repository ()));
if (!mp_result->has_shape_id (id2)) {
db::Polygon poly = ref2->obj ().transformed (ref2->trans ());
mp_result->add_shape (id2, db::PolygonRef (poly, mp_layout->shape_repository ()));
}
} else {
(*mp_result) [*ref1].push_back (*ref2);
mp_result->add_shape (id2, *ref2);
}
mp_result->add_interaction (id1, id2);
}
private:
std::map<db::PolygonRef, std::vector<db::PolygonRef> > *mp_result;
ShapeInteractions *mp_result;
db::Layout *mp_layout;
};
struct InteractionRegistrationShape2Inst
: db::box_scanner_receiver2<db::PolygonRef, int, db::CellInstArray, int>
struct InteractionRegistrationShape1
: db::box_scanner_receiver<db::PolygonRef, unsigned int>
{
public:
InteractionRegistrationShape2Inst (db::Layout *subject_layout, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, std::map<db::PolygonRef, std::vector<db::PolygonRef> > *result)
InteractionRegistrationShape1 (ShapeInteractions *result)
: mp_result (result)
{
// nothing yet ..
}
void add (const db::PolygonRef *ref1, unsigned int id1, const db::PolygonRef *ref2, unsigned int id2)
{
mp_result->add_shape (id1, *ref1);
mp_result->add_shape (id2, *ref2);
mp_result->add_interaction (id1, id2);
}
private:
ShapeInteractions *mp_result;
};
struct InteractionRegistrationShape2Inst
: db::box_scanner_receiver2<db::PolygonRef, unsigned int, db::CellInstArray, unsigned int>
{
public:
InteractionRegistrationShape2Inst (db::Layout *subject_layout, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, ShapeInteractions *result)
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result)
{
// nothing yet ..
}
void add (const db::PolygonRef *ref, int, const db::CellInstArray *inst, int)
void add (const db::PolygonRef *ref, unsigned int id1, const db::CellInstArray *inst, unsigned int inst_id)
{
const db::Cell &intruder_cell = mp_intruder_layout->cell (inst->object ().cell_index ());
db::box_convert <db::CellInst, true> inst_bc (*mp_intruder_layout, m_intruder_layer);
mp_result->add_shape (id1, *ref);
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) {
@ -327,12 +471,23 @@ public:
si.shape_flags (polygon_ref_flags ());
while (! si.at_end ()) {
// @@@ 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 ()));
// NOTE: we intentionally rewrite to the subject layout - this way polygon refs in the context come from the
// subject, not from the intruder.
(*mp_result)[*ref].push_back (db::PolygonRef (poly, mp_subject_layout->shape_repository()));
// reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on
// the intruder side.
std::map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int>::const_iterator k = m_inst_shape_ids.find (std::make_pair (inst_id, ref2));
if (k == m_inst_shape_ids.end ()) {
k = m_inst_shape_ids.insert (std::make_pair (std::make_pair (inst_id, ref2), mp_result->next_id ())).first;
db::Polygon poly = ref2->obj ().transformed (tn * si.trans () * db::ICplxTrans (ref2->trans ()));
// NOTE: we intentionally rewrite to the subject layout - this way polygon refs in the context come from the
// subject, not from the intruder.
mp_result->add_shape (k->second, db::PolygonRef (poly, mp_subject_layout->shape_repository()));
}
mp_result->add_interaction (id1, k->second);
++si;
@ -348,7 +503,8 @@ private:
const db::Layout *mp_intruder_layout;
unsigned int m_intruder_layer;
db::Coord m_dist;
std::map<db::PolygonRef, std::vector<db::PolygonRef> > *mp_result;
ShapeInteractions *mp_result;
std::map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int> m_inst_shape_ids;
};
static bool
@ -414,7 +570,7 @@ instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, u
}
struct InteractionRegistrationInst2Inst
: db::box_scanner_receiver2<db::CellInstArray, int, db::CellInstArray, int>
: db::box_scanner_receiver2<db::CellInstArray, unsigned int, db::CellInstArray, unsigned int>
{
public:
typedef std::pair<std::set<const db::CellInstArray *>, std::set<db::PolygonRef> > interaction_value_type;
@ -425,14 +581,26 @@ public:
// nothing yet ..
}
void add (const db::CellInstArray *inst1, int, const db::CellInstArray *inst2, int)
void add (const db::CellInstArray *inst1, unsigned int id1, const db::CellInstArray *inst2, unsigned int id2)
{
// @@@ TODO: always insert, if both instances come from different layouts
// NOTE: self-interactions are possible for arrays: different elements of the
// array may interact which is a cell-external interaction.
if ((mp_subject_layout != mp_intruder_layout || *inst1 != *inst2 || inst1->size () > 1)
&& instances_interact (mp_subject_layout, inst1, m_subject_layer, mp_intruder_layout, inst2, m_intruder_layer, m_dist)) {
(*mp_result) [inst1].first.insert (inst2);
if (mp_subject_layout != mp_intruder_layout || id1 != id2 || inst1->size () > 1) {
bool ignore = false;
if (mp_subject_layout == mp_intruder_layout && m_subject_layer == m_intruder_layer) {
if (m_interactions.find (std::make_pair (id2, id1)) != m_interactions.end ()) {
// for self interactions ignore the reverse interactions
ignore = true;
} else {
m_interactions.insert (std::make_pair (id1, id2));
}
}
if (! ignore && instances_interact (mp_subject_layout, inst1, m_subject_layer, mp_intruder_layout, inst2, m_intruder_layer, m_dist)) {
(*mp_result) [inst1].first.insert (inst2);
}
}
}
@ -441,6 +609,7 @@ private:
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;
std::set<std::pair<unsigned int, unsigned int> > m_interactions;
};
static bool
@ -473,7 +642,7 @@ instance_shape_interacts (const db::Layout *layout, const db::CellInstArray *ins
}
struct InteractionRegistrationInst2Shape
: db::box_scanner_receiver2<db::CellInstArray, int, db::PolygonRef, int>
: db::box_scanner_receiver2<db::CellInstArray, unsigned int, db::PolygonRef, unsigned int>
{
public:
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)
@ -482,7 +651,7 @@ public:
// nothing yet ..
}
void add (const db::CellInstArray *inst, int, const db::PolygonRef *ref, int)
void add (const db::CellInstArray *inst, unsigned int, const db::PolygonRef *ref, unsigned int)
{
if (instance_shape_interacts (mp_subject_layout, inst, m_subject_layer, *ref, m_dist)) {
(*mp_result) [inst].second.insert (*ref);
@ -599,23 +768,44 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
db::box_scanner2<db::CellInstArray, int, db::CellInstArray, int> scanner;
InteractionRegistrationInst2Inst rec (mp_subject_layout, contexts.subject_layer (), mp_intruder_layout, contexts.intruder_layer (), dist, &interactions);
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
if (! inst_bcs (i->cell_inst ()).empty ()) {
scanner.insert1 (&i->cell_inst (), 0);
}
}
unsigned int id = 0;
if (intruder_cell) {
for (db::Cell::const_iterator i = intruder_cell->begin (); !i.at_end (); ++i) {
if (subject_cell == intruder_cell) {
// Use the same id's for same instances - this way we can easily detect same instances
// and don't make the self-interacting
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
unsigned int iid = ++id;
if (! inst_bcs (i->cell_inst ()).empty ()) {
scanner.insert1 (&i->cell_inst (), iid);
}
if (! inst_bci (i->cell_inst ()).empty ()) {
scanner.insert2 (&i->cell_inst (), 0);
scanner.insert2 (&i->cell_inst (), iid);
}
}
} else {
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
if (! inst_bcs (i->cell_inst ()).empty ()) {
scanner.insert1 (&i->cell_inst (), ++id);
}
}
if (intruder_cell) {
for (db::Cell::const_iterator i = intruder_cell->begin (); !i.at_end (); ++i) {
if (! inst_bci (i->cell_inst ()).empty ()) {
scanner.insert2 (&i->cell_inst (), ++id);
}
}
}
}
for (std::set<db::CellInstArray>::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) {
if (! inst_bci (*i).empty ()) {
scanner.insert2 (i.operator-> (), 0);
scanner.insert2 (i.operator-> (), ++id);
}
}
@ -724,36 +914,69 @@ LocalProcessor::compute_local_cell (LocalProcessorContexts &contexts, db::Cell *
// local shapes vs. child cell
std::map<db::PolygonRef, std::vector<db::PolygonRef> > interactions;
ShapeInteractions interactions;
db::box_convert <db::CellInstArray, true> inst_bci (*mp_intruder_layout, contexts.intruder_layer ());
if (op->on_empty_intruder_hint () != LocalOperation::Drop) {
// insert dummy interactions to accommodate subject vs. nothing
for (db::Shapes::shape_iterator i = subject_shapes->begin (polygon_ref_flags ()); !i.at_end (); ++i) {
interactions.insert (std::make_pair (*i->basic_ptr (db::PolygonRef::tag ()), std::vector<db::PolygonRef> ()));
// 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 (polygon_ref_flags ()); !i.at_end (); ++i) {
unsigned int id = interactions.next_id ();
if (subject_id0 == 0) {
subject_id0 = id;
}
if (op->on_empty_intruder_hint () != LocalOperation::Drop) {
const db::PolygonRef *ref = i->basic_ptr (db::PolygonRef::tag ());
interactions.add_subject (id, *ref);
}
}
if (! subject_shapes->empty () && (intruder_shapes || ! intruders.second.empty ())) {
db::box_scanner2<db::PolygonRef, int, db::PolygonRef, int> scanner;
InteractionRegistrationShape2Shape rec (mp_subject_layout == mp_intruder_layout ? 0 : mp_subject_layout, &interactions);
if (subject_cell == intruder_cell && contexts.subject_layer () == contexts.intruder_layer ()) {
for (db::Shapes::shape_iterator i = subject_shapes->begin (polygon_ref_flags ()); !i.at_end (); ++i) {
scanner.insert1 (i->basic_ptr (db::PolygonRef::tag ()), 0);
}
db::box_scanner<db::PolygonRef, int> scanner;
InteractionRegistrationShape1 rec (&interactions);
for (std::set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) {
scanner.insert2 (i.operator-> (), 0);
}
if (intruder_shapes) {
for (db::Shapes::shape_iterator i = intruder_shapes->begin (polygon_ref_flags ()); !i.at_end (); ++i) {
scanner.insert2 (i->basic_ptr (db::PolygonRef::tag ()), 0);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (polygon_ref_flags ()); !i.at_end (); ++i) {
const db::PolygonRef *ref = i->basic_ptr (db::PolygonRef::tag ());
scanner.insert (ref, id++);
}
}
scanner.process (rec, op->dist (), db::box_convert<db::PolygonRef> (), db::box_convert<db::PolygonRef> ());
for (std::set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) {
scanner.insert (i.operator-> (), interactions.next_id ());
}
scanner.process (rec, op->dist (), db::box_convert<db::PolygonRef> ());
} else {
db::box_scanner2<db::PolygonRef, int, db::PolygonRef, int> scanner;
InteractionRegistrationShape2Shape rec (mp_subject_layout == mp_intruder_layout ? 0 : mp_subject_layout, &interactions);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (polygon_ref_flags ()); !i.at_end (); ++i) {
const db::PolygonRef *ref = i->basic_ptr (db::PolygonRef::tag ());
scanner.insert1 (ref, id++);
}
for (std::set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) {
scanner.insert2 (i.operator-> (), interactions.next_id ());
}
if (intruder_shapes) {
for (db::Shapes::shape_iterator i = intruder_shapes->begin (polygon_ref_flags ()); !i.at_end (); ++i) {
scanner.insert2 (i->basic_ptr (db::PolygonRef::tag ()), interactions.next_id ());
}
}
scanner.process (rec, op->dist (), db::box_convert<db::PolygonRef> (), db::box_convert<db::PolygonRef> ());
}
}
@ -762,21 +985,30 @@ LocalProcessor::compute_local_cell (LocalProcessorContexts &contexts, db::Cell *
db::box_scanner2<db::PolygonRef, int, db::CellInstArray, int> scanner;
InteractionRegistrationShape2Inst rec (mp_subject_layout, mp_intruder_layout, contexts.intruder_layer (), op->dist (), &interactions);
unsigned int id = subject_id0;
for (db::Shapes::shape_iterator i = subject_shapes->begin (polygon_ref_flags ()); !i.at_end (); ++i) {
scanner.insert1 (i->basic_ptr (db::PolygonRef::tag ()), 0);
scanner.insert1 (i->basic_ptr (db::PolygonRef::tag ()), id++);
}
if (intruder_cell) {
unsigned int inst_id = 0;
if (subject_cell == intruder_cell && contexts.subject_layer () == contexts.intruder_layer ()) {
// Same cell, same layer -> no shape to child instance interactions because this will be taken care of
// by the instances themselves (and their intruders). This also means, we prefer to deal with
// interactions low in the hierarchy.
} else if (intruder_cell) {
for (db::Cell::const_iterator i = intruder_cell->begin (); !i.at_end (); ++i) {
if (! inst_bci (i->cell_inst ()).empty ()) {
scanner.insert2 (&i->cell_inst (), 0);
scanner.insert2 (&i->cell_inst (), ++inst_id);
}
}
}
for (std::set<db::CellInstArray>::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) {
if (! inst_bci (*i).empty ()) {
scanner.insert2 (i.operator-> (), 0);
scanner.insert2 (i.operator-> (), ++inst_id);
}
}

View File

@ -39,6 +39,44 @@ class LocalProcessor;
class LocalProcessorCellContext;
class LocalProcessorContexts;
// @@@ TODO: move this somewhere else?
class DB_PLUGIN_PUBLIC ShapeInteractions
{
public:
typedef std::map<unsigned int, std::vector<unsigned int> > container;
typedef container::const_iterator iterator;
typedef container::value_type::second_type::const_iterator iterator2;
ShapeInteractions ();
iterator begin () const
{
return m_interactions.begin ();
}
iterator end () const
{
return m_interactions.end ();
}
bool has_shape_id (unsigned int id) const;
void add_shape (unsigned int id, const db::PolygonRef &shape);
void add_subject (unsigned int id, const db::PolygonRef &shape);
void add_interaction (unsigned int subject_id, unsigned int intruder_id);
const std::vector<unsigned int> &intruders_for (unsigned int subject_id) const;
const db::PolygonRef &shape (unsigned int id) const;
unsigned int next_id ()
{
return ++m_id;
}
private:
std::map<unsigned int, std::vector<unsigned int> > m_interactions;
std::map<unsigned int, db::PolygonRef> m_shapes;
unsigned int m_id;
};
class DB_PLUGIN_PUBLIC LocalOperation
{
public:
@ -49,7 +87,7 @@ public:
LocalOperation () { }
virtual ~LocalOperation () { }
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 void compute_local (db::Layout *layout, const ShapeInteractions &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; }
@ -61,7 +99,7 @@ class DB_PLUGIN_PUBLIC BoolAndOrNotLocalOperation
public:
BoolAndOrNotLocalOperation (bool is_and);
virtual void compute_local (db::Layout *layout, const std::map<db::PolygonRef, std::vector<db::PolygonRef> > &interactions, std::set<db::PolygonRef> &result) const;
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const;
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
virtual std::string description () const;
@ -69,6 +107,20 @@ private:
bool m_is_and;
};
class DB_PLUGIN_PUBLIC SelfOverlapMergeLocalOperation
: public LocalOperation
{
public:
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set<db::PolygonRef> &result) const;
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
virtual std::string description () const;
private:
unsigned int m_wrap_count;
};
// @@@ TODO: should be hidden (private data?)
struct DB_PLUGIN_PUBLIC LocalProcessorCellDrop
{

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.

View File

@ -36,7 +36,8 @@ static std::string testdata (const std::string &fn)
enum TestMode
{
TMAnd = 0,
TMNot = 1
TMNot = 1,
TMSelfOverlap = 2
};
/**
@ -52,14 +53,15 @@ public:
// .. 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
virtual void compute_local (db::Layout *layout, const db::ShapeInteractions &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 ());
db::ShapeInteractions sized_interactions = interactions;
for (db::ShapeInteractions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) {
for (db::ShapeInteractions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
const db::PolygonRef &ref = interactions.shape (*j);
db::Polygon poly = ref.obj ().transformed (ref.trans ());
poly.size (m_dist, m_dist);
*j = db::PolygonRef (poly, layout->shape_repository ());
sized_interactions.add_shape (*j, db::PolygonRef (poly, layout->shape_repository ()));
}
}
BoolAndOrNotLocalOperation::compute_local (layout, sized_interactions, result);
@ -130,8 +132,12 @@ void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode mode, in
p.layer = 2;
p.datatype = 0;
lmap.map (db::LDPair (2, 0), l2 = layout_org.insert_layer ());
layout_org.set_properties (l2, p);
if (mode == TMSelfOverlap) {
lmap.map (db::LDPair (2, 0), l2 = l1);
} else {
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;
@ -146,21 +152,30 @@ void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode mode, in
layout_org.clear_layer (lout);
normalize_layer (layout_org, l1);
normalize_layer (layout_org, l2);
if (l1 != l2) {
normalize_layer (layout_org, l2);
}
db::BoolAndOrNotLocalOperation op (mode == TMAnd);
db::LocalOperation *lop = 0;
db::BoolAndOrNotLocalOperation bool_op (mode == TMAnd);
db::SelfOverlapMergeLocalOperation self_intersect_op (2);
if (mode == TMSelfOverlap) {
lop = &self_intersect_op;
} else {
lop = &bool_op;
}
if (single) {
db::LocalProcessor proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ()));
if (! context_doc) {
proc.run (&op, l1, l2, lout);
proc.run (lop, l1, l2, lout);
} else {
db::LocalProcessorContexts contexts;
proc.compute_contexts (contexts, &op, l1, l2);
proc.compute_contexts (contexts, lop, l1, l2);
*context_doc = contexts_to_s (&layout_org, contexts);
proc.compute_results (contexts, &op, lout);
proc.compute_results (contexts, lop, lout);
}
} else {
@ -170,12 +185,12 @@ void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode mode, in
db::LocalProcessor proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ()), &layout_org2, &layout_org2.cell (*layout_org2.begin_top_down ()));
if (! context_doc) {
proc.run (&op, l1, l2, lout);
proc.run (lop, l1, l2, lout);
} else {
db::LocalProcessorContexts contexts;
proc.compute_contexts (contexts, &op, l1, l2);
proc.compute_contexts (contexts, lop, l1, l2);
*context_doc = contexts_to_s (&layout_org, contexts);
proc.compute_results (contexts, &op, lout);
proc.compute_results (contexts, lop, lout);
}
}
@ -835,3 +850,147 @@ TEST(TwoInputsNotWithSize10)
// Array instances, NOT
run_test_bool2_with_size (_this, "hlp10.oas", TMNot, 150, 103);
}
TEST(BasicSelfOverlap1)
{
// Simple flat AND
run_test_bool (_this, "hlp1.oas", TMSelfOverlap, 110);
}
TEST(BasicSelfOverlap2)
{
// Up/down and down/up interactions, AND
run_test_bool (_this, "hlp2.oas", TMSelfOverlap, 110);
}
TEST(BasicSelfOverlap3)
{
// Variant building, AND
run_test_bool (_this, "hlp3.oas", TMSelfOverlap, 110);
}
TEST(BasicSelfOverlap4)
{
// Sibling interactions, variant building, AND
run_test_bool (_this, "hlp4.oas", TMSelfOverlap, 110);
}
TEST(BasicSelfOverlap5)
{
// Variant building with intermediate hierarchy, AND
run_test_bool (_this, "hlp5.oas", TMSelfOverlap, 110);
}
TEST(BasicSelfOverlap6)
{
// Extreme variants (copy, vanishing), AND
run_test_bool (_this, "hlp6.oas", TMSelfOverlap, 110);
}
TEST(BasicSelfOverlap7)
{
// Context replication - direct and indirect, AND
run_test_bool (_this, "hlp7.oas", TMSelfOverlap, 110);
}
TEST(BasicSelfOverlap8)
{
// Mixed sibling-parent contexts, AND
run_test_bool (_this, "hlp8.oas", TMSelfOverlap, 110);
}
TEST(BasicSelfOverlap9)
{
// Top-level ring structure, AND
std::string doc;
run_test_bool (_this, "hlp9.oas", TMSelfOverlap, 110, &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, 4 shapes (2 times)\n"
);
}
TEST(BasicSelfOverlap10)
{
// Array instances, AND
run_test_bool (_this, "hlp10.oas", TMSelfOverlap, 110);
}
#if 0 // @@@
TEST(BasicSelfOverlapWithSize1)
{
// Simple flat AND
run_test_bool_with_size (_this, "hlp1.oas", TMSelfOverlap, 1500, 111);
}
TEST(BasicSelfOverlapWithSize2)
{
// Up/down and down/up interactions, AND
run_test_bool_with_size (_this, "hlp2.oas", TMSelfOverlap, 1500, 111);
}
TEST(BasicSelfOverlapWithSize3)
{
// Variant building, AND
run_test_bool_with_size (_this, "hlp3.oas", TMSelfOverlap, 1500, 111);
}
TEST(BasicSelfOverlapWithSize4)
{
// Sibling interactions, variant building, AND
run_test_bool_with_size (_this, "hlp4.oas", TMSelfOverlap, 1500, 111);
}
TEST(BasicSelfOverlapWithSize5)
{
// Variant building with intermediate hierarchy, AND
run_test_bool_with_size (_this, "hlp5.oas", TMSelfOverlap, 1500, 111);
}
TEST(BasicSelfOverlapWithSize6)
{
// Extreme variants (copy, vanishing), AND
run_test_bool_with_size (_this, "hlp6.oas", TMSelfOverlap, 1500, 111);
}
TEST(BasicSelfOverlapWithSize7)
{
// Context replication - direct and indirect, AND
run_test_bool_with_size (_this, "hlp7.oas", TMSelfOverlap, 1500, 111);
}
TEST(BasicSelfOverlapWithSize8)
{
// Mixed sibling-parent contexts, AND
run_test_bool_with_size (_this, "hlp8.oas", TMSelfOverlap, 1500, 111);
}
TEST(BasicSelfOverlapWithSize9)
{
// Top-level ring structure, AND
std::string doc;
run_test_bool_with_size (_this, "hlp9.oas", TMSelfOverlap, 1500, 111, &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(BasicSelfOverlapWithSize10)
{
// Array instances, AND
run_test_bool_with_size (_this, "hlp10.oas", TMSelfOverlap, 150, 111);
}
#endif