WIP: experimental - introducing net DRC, first steps

This commit is contained in:
Matthias Koefferlein 2023-01-07 22:31:41 +01:00
parent af30695ab3
commit f9ccb60dd9
6 changed files with 206 additions and 36 deletions

View File

@ -182,6 +182,33 @@ public:
shape_reference_translator (db::Layout * /*target_layout*/) { }
};
template<class Basic>
class shape_reference_translator<db::object_with_properties<Basic> >
: public shape_reference_translator<Basic>
{
public:
typedef db::object_with_properties<Basic> shape_type;
shape_reference_translator (db::Layout *target_layout)
: shape_reference_translator<Basic> (target_layout)
{
// .. nothing yet ..
}
shape_type operator() (const shape_type &s) const
{
// CAUTION: no property ID translation happens here (reasoning: the main use case is fake ID for net tagging)
return shape_type (shape_reference_translator<Basic>::operator () (s), s.properties_id ());
}
template <class Trans>
shape_type operator() (const shape_type &s, const Trans &tr) const
{
// CAUTION: no property ID translation happens here (reasoning: the main use case is fake ID for net tagging)
return shape_type (shape_reference_translator<Basic>::operator () (s, tr), s.properties_id ());
}
};
template <class Ref, class Trans>
class shape_reference_translator_with_trans_from_shape_ref
{
@ -273,6 +300,26 @@ private:
Trans m_trans;
};
template <class Basic, class Trans>
class shape_reference_translator_with_trans<db::object_with_properties<Basic>, Trans>
: public shape_reference_translator_with_trans<Basic, Trans>
{
public:
typedef db::object_with_properties<Basic> shape_type;
shape_reference_translator_with_trans (db::Layout *target_layout)
: shape_reference_translator_with_trans<Basic, Trans> (target_layout)
{
// .. nothing yet ..
}
shape_type operator() (const shape_type &s) const
{
// CAUTION: no property ID translation happens here (reasoning: the main use case is fake ID for net tagging)
return shape_type (shape_reference_translator_with_trans<Basic, Trans>::operator () (s), s.properties_id ());
}
};
// ---------------------------------------------------------------------------------------------
/**
@ -398,6 +445,7 @@ template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db:
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::EdgePair>;
@ -711,6 +759,7 @@ template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::EdgePair>;
@ -815,6 +864,7 @@ template class DB_PUBLIC shape_interactions<db::Polygon, db::Polygon>;
template class DB_PUBLIC shape_interactions<db::Polygon, db::Text>;
template class DB_PUBLIC shape_interactions<db::Polygon, db::TextRef>;
template class DB_PUBLIC shape_interactions<db::Polygon, db::Edge>;
template class DB_PUBLIC shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::TextRef>;
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Text>;
@ -1285,6 +1335,7 @@ template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, d
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::TextRef>;
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::PolygonRef>;
@ -1347,6 +1398,7 @@ template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
@ -2362,6 +2414,7 @@ template class DB_PUBLIC local_processor<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_processor<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_processor<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_processor<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
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>;

View File

@ -742,28 +742,28 @@ static bool deliver_shape (const db::NetShape &s, db::Shapes &shapes, const Tr &
db::PolygonRef pr = s.polygon_ref ();
if (pr.obj ().is_box ()) {
db::Layout *layout = shapes.layout ();
if (layout) {
// NOTE: by maintaining the PolygonRefs we can directly use the output of "build_nets" as input
// for a hierarchical processor.
db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ());
if (propid) {
shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid));
} else {
shapes.insert (polygon_ref);
}
} else if (pr.obj ().is_box ()) {
if (propid) {
shapes.insert (db::BoxWithProperties (pr.obj ().box ().transformed (pr.trans ()).transformed (tr), propid));
} else {
shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
}
} else {
db::Layout *layout = shapes.layout ();
if (layout) {
db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ());
if (propid) {
shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid));
} else {
shapes.insert (polygon_ref);
}
db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr));
if (propid) {
shapes.insert (db::PolygonWithProperties (polygon, propid));
} else {
db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr));
if (propid) {
shapes.insert (db::PolygonWithProperties (polygon, propid));
} else {
shapes.insert (polygon);
}
shapes.insert (polygon);
}
}

View File

@ -92,6 +92,7 @@ template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
template class DB_PUBLIC local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_operation<db::PolygonRef, db::Text, db::PolygonRef>;
template class DB_PUBLIC local_operation<db::PolygonRef, db::TextRef, db::PolygonRef>;

View File

@ -33,30 +33,53 @@ namespace db
template <class T> unsigned int shape_flags ();
template <class T> unsigned int shape_flags_pure ();
template <> inline unsigned int shape_flags<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
template <> inline unsigned int shape_flags_pure<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
template <> inline unsigned int shape_flags<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
template <> inline unsigned int shape_flags_pure<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
template <> inline unsigned int shape_flags<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
template <> inline unsigned int shape_flags_pure<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
template <> inline unsigned int shape_flags<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
template <> inline unsigned int shape_flags_pure<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
template <> inline unsigned int shape_flags<db::Box> () { return db::ShapeIterator::Boxes; }
template <> inline unsigned int shape_flags_pure<db::Box> () { return 1 << db::ShapeIterator::Box; }
template <> inline unsigned int shape_flags<db::Box> () { return db::ShapeIterator::Boxes; }
template <> inline unsigned int shape_flags_pure<db::Box> () { return 1 << db::ShapeIterator::Box; }
template <> inline unsigned int shape_flags<db::Path> () { return db::ShapeIterator::Paths; }
template <> inline unsigned int shape_flags_pure<db::Path> () { return 1 << db::ShapeIterator::Path; }
template <> inline unsigned int shape_flags<db::Path> () { return db::ShapeIterator::Paths; }
template <> inline unsigned int shape_flags_pure<db::Path> () { return 1 << db::ShapeIterator::Path; }
template <> inline unsigned int shape_flags<db::Polygon> () { return db::ShapeIterator::Polygons; }
template <> inline unsigned int shape_flags_pure<db::Polygon> () { return 1 << db::ShapeIterator::Polygon; }
template <> inline unsigned int shape_flags<db::Polygon> () { return db::ShapeIterator::Polygons; }
template <> inline unsigned int shape_flags_pure<db::Polygon> () { return 1 << db::ShapeIterator::Polygon; }
template <> inline unsigned int shape_flags<db::Edge> () { return db::ShapeIterator::Edges; }
template <> inline unsigned int shape_flags_pure<db::Edge> () { return 1 << db::ShapeIterator::Edge; }
template <> inline unsigned int shape_flags<db::Edge> () { return db::ShapeIterator::Edges; }
template <> inline unsigned int shape_flags_pure<db::Edge> () { return 1 << db::ShapeIterator::Edge; }
template <> inline unsigned int shape_flags<db::EdgePair> () { return db::ShapeIterator::EdgePairs; }
template <> inline unsigned int shape_flags_pure<db::EdgePair> () { return 1 << db::ShapeIterator::EdgePair; }
template <> inline unsigned int shape_flags<db::EdgePair> () { return db::ShapeIterator::EdgePairs; }
template <> inline unsigned int shape_flags_pure<db::EdgePair> () { return 1 << db::ShapeIterator::EdgePair; }
template <> inline unsigned int shape_flags<db::Text> () { return db::ShapeIterator::Texts; }
template <> inline unsigned int shape_flags_pure<db::Text> () { return 1 << db::ShapeIterator::Text; }
template <> inline unsigned int shape_flags<db::Text> () { return db::ShapeIterator::Texts; }
template <> inline unsigned int shape_flags_pure<db::Text> () { return 1 << db::ShapeIterator::Text; }
template <> inline unsigned int shape_flags<db::PolygonRefWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::PolygonRef> (); }
template <> inline unsigned int shape_flags_pure<db::PolygonRefWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::PolygonRef> (); }
template <> inline unsigned int shape_flags<db::TextRefWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::TextRef> (); }
template <> inline unsigned int shape_flags_pure<db::TextRefWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::TextRef> (); }
template <> inline unsigned int shape_flags<db::BoxWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Box> (); }
template <> inline unsigned int shape_flags_pure<db::BoxWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Box> (); }
template <> inline unsigned int shape_flags<db::PathWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Path> (); }
template <> inline unsigned int shape_flags_pure<db::PathWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Path> (); }
template <> inline unsigned int shape_flags<db::PolygonWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Polygon> (); }
template <> inline unsigned int shape_flags_pure<db::PolygonWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Polygon> (); }
template <> inline unsigned int shape_flags<db::EdgeWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Edge> (); }
template <> inline unsigned int shape_flags_pure<db::EdgeWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Edge> (); }
template <> inline unsigned int shape_flags<db::EdgePairWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::EdgePair> (); }
template <> inline unsigned int shape_flags_pure<db::EdgePairWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::EdgePair> (); }
template <> inline unsigned int shape_flags<db::TextWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Text> (); }
template <> inline unsigned int shape_flags_pure<db::TextWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Text> (); }
template <class T>
struct DB_PUBLIC shape_to_object

View File

@ -28,7 +28,10 @@
#include "dbReader.h"
#include "dbWriter.h"
#include "dbCommonReader.h"
#include "dbHierProcessor.h"
// @@@
#include "dbLocalOperationUtils.h"
static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_layer, int gds_datatype = 0)
{
@ -37,6 +40,91 @@ static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_la
return lid;
}
class BoolBetweenNets
: public db::local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>
{
public:
BoolBetweenNets (bool is_and, bool connected)
: m_is_and (is_and), m_connected (connected)
{
// .. nothing yet ..
}
db::OnEmptyIntruderHint
on_empty_intruder_hint () const
{
return m_is_and ? db::Drop : db::Copy;
}
std::string
description () const
{
return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation"));
}
void
do_compute_local (db::Layout *layout, const db::shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t max_vertex_count, double area_ratio) const
{
tl_assert (results.size () == 1);
std::unordered_set<db::PolygonRef> &result = results.front ();
db::EdgeProcessor ep;
// NOTE: is guess we do not need to handle subject/subject interactions ...
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
const db::PolygonRefWithProperties &subject = interactions.subject_shape (i->first);
bool any_intruder = false;
for (auto j = i->second.begin (); j != i->second.end () && ! any_intruder; ++j) {
const db::PolygonRefWithProperties &other = interactions.intruder_shape (*j).second;
any_intruder = ((other.properties_id () == subject.properties_id ()) == m_connected);
}
if (! any_intruder) {
// shortcut (not: keep, and: drop)
if (! m_is_and) {
result.insert (subject);
}
} else {
ep.clear ();
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, 0);
}
for (auto j = i->second.begin (); j != i->second.end (); ++j) {
const db::PolygonRefWithProperties &other = interactions.intruder_shape (*j).second;
if ((other.properties_id () == subject.properties_id ()) == m_connected) {
for (db::PolygonRef::polygon_edge_iterator e = other.begin_edge (); ! e.at_end(); ++e) {
ep.insert (*e, 1);
}
}
}
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
db::PolygonRefGenerator pr (layout, result);
db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count);
db::PolygonGenerator pg (splitter, true, true);
ep.set_base_verbosity (50);
ep.process (pg, op);
}
}
}
private:
bool m_is_and;
bool m_connected;
};
TEST(0_Develop)
{
@ -122,17 +210,22 @@ TEST(0_Develop)
lmap_write [wvia1 = ly2.insert_layer (db::LayerProperties (16, 0))] = l2n.layer_by_name ("via1");
lmap_write [wmetal2 = ly2.insert_layer (db::LayerProperties (17, 0))] = l2n.layer_by_name ("metal2");
l2n.build_all_nets (cm, ly2, lmap_write, "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "SC_", 0 /*don't produce devices*/);
l2n.build_all_nets (cm, ly2, lmap_write, "NET_", db::LayoutToNetlist::FakePropId, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "SC_", 0 /*don't produce devices*/);
unsigned int out = ly2.insert_layer (db::LayerProperties (1000, 0));
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef> proc (&ly2, &top2);
BoolBetweenNets n2n (true, true);
proc.run (&n2n, wmetal1, wmetal2, out);
// @@@ may no work correctly as we have used fake prop ids
{
db::SaveLayoutOptions options;
std::string fn ("net.gds"); // @@@
std::string fn ("net_out.gds"); // @@@
tl::OutputStream stream (fn);
db::Writer writer (options);
writer.write (ly2, stream);
}
}

View File

@ -78,7 +78,7 @@ void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracer
db::Cell &top_cell = layout_nets.cell (layout_nets.add_cell ("NETS"));
db::CellMapping cm = l2ndb.cell_mapping_into (layout_nets, top_cell);
l2ndb.build_all_nets (cm, layout_nets, l2ndb.create_layermap (layout_nets, 1000), "NET_", tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0);
l2ndb.build_all_nets (cm, layout_nets, l2ndb.create_layermap (layout_nets, 1000), "NET_", db::LayoutToNetlist::NoProperties, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", 0);
std::string fn (tl::testdata ());
fn += "/net_tracer/";