WIP: bug fixes, more tests for complex DRC

This commit is contained in:
Matthias Koefferlein 2021-01-09 15:56:55 +01:00
parent f993e4c31b
commit 7093dfd0eb
12 changed files with 161 additions and 50 deletions

View File

@ -1553,7 +1553,8 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
for (std::vector<unsigned int>::const_iterator il = contexts.intruder_layers ().begin (); il != contexts.intruder_layers ().end (); ++il) { for (std::vector<unsigned int>::const_iterator il = contexts.intruder_layers ().begin (); il != contexts.intruder_layers ().end (); ++il) {
db::box_convert <db::CellInst, true> inst_bcii (*mp_intruder_layout, contexts.actual_intruder_layer (*il)); unsigned int ail = contexts.actual_intruder_layer (*il);
db::box_convert <db::CellInst, true> inst_bcii (*mp_intruder_layout, ail);
for (std::unordered_set<const db::CellInstArray *>::const_iterator j = i->second.first.begin (); j != i->second.first.end (); ++j) { for (std::unordered_set<const db::CellInstArray *>::const_iterator j = i->second.first.begin (); j != i->second.first.end (); ++j) {
for (db::CellInstArray::iterator k = (*j)->begin_touching (safe_box_enlarged (nbox, -1, -1), inst_bcii); ! k.at_end (); ++k) { for (db::CellInstArray::iterator k = (*j)->begin_touching (safe_box_enlarged (nbox, -1, -1), inst_bcii); ! k.at_end (); ++k) {
@ -1561,7 +1562,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
// NOTE: no self-interactions // NOTE: no self-interactions
if (i->first != *j || tn != tk) { if (i->first != *j || tn != tk) {
// optimize the intruder instance so it will be as low as possible // optimize the intruder instance so it will be as low as possible
std::pair<bool, db::CellInstArray> ei = effective_instance (contexts.subject_layer (), i->first->object ().cell_index (), contexts.actual_intruder_layer (*il), (*j)->object ().cell_index (), tni * tk, dist); std::pair<bool, db::CellInstArray> ei = effective_instance (contexts.subject_layer (), i->first->object ().cell_index (), ail, (*j)->object ().cell_index (), tni * tk, dist);
if (ei.first) { if (ei.first) {
intruders_below.first.insert (ei.second); intruders_below.first.insert (ei.second);
} }
@ -1902,7 +1903,7 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
db::box_convert<db::CellInstArray, true> inst_bci (*mp_intruder_layout, ail); db::box_convert<db::CellInstArray, true> inst_bci (*mp_intruder_layout, ail);
typename std::map<unsigned int, std::set<TI> >::const_iterator ipl = intruders.second.find (ail); typename std::map<unsigned int, std::set<TI> >::const_iterator ipl = intruders.second.find (*il);
static std::set<TI> empty_intruders; static std::set<TI> empty_intruders;
if (! subject_shapes->empty () && (intruder_shapes || ipl != intruders.second.end ())) { if (! subject_shapes->empty () && (intruder_shapes || ipl != intruders.second.end ())) {
@ -1932,7 +1933,7 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
unsigned int inst_id = 0; unsigned int inst_id = 0;
if (subject_cell == intruder_cell && contexts.subject_layer () == ail) { if (subject_cell == intruder_cell && contexts.subject_layer () == ail && !foreign) {
// Same cell, same layer -> no shape to child instance interactions because this will be taken care of // 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 // by the instances themselves (and their intruders). This also means, we prefer to deal with

View File

@ -145,6 +145,56 @@ void insert_into_hash (std::unordered_set<T> &hash, const T &shape)
} }
template <class TS>
static
uint32_t compute_error_pattern (const TS &subject, std::unordered_set<db::EdgePair> &result, std::map<db::Edge, uint32_t> &edges_with_errors)
{
uint32_t p = 1;
for (typename TS::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end (); ++e) {
edges_with_errors [*e] = p;
p <<= 1;
}
uint32_t error_pattern = 0;
for (std::unordered_set<db::EdgePair>::const_iterator ep = result.begin (); ep != result.end (); ++ep) {
std::map<db::Edge, unsigned int>::iterator i = edges_with_errors.find (ep->first ());
if (i != edges_with_errors.end ()) {
if ((error_pattern & i->second) == 0) {
error_pattern |= i->second;
}
}
}
return error_pattern;
}
static bool rect_filter_can_be_waived (uint32_t error_pattern, uint32_t rect_filter)
{
if (! error_pattern) {
return false;
}
bool can_be_waived = false;
// decode pattern: consider each group of 4 bits and match them against the error pattern in their four rotation variants
uint32_t p32 = (uint32_t) rect_filter;
while (p32 != 0 && ! can_be_waived) {
uint32_t p4 = p32 & 0xf;
p32 >>= 4;
if (p4 > 0) {
for (unsigned int r = 0; r < 4 && ! can_be_waived; ++r) {
can_be_waived = (error_pattern == p4);
p4 = ((p4 << 1) & 0xf) | ((p4 & 0x8) >> 3);
}
}
}
return can_be_waived;
}
template <class TS, class TI> template <class TS, class TI>
void void
check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
@ -413,52 +463,16 @@ check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape
continue; continue;
} }
unsigned int p = 1; std::map<db::Edge, uint32_t> edges_with_errors;
std::map<db::Edge, unsigned int> edges_with_errors; unsigned int error_pattern = compute_error_pattern (subject, result, edges_with_errors);
for (typename TS::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end (); ++e) {
edges_with_errors [*e] = p;
p <<= 1;
}
unsigned int error_pattern = 0; if (rect_filter_can_be_waived (error_pattern, (uint32_t) m_options.rect_filter)) {
for (std::unordered_set<db::EdgePair>::const_iterator ep = result.begin (); ep != result.end (); ++ep) {
std::map<db::Edge, unsigned int>::iterator i = edges_with_errors.find (ep->first ()); for (std::unordered_set<db::EdgePair>::const_iterator ep = result.begin (); ep != result.end (); ++ep) {
if (i != edges_with_errors.end ()) { if (edges_with_errors.find (ep->first ()) != edges_with_errors.end ()) {
if ((error_pattern & i->second) == 0) { waived.insert (*ep);
error_pattern |= i->second;
} }
} }
}
if (error_pattern != 0) {
bool can_be_waived = false;
// decode pattern: consider each group of 4 bits and match them against the error pattern in their four rotation variants
uint32_t p32 = (uint32_t) m_options.rect_filter;
while (p32 != 0 && ! can_be_waived) {
uint32_t p4 = p32 & 0xf;
p32 >>= 4;
if (p4 > 0) {
for (unsigned int r = 0; r < 4 && ! can_be_waived; ++r) {
can_be_waived = (error_pattern == p4);
p4 = ((p4 << 1) & 0xf) | ((p4 & 0x8) >> 3);
}
}
}
if (can_be_waived) {
for (std::unordered_set<db::EdgePair>::const_iterator ep = result.begin (); ep != result.end (); ++ep) {
if (edges_with_errors.find (ep->first ()) != edges_with_errors.end ()) {
waived.insert (*ep);
}
}
}
} }
@ -470,9 +484,28 @@ check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape
} }
} }
} if (! m_has_other) {
results.front ().insert (result.begin (), result.end ()); // this is the case of single-layer interaction. We need to separate the results
// from edge pairs into single edges (basically returning the first edge only)
// Reasoning: we cannot say what's going to happen on the other side of the
// error - it may not be waived and we cannot waive half of an edge pair.
for (std::unordered_set<db::EdgePair>::const_iterator i = result.begin (); i != result.end (); ++i) {
results.front ().insert (db::EdgePair (i->first (), i->first ().swapped_points ()));
}
} else {
results.front ().insert (result.begin (), result.end ());
}
} else {
results.front ().insert (result.begin (), result.end ());
}
} }
template <class TS, class TI> template <class TS, class TI>

View File

@ -77,7 +77,8 @@ module DRC
@engine._context("drc") do @engine._context("drc") do
requires_region requires_region
op.is_a?(DRCOpNode) || raise("A DRC expression is required for the argument (got #{op.inspect})") op.is_a?(DRCOpNode) || raise("A DRC expression is required for the argument (got #{op.inspect})")
DRCLayer::new(@engine, self.data.complex_op(op.create_node({}))) # @@@ proper output type!!!
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Region, :complex_op, op.create_node({})))
end end
end end

View File

@ -88,3 +88,13 @@ TEST(2d)
{ {
run_test (_this, "2", true); run_test (_this, "2", true);
} }
TEST(3)
{
run_test (_this, "3", false);
}
TEST(3d)
{
run_test (_this, "3", true);
}

36
testdata/drc/drcGenericTests_3.drc vendored Normal file
View File

@ -0,0 +1,36 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
threads(0) # easier to debug
end
l1 = input(1, 0)
l2 = input(2, 0)
l3 = input(3, 0)
l1.output(1, 0)
l2.output(2, 0)
l3.output(3, 0)
# space with rectangle side selection option
l1.drc(space(projection) < 1.um).polygons.output(100, 0)
l1.drc(space(projection, one_side_allowed) < 1.um).output(101, 0)
l1.drc(space(projection, two_sides_allowed) < 1.um).output(102, 0)
l1.drc(space(projection, three_sides_allowed) < 1.um).output(103, 0)
# space with rectangle side selection option
l1.drc(iso(projection) < 1.um).polygons.output(110, 0)
l1.drc(iso(projection, one_side_allowed) < 1.um).output(111, 0)
l1.drc(iso(projection, two_sides_allowed) < 1.um).output(112, 0)
l1.drc(iso(projection, three_sides_allowed) < 1.um).output(113, 0)
# separation with rectangle side selection option
l1.drc(sep(l2, projection) < 1.um).polygons.output(120, 0)
l1.drc(sep(l2, projection, one_side_allowed) < 1.um).polygons.output(121, 0)
l1.drc(sep(l2, projection, two_sides_allowed) < 1.um).polygons.output(122, 0)
l1.drc(sep(l2, projection, three_sides_allowed) < 1.um).polygons.output(123, 0)

BIN
testdata/drc/drcGenericTests_3.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcGenericTests_au3.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcGenericTests_au3d.gds vendored Normal file

Binary file not shown.

30
testdata/drc/drcSimpleTests_25.drc vendored Normal file
View File

@ -0,0 +1,30 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
end
l1 = input(1, 0)
l2 = input(2, 0)
l3 = input(3, 0)
l1.output(1, 0)
l2.output(2, 0)
l3.output(3, 0)
l1.space(1.0, projection).polygons.output(100, 0)
l1.space(1.0, euclidian).polygons.output(110, 0)
l1.space(1.0, projection, projection_limits(0..2.0)).polygons.output(111, 0)
l1.space(1.0, projection, whole_edges).polygons.output(112, 0)
l1.space(1.0, projection, only_opposite).output(113, 0)
l1.space(1.0, projection, not_opposite).output(114, 0)
l1.isolated(1.0, euclidian).polygons.output(120, 0)
l1.isolated(1.0, projection, projection_limits(0..2.0)).polygons.output(121, 0)
l1.isolated(1.0, projection, whole_edges).polygons.output(122, 0)
l1.isolated(1.0, projection, only_opposite).output(123, 0)
l1.isolated(1.0, projection, not_opposite).output(124, 0)

BIN
testdata/drc/drcSimpleTests_25.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au25.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au25d.gds vendored Normal file

Binary file not shown.