WIP: debugging and unit test for net-aware booleans

This commit is contained in:
Matthias Koefferlein 2023-01-19 21:15:41 +01:00
parent e1ddd6f8d2
commit 984c001f56
15 changed files with 201 additions and 115 deletions

View File

@ -40,6 +40,7 @@
#include "dbRegionLocalOperations.h"
#include "dbHierProcessor.h"
#include "dbCompoundOperation.h"
#include "dbLayoutToNetlist.h"
#include <sstream>
@ -1730,6 +1731,60 @@ AsIfFlatRegion::add (const Region &other) const
}
}
static void
deliver_shapes_of_nets_recursive (db::Shapes &out, db::PropertiesRepository *pr, const db::Circuit *circuit, const LayoutToNetlist *l2n, const db::Region *of_layer, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const db::ICplxTrans &tr, const std::set<const db::Net *> *net_filter)
{
db::CplxTrans dbu_trans (l2n->internal_layout ()->dbu ());
auto dbu_trans_inv = dbu_trans.inverted ();
for (auto n = circuit->begin_nets (); n != circuit->end_nets (); ++n) {
if (! net_filter || net_filter->find (n.operator-> ()) != net_filter->end ()) {
db::properties_id_type prop_id = db::NetBuilder::make_netname_propid (*pr, prop_mode, net_prop_name, *n);
l2n->shapes_of_net (*n, *of_layer, true, out, prop_id, tr);
}
// dive into subcircuits
for (auto sc = circuit->begin_subcircuits (); sc != circuit->end_subcircuits (); ++sc) {
const db::Circuit *circuit_ref = sc->circuit_ref ();
db::ICplxTrans tr_ref = tr * (dbu_trans_inv * sc->trans () * dbu_trans);
deliver_shapes_of_nets_recursive (out, pr, circuit_ref, l2n, of_layer, prop_mode, net_prop_name, tr_ref, net_filter);
}
}
}
RegionDelegate *
AsIfFlatRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const
{
if (! l2n->is_netlist_extracted ()) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
std::unique_ptr<db::FlatRegion> result (new db::FlatRegion ());
std::unique_ptr<db::Region> region_for_layer (l2n->layer_by_original (this));
if (! region_for_layer) {
throw tl::Exception (tl::to_string (tr ("The given layer is not an original layer used in netlist extraction")));
}
if (l2n->netlist ()->top_circuit_count () == 0) {
throw tl::Exception (tl::to_string (tr ("No top circuit found in netlist")));
} else if (l2n->netlist ()->top_circuit_count () > 1) {
throw tl::Exception (tl::to_string (tr ("More than one top circuit found in netlist")));
}
const db::Circuit *top_circuit = l2n->netlist ()->begin_top_down ().operator-> ();
std::set<const db::Net *> net_filter_set;
if (net_filter) {
net_filter_set.insert (net_filter->begin (), net_filter->end ());
}
deliver_shapes_of_nets_recursive (result->raw_polygons (), result->properties_repository (), top_circuit, l2n, region_for_layer.get (), prop_mode, net_prop_name, db::ICplxTrans (), net_filter ? &net_filter_set : 0);
return result.release ();
}
void
AsIfFlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{

View File

@ -278,6 +278,8 @@ public:
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
protected:

View File

@ -436,12 +436,6 @@ const db::PropertiesRepository *FlatRegion::properties_repository () const
return mp_properties_repository.get_const ();
}
RegionDelegate *FlatRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const
{
// @@@ TODO: implement (how?)
return 0;
}
void FlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
db::PropertyMapper pm (&layout->properties_repository (), mp_properties_repository.get_const ());

View File

@ -103,8 +103,6 @@ public:
virtual db::PropertiesRepository *properties_repository ();
virtual const db::PropertiesRepository *properties_repository () const;
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const;
void do_insert (const db::Polygon &polygon, db::properties_id_type prop_id);
void do_transform (const db::Trans &t)

View File

@ -267,7 +267,7 @@ void LayoutToNetlist::connect (const db::Region &l)
reset_extracted ();
if (! is_persisted (l)) {
register_layer (l, make_new_name ());
register_layer (l);
}
// we need to keep a reference, so we can safely delete the region
@ -282,10 +282,10 @@ void LayoutToNetlist::connect_impl (const db::ShapeCollection &a, const db::Shap
reset_extracted ();
if (! is_persisted (a)) {
register_layer (a, make_new_name ());
register_layer (a);
}
if (! is_persisted (b)) {
register_layer (b, make_new_name ());
register_layer (b);
}
// we need to keep a reference, so we can safely delete the region
@ -302,7 +302,7 @@ size_t LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const
reset_extracted ();
if (! is_persisted (l)) {
register_layer (l, make_new_name ());
register_layer (l);
}
// we need to keep a reference, so we can safely delete the region
@ -548,9 +548,17 @@ db::Region *LayoutToNetlist::layer_by_index (unsigned int index)
db::Region *LayoutToNetlist::layer_by_original (const ShapeCollectionDelegateBase *original_delegate)
{
auto n = m_region_by_original.find (original_delegate);
auto n = m_region_by_original.find (tl::id_of (original_delegate));
if (n == m_region_by_original.end ()) {
return 0;
DeepShapeCollectionDelegateBase *dl = const_cast<ShapeCollectionDelegateBase *> (original_delegate)->deep ();
if (dl && dl->deep_layer ().store () == mp_dss.get ()) {
// implicitly original because the collection is inside our DSS
return new db::Region (new db::DeepRegion (dl->deep_layer ()));
} else {
return 0;
}
} else {
return new db::Region (new db::DeepRegion (n->second));
}
@ -581,7 +589,11 @@ std::string LayoutToNetlist::name (const ShapeCollection &coll) const
void LayoutToNetlist::register_layer (const ShapeCollection &collection, const std::string &n)
{
if (m_named_regions.find (n) != m_named_regions.end ()) {
if (m_region_by_original.find (tl::id_of (collection.get_delegate ())) != m_region_by_original.end ()) {
throw tl::Exception (tl::to_string (tr ("The layer is already registered")));
}
if (! n.empty () && m_named_regions.find (n) != m_named_regions.end ()) {
throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n);
}
@ -611,9 +623,12 @@ void LayoutToNetlist::register_layer (const ShapeCollection &collection, const s
}
m_named_regions [n] = dl;
m_region_by_original [collection.get_delegate ()] = dl;
m_name_of_layer [dl.layer ()] = n;
m_region_by_original [tl::id_of (collection.get_delegate ())] = dl;
if (! n.empty ()) {
m_named_regions [n] = dl;
m_name_of_layer [dl.layer ()] = n;
}
}
db::DeepLayer LayoutToNetlist::deep_layer_of (const db::ShapeCollection &coll) const
@ -633,6 +648,17 @@ db::DeepLayer LayoutToNetlist::deep_layer_of (const db::ShapeCollection &coll) c
}
}
bool LayoutToNetlist::is_persisted_impl (const db::ShapeCollection &coll) const
{
if (coll.get_delegate ()->deep () && coll.get_delegate ()->deep ()->deep_layer ().store () == mp_dss.get ()) {
// implicitly persisted because the collection is inside our DSS
return true;
} else {
// explicitly persisted through "register"
return m_region_by_original.find (tl::id_of (coll.get_delegate ())) != m_region_by_original.end ();
}
}
db::CellMapping LayoutToNetlist::make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells)
{
std::set<db::cell_index_type> device_cells;
@ -865,7 +891,7 @@ static bool deliver_shapes_of_net (bool recursive, const db::Netlist *nl, const
return true;
}
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid) const
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid, const ICplxTrans &trans) const
{
unsigned int lid = layer_of (of_layer);
const db::Circuit *circuit = net.circuit ();
@ -874,10 +900,10 @@ void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_la
std::map<unsigned int, db::Shapes *> lmap;
lmap [lid] = &to;
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), propid);
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, trans, propid);
}
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, const db::ICplxTrans &trans) const
{
unsigned int lid = layer_of (of_layer);
const db::Circuit *circuit = net.circuit ();
@ -887,7 +913,7 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region
std::map<unsigned int, db::Region *> lmap;
lmap [lid] = res.get ();
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), 0);
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, trans, 0);
return res.release ();
}

View File

@ -237,14 +237,22 @@ public:
double device_scaling () const;
/**
* @brief Register a layer under the given name
* This is a formal name for the layer. Using a name or layer properties
* (see below) enhances readability of backannotated information
* @brief Register a layer, optionally under the given name
* Using a name or layer properties (see below) enhances readability of backannotated information
* if layers are involved. Use this method to attach a name to a region
* derived by boolean operations for example.
* Named regions are persisted inside the LayoutToNetlist object.
*
* Registered regions are persisted inside the LayoutToNetlist object
* if they are flat or original layer regions.
* This allows passing flat or original layer collections.
*
* If no name is given, the region will not be registered under a name.
* Still the collection will be persisted if required.
*
* In addition to regions, text collections can be registered too.
* Including texts in "connect" makes net names begin assigned from the text strings.
*/
void register_layer (const ShapeCollection &collection, const std::string &name);
void register_layer (const ShapeCollection &collection, const std::string &name = std::string ());
/**
* @brief Gets the name of the given collection
@ -279,7 +287,7 @@ public:
template <class Collection>
bool is_persisted (const Collection &coll) const
{
return m_name_of_layer.find (layer_of (coll)) != m_name_of_layer.end ();
return is_persisted_impl (coll);
}
/**
@ -705,7 +713,7 @@ public:
* This methods returns a new'd Region. It's the responsibility of the caller
* to delete this object.
*/
db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const;
db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, const db::ICplxTrans &trans = db::ICplxTrans ()) const;
/**
* @brief Delivers all shapes of a specific net and layer to the given Shapes container.
@ -718,7 +726,7 @@ public:
*
* propid is an optional properties ID which is attached to the shapes if not 0.
*/
void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0) const;
void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0, const db::ICplxTrans &trans = db::ICplxTrans ()) const;
/**
* @brief Builds a net representation in the given layout and cell
@ -932,7 +940,7 @@ private:
std::set<db::DeepLayer> m_dlrefs;
std::map<std::string, db::DeepLayer> m_named_regions;
std::map<unsigned int, std::string> m_name_of_layer;
std::map<const db::ShapeCollectionDelegateBase *, db::DeepLayer> m_region_by_original;
std::map<tl::id_type, db::DeepLayer> m_region_by_original;
bool m_netlist_extracted;
bool m_is_flat;
double m_device_scaling;
@ -953,6 +961,7 @@ private:
db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells);
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
bool is_persisted_impl (const db::ShapeCollection &coll) const;
// implementation of NetlistManipulationCallbacks
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);

View File

@ -440,12 +440,6 @@ OriginalLayerRegion::insert_into (Layout *layout, db::cell_index_type into_cell,
}
}
RegionDelegate *OriginalLayerRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const
{
// @@@ TODO: implement (how?)
return 0;
}
void
OriginalLayerRegion::ensure_merged_polygons_valid () const
{

View File

@ -76,8 +76,6 @@ public:
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const;
protected:
virtual void merged_semantics_changed ();
virtual void min_coherence_changed ();

View File

@ -75,7 +75,7 @@ template <>
struct shape_flags_traits<db::Polygon>
: public shape_flags_traits<void>
{
static unsigned int generic () { return db::ShapeIterator::Polygons; }
static unsigned int generic () { return db::ShapeIterator::Regions; }
static unsigned int pure () { return 1 << db::ShapeIterator::Polygon; }
};
@ -83,7 +83,7 @@ template <>
struct shape_flags_traits<db::SimplePolygon>
: public shape_flags_traits<void>
{
static unsigned int generic () { return db::ShapeIterator::Polygons; }
static unsigned int generic () { return db::ShapeIterator::Regions; }
static unsigned int pure () { return 1 << db::ShapeIterator::SimplePolygon; }
};

View File

@ -315,10 +315,12 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
gsi::method ("layer_name", (std::string (db::LayoutToNetlist::*) (unsigned int) const) &db::LayoutToNetlist::name, gsi::arg ("l"),
"@brief Gets the name of the given layer (by index)\n"
) +
gsi::method ("register", (void (db::LayoutToNetlist::*) (const db::ShapeCollection &collection, const std::string &)) &db::LayoutToNetlist::register_layer, gsi::arg ("l"), gsi::arg ("n"),
gsi::method ("register", (void (db::LayoutToNetlist::*) (const db::ShapeCollection &collection, const std::string &)) &db::LayoutToNetlist::register_layer, gsi::arg ("l"), gsi::arg ("n", std::string ()),
"@brief Names the given layer\n"
"'l' must be a hierarchical \\Region or \\Texts object derived with \\make_layer, \\make_text_layer or \\make_polygon_layer or "
"a region derived from those by boolean operations or other hierarchical operations.\n"
"'l' must be a \\Region or \\Texts object.\n"
"Flat regions or text collections must be registered with this function, before they can be used in \\connect. "
"Registering will copy the shapes into the LayoutToNetlist object in this step to enable "
"netlist extraction.\n"
"\n"
"Naming a layer allows the system to indicate the layer in various contexts, i.e. "
"when writing the data to a file. Named layers are also persisted inside the LayoutToNetlist object. "
@ -574,16 +576,20 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
gsi::method ("netlist", &db::LayoutToNetlist::netlist,
"@brief gets the netlist extracted (0 if no extraction happened yet)\n"
) +
gsi::factory ("shapes_of_net", (db::Region *(db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"),
gsi::factory ("shapes_of_net", (db::Region *(db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, const db::ICplxTrans &) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive", true), gsi::arg ("trans", db::ICplxTrans (), "unity"),
"@brief Returns all shapes of a specific net and layer.\n"
"If 'recursive'' is true, the returned region will contain the shapes of\n"
"all subcircuits too.\n"
"\n"
"The optional 'trans' parameter allows applying a transformation to all shapes. It has been introduced in version 0.28.4."
) +
gsi::method ("shapes_of_net", (void (db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, db::Shapes &, db::properties_id_type) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), gsi::arg ("to"), gsi::arg ("propid", db::properties_id_type (0), "0"),
gsi::method ("shapes_of_net", (void (db::LayoutToNetlist::*) (const db::Net &, const db::Region &, bool, db::Shapes &, db::properties_id_type, const db::ICplxTrans &) const) &db::LayoutToNetlist::shapes_of_net, gsi::arg ("net"), gsi::arg ("of_layer"), gsi::arg ("recursive"), gsi::arg ("to"), gsi::arg ("propid", db::properties_id_type (0), "0"), gsi::arg ("trans", db::ICplxTrans (), "unity"),
"@brief Sends all shapes of a specific net and layer to the given Shapes container.\n"
"If 'recursive'' is true, the returned region will contain the shapes of\n"
"all subcircuits too.\n"
"\"prop_id\" is an optional properties ID. If given, this property set will be attached to the shapes."
"\n"
"The optional 'trans' parameter allows applying a transformation to all shapes. It has been introduced in version 0.28.4."
) +
gsi::method_ext ("build_net", &build_net, gsi::arg ("net"), gsi::arg ("target"), gsi::arg ("target_cell"), gsi::arg ("lmap"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"),
"@brief Builds a net representation in the given layout and cell\n"

View File

@ -23,15 +23,12 @@
#include "tlUnitTest.h"
#include "tlStream.h"
#include "tlFileUtils.h"
#include "dbLayoutToNetlist.h"
#include "dbTestSupport.h"
#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)
{
@ -40,33 +37,37 @@ static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_la
return lid;
}
TEST(0_Develop)
db::Region make_region (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, bool flat)
{
return flat ? db::Region (si) : db::Region (si, dss);
}
void run_test (tl::TestBase *_this, bool flat, bool flat_nets, const std::string &au_fn)
{
db::Layout ly;
db::DeepShapeStore dss;
// @@@ dss.set_subcircuit_hierarchy_for_nets (true);
if (! flat_nets) {
dss.set_subcircuit_hierarchy_for_nets (true);
}
db::LayerMap lmap;
unsigned int poly = define_layer (ly, lmap, 7);
unsigned int cont = define_layer (ly, lmap, 14);
unsigned int metal1 = define_layer (ly, lmap, 15);
unsigned int via1 = define_layer (ly, lmap, 16);
unsigned int metal2 = define_layer (ly, lmap, 17);
unsigned int via2 = define_layer (ly, lmap, 18);
unsigned int metal3 = define_layer (ly, lmap, 19);
unsigned int via3 = define_layer (ly, lmap, 20);
unsigned int metal4 = define_layer (ly, lmap, 21);
unsigned int poly = define_layer (ly, lmap, 1);
unsigned int cont = define_layer (ly, lmap, 2);
unsigned int metal1 = define_layer (ly, lmap, 3);
unsigned int via1 = define_layer (ly, lmap, 4);
unsigned int metal2 = define_layer (ly, lmap, 5);
unsigned int via2 = define_layer (ly, lmap, 6);
unsigned int metal3 = define_layer (ly, lmap, 7);
unsigned int via3 = define_layer (ly, lmap, 8);
unsigned int metal4 = define_layer (ly, lmap, 9);
{
db::LoadLayoutOptions options;
options.get_options<db::CommonReaderOptions> ().layer_map = lmap;
options.get_options<db::CommonReaderOptions> ().create_other_layers = false;
// @@@ std::string fn (tl::testdata ());
// @@@ fn = tl::combine_path (fn, "algo");
// @@@ fn = tl::combine_path (fn, "device_extract_l1.gds");
std::string fn ("/home/matthias/klayout/testdata/laurent_ANA_DRIVE7/ANA_DRIVE7.gds"); // @@@
std::string fn = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "nets_proc_1.gds");
tl::InputStream stream (fn);
db::Reader reader (stream);
@ -75,21 +76,39 @@ TEST(0_Develop)
db::Cell &tc = ly.cell (*ly.begin_top_down ());
db::Region rpoly (db::RecursiveShapeIterator (ly, tc, poly), dss);
db::Region rcont (db::RecursiveShapeIterator (ly, tc, cont), dss);
db::Region rmetal1 (db::RecursiveShapeIterator (ly, tc, metal1), dss);
db::Region rvia1 (db::RecursiveShapeIterator (ly, tc, via1), dss);
db::Region rmetal2 (db::RecursiveShapeIterator (ly, tc, metal2), dss);
db::Region rvia2 (db::RecursiveShapeIterator (ly, tc, via2), dss);
db::Region rmetal3 (db::RecursiveShapeIterator (ly, tc, metal3), dss);
db::Region rvia3 (db::RecursiveShapeIterator (ly, tc, via3), dss);
db::Region rmetal4 (db::RecursiveShapeIterator (ly, tc, metal4), dss);
db::Region rpoly = make_region (db::RecursiveShapeIterator (ly, tc, poly), dss, flat);
db::Region rcont = make_region (db::RecursiveShapeIterator (ly, tc, cont), dss, flat);
db::Region rmetal1 = make_region (db::RecursiveShapeIterator (ly, tc, metal1), dss, flat);
db::Region rvia1 = make_region (db::RecursiveShapeIterator (ly, tc, via1), dss, flat);
db::Region rmetal2 = make_region (db::RecursiveShapeIterator (ly, tc, metal2), dss, flat);
db::Region rvia2 = make_region (db::RecursiveShapeIterator (ly, tc, via2), dss, flat);
db::Region rmetal3 = make_region (db::RecursiveShapeIterator (ly, tc, metal3), dss, flat);
db::Region rvia3 = make_region (db::RecursiveShapeIterator (ly, tc, via3), dss, flat);
db::Region rmetal4 = make_region (db::RecursiveShapeIterator (ly, tc, metal4), dss, flat);
std::unique_ptr<db::LayoutToNetlist> l2n (new db::LayoutToNetlist (&dss));
EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false);
std::unique_ptr<db::LayoutToNetlist> l2n;
if (! flat) {
l2n.reset (new db::LayoutToNetlist (&dss));
EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false);
} else {
l2n.reset (new db::LayoutToNetlist (ly.cell_name (tc.cell_index ()), ly.dbu ()));
}
// net extraction
if (flat) {
// flat or original layers need to be registered
l2n->register_layer (rpoly);
l2n->register_layer (rcont);
l2n->register_layer (rmetal1);
l2n->register_layer (rvia1);
l2n->register_layer (rmetal2);
l2n->register_layer (rvia2);
l2n->register_layer (rmetal3);
l2n->register_layer (rvia3);
l2n->register_layer (rmetal4);
}
// Intra-layer
l2n->connect (rpoly);
l2n->connect (rcont);
@ -110,41 +129,17 @@ TEST(0_Develop)
l2n->connect (rmetal3, rvia3);
l2n->connect (rvia3, rmetal4);
printf("@@@ extraction\n"); fflush(stdout);
l2n->extract_netlist ();
printf("@@@ cells1=%d\n", int(dss.layout ().cells())); fflush(stdout);
db::Region rmetal1_nets = rmetal1.nets (*l2n, db::NPM_NetNameAndIDOnly, tl::Variant (1));
EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), true);
printf("@@@ cells2=%d\n", int(dss.layout ().cells())); fflush(stdout);
if (! flat) {
EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), true);
}
db::Region rmetal2_nets = rmetal2.nets (*l2n, db::NPM_NetNameAndIDOnly, tl::Variant (1));
printf("@@@ cells3=%d\n", int(dss.layout ().cells())); fflush(stdout);
db::Region rmetal1_nets_more = rmetal1.nets (*l2n, db::NPM_NetNameAndIDOnly, tl::Variant (1));
printf("@@@ cells4=%d\n", int(dss.layout ().cells())); fflush(stdout);
// @@@
dss.layout().set_properties(rpoly.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(7, 0));
dss.layout().set_properties(rcont.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(14, 0));
dss.layout().set_properties(rmetal1.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(15, 0));
dss.layout().set_properties(rvia1.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(16, 0));
dss.layout().set_properties(rmetal2.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(17, 0));
dss.layout().set_properties(rmetal1_nets.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(115, 0));
dss.layout().set_properties(rmetal2_nets.delegate ()->deep ()->deep_layer ().layer (), db::LayerProperties(117, 0));
{
db::SaveLayoutOptions options;
std::string fn ("net_outx.gds"); // @@@
tl::OutputStream stream (fn);
db::Writer writer (options);
writer.write (dss.layout(), stream);
}
// @@@
db::Region res1 = rmetal1_nets.bool_and (rmetal2_nets, db::SamePropertiesConstraint);
printf("@@@2\n"); fflush(stdout);
db::Region res2 = rmetal1_nets.bool_and (rmetal2_nets, db::DifferentPropertiesConstraint);
printf("@@@3\n"); fflush(stdout);
db::Region res3 = rmetal1_nets.bool_and (rmetal2_nets, db::NoPropertyConstraint);
printf("@@@4\n"); fflush(stdout);
rmetal1_nets.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (100, 0)));
rmetal2_nets.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (101, 0)));
@ -152,19 +147,28 @@ printf("@@@4\n"); fflush(stdout);
res1.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (1000, 0)));
res2.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (1001, 0)));
res3.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (1002, 0)));
printf("@@@5\n"); fflush(stdout);
// Test auto-unregistration
l2n.reset (0);
EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false);
{
db::SaveLayoutOptions options;
std::string fn (dss.subcircuit_hierarchy_for_nets () ? "net_outh.gds" : "net_out.gds"); // @@@
tl::OutputStream stream (fn);
db::Writer writer (options);
writer.write (ly, stream);
if (! flat) {
EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false);
}
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), au_fn);
db::compare_layouts (_this, ly, au_path);
}
TEST(1_NetSpecificBoolFlat)
{
run_test (_this, false, true, "net_proc_au1.gds");
}
TEST(2_NetSpecificBoolFlatNets)
{
run_test (_this, false, true, "net_proc_au2.gds");
}
TEST(3_NetSpecificBoolFullyHier)
{
run_test (_this, false, false, "net_proc_au3.gds");
}

BIN
testdata/algo/net_proc_au1.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/net_proc_au2.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/net_proc_au3.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/nets_proc_1.gds vendored Normal file

Binary file not shown.