mirror of https://github.com/KLayout/klayout.git
WIP: debugging and unit test for net-aware booleans
This commit is contained in:
parent
e1ddd6f8d2
commit
984c001f56
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue