mirror of https://github.com/KLayout/klayout.git
Refactoring, some bugfixes, GSI bindings for L2N methods.
This commit is contained in:
parent
4c7f43d749
commit
f83e1dae43
|
|
@ -46,6 +46,7 @@ public:
|
|||
DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics = true, double area_ratio = 3.0, size_t max_vertex_count = 16);
|
||||
|
||||
DeepRegion (const DeepRegion &other);
|
||||
DeepRegion (const DeepLayer &dl);
|
||||
|
||||
virtual ~DeepRegion ();
|
||||
|
||||
|
|
@ -94,10 +95,9 @@ protected:
|
|||
|
||||
private:
|
||||
DeepRegion &operator= (const DeepRegion &other);
|
||||
DeepRegion (const DeepLayer &dl);
|
||||
|
||||
DeepLayer m_deep_layer;
|
||||
// @@@ have hierarchical merged polygons later
|
||||
// TODO: have hierarchical merged polygons later
|
||||
mutable db::Shapes m_merged_polygons;
|
||||
mutable bool m_merged_polygons_valid;
|
||||
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ struct DeepShapeStore::LayoutHolder
|
|||
void remove_layer_ref (unsigned int layer)
|
||||
{
|
||||
if ((layer_refs[layer] -= 1) <= 0) {
|
||||
layout.clear_layer (layer);
|
||||
layout.delete_layer (layer);
|
||||
layer_refs.erase (layer);
|
||||
}
|
||||
}
|
||||
|
|
@ -343,7 +343,9 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
|
|||
|
||||
db::Layout &layout = m_layouts.back ()->layout;
|
||||
layout.hier_changed_event.add (this, &DeepShapeStore::invalidate_hier);
|
||||
layout.dbu (si.layout ()->dbu ());
|
||||
if (si.layout ()) {
|
||||
layout.dbu (si.layout ()->dbu ());
|
||||
}
|
||||
|
||||
m_layout_map[si] = layout_index;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,13 +36,22 @@ static HierarchyBuilderShapeInserter def_inserter;
|
|||
int
|
||||
compare_iterators_with_respect_to_target_hierarchy (const db::RecursiveShapeIterator &iter1, const db::RecursiveShapeIterator &iter2)
|
||||
{
|
||||
if ((iter1.layout () == 0) != (iter2.layout () == 0)) {
|
||||
return (iter1.layout () == 0) < (iter2.layout () == 0);
|
||||
}
|
||||
if ((iter1.top_cell () == 0) != (iter2.top_cell () == 0)) {
|
||||
return (iter1.top_cell () == 0) < (iter2.top_cell () == 0);
|
||||
}
|
||||
|
||||
// basic source (layout, top_cell) needs to be the same of course
|
||||
if (iter1.layout () != iter2.layout ()) {
|
||||
// NOTE: pointer compare :-(
|
||||
return iter1.layout () < iter2.layout () ? -1 : 1;
|
||||
}
|
||||
if (iter1.top_cell ()->cell_index () != iter2.top_cell ()->cell_index ()) {
|
||||
return iter1.top_cell ()->cell_index () < iter2.top_cell ()->cell_index () ? -1 : 1;
|
||||
if (iter1.top_cell ()) {
|
||||
if (iter1.top_cell ()->cell_index () != iter2.top_cell ()->cell_index ()) {
|
||||
return iter1.top_cell ()->cell_index () < iter2.top_cell ()->cell_index () ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
// max depth controls the main hierarchical appearance
|
||||
|
|
@ -51,10 +60,11 @@ compare_iterators_with_respect_to_target_hierarchy (const db::RecursiveShapeIter
|
|||
}
|
||||
|
||||
// if a region is set, the hierarchical appearance is the same only if the layers and
|
||||
// complex region are indentical
|
||||
// complex region are identical
|
||||
if ((iter1.region () == db::Box::world ()) != (iter2.region () == db::Box::world ())) {
|
||||
return (iter1.region () == db::Box::world ()) < (iter2.region () == db::Box::world ()) ? -1 : 1;
|
||||
}
|
||||
|
||||
if (iter1.region () != db::Box::world ()) {
|
||||
if (iter1.has_complex_region () != iter2.has_complex_region ()) {
|
||||
return iter1.has_complex_region () < iter2.has_complex_region () ? -1 : 1;
|
||||
|
|
@ -174,30 +184,36 @@ HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
|
|||
m_cell_stack.clear ();
|
||||
m_cells_seen.clear ();
|
||||
|
||||
if (! iter->layout () || ! iter->top_cell ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::pair<db::cell_index_type, std::set<db::Box> > key (iter->top_cell ()->cell_index (), std::set<db::Box> ());
|
||||
m_cm_entry = m_cell_map.find (key);
|
||||
m_cm_new_entry = false;
|
||||
|
||||
if (m_cm_entry == m_cell_map.end ()) {
|
||||
db::cell_index_type new_top_index = mp_target->add_cell (iter->layout ()->cell_name (key.first));
|
||||
m_cm_entry = m_cell_map.insert (std::make_pair (key, new_top_index)).first;
|
||||
m_cm_new_entry = true;
|
||||
}
|
||||
|
||||
db::Cell &new_top = mp_target->cell (m_cm_entry->second);
|
||||
m_cells_seen.insert (key);
|
||||
|
||||
// NOTE: we consider the top cell "new" if it does not have instances.
|
||||
// We can do so as the recursive shape iterator will always deliver all instances
|
||||
// and not a partial set of instances.
|
||||
m_cm_new_entry = new_top.begin ().at_end ();
|
||||
m_cell_stack.push_back (std::make_pair (m_cm_new_entry, &new_top));
|
||||
}
|
||||
|
||||
void
|
||||
HierarchyBuilder::end (const RecursiveShapeIterator * /*iter*/)
|
||||
HierarchyBuilder::end (const RecursiveShapeIterator *iter)
|
||||
{
|
||||
tl_assert (m_cell_stack.size () == 1);
|
||||
tl_assert (! iter->layout () || ! iter->top_cell () || m_cell_stack.size () == 1);
|
||||
|
||||
m_initial_pass = false;
|
||||
m_cells_seen.clear ();
|
||||
mp_initial_cell = m_cell_stack.front ().second;
|
||||
mp_initial_cell = m_cell_stack.empty () ? 0 : m_cell_stack.front ().second;
|
||||
m_cell_stack.clear ();
|
||||
m_cm_entry = cell_map_type::const_iterator ();
|
||||
m_cm_new_entry = false;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ static bool is_deep (const db::Region &r)
|
|||
}
|
||||
|
||||
// the iterator provides the hierarchical selection (enabling/disabling cells etc.)
|
||||
|
||||
LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter)
|
||||
: m_iter (iter), m_netlist_extracted (false)
|
||||
{
|
||||
|
|
@ -44,6 +45,17 @@ LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter)
|
|||
throw tl::Exception (tl::to_string (tr ("The netlist extractor cannot work on clipped layouts")));
|
||||
}
|
||||
|
||||
init ();
|
||||
}
|
||||
|
||||
LayoutToNetlist::LayoutToNetlist ()
|
||||
: m_iter (), m_netlist_extracted (false)
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
||||
void LayoutToNetlist::init ()
|
||||
{
|
||||
m_dss.set_text_enlargement (1);
|
||||
m_dss.set_text_property_name (tl::Variant ("LABEL"));
|
||||
}
|
||||
|
|
@ -83,11 +95,11 @@ db::Region *LayoutToNetlist::make_layer (const std::string &n)
|
|||
db::RecursiveShapeIterator si (m_iter);
|
||||
si.shape_flags (db::ShapeIterator::Nothing);
|
||||
|
||||
db::Region *region = new db::Region (si, m_dss);
|
||||
std::auto_ptr <db::Region> region (new db::Region (si, m_dss));
|
||||
if (! n.empty ()) {
|
||||
name (*region, n);
|
||||
register_layer (*region, n);
|
||||
}
|
||||
return region;
|
||||
return region.release ();
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::make_layer (unsigned int layer_index, const std::string &n)
|
||||
|
|
@ -96,11 +108,11 @@ db::Region *LayoutToNetlist::make_layer (unsigned int layer_index, const std::st
|
|||
si.set_layer (layer_index);
|
||||
si.shape_flags (db::ShapeIterator::All);
|
||||
|
||||
db::Region *region = new db::Region (si, m_dss);
|
||||
std::auto_ptr <db::Region> region (new db::Region (si, m_dss));
|
||||
if (! n.empty ()) {
|
||||
name (*region, n);
|
||||
register_layer (*region, n);
|
||||
}
|
||||
return region;
|
||||
return region.release ();
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::make_text_layer (unsigned int layer_index, const std::string &n)
|
||||
|
|
@ -109,11 +121,11 @@ db::Region *LayoutToNetlist::make_text_layer (unsigned int layer_index, const st
|
|||
si.set_layer (layer_index);
|
||||
si.shape_flags (db::ShapeIterator::Texts);
|
||||
|
||||
db::Region *region = new db::Region (si, m_dss);
|
||||
std::auto_ptr <db::Region> region (new db::Region (si, m_dss));
|
||||
if (! n.empty ()) {
|
||||
name (*region, n);
|
||||
register_layer (*region, n);
|
||||
}
|
||||
return region;
|
||||
return region.release ();
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::make_polygon_layer (unsigned int layer_index, const std::string &n)
|
||||
|
|
@ -122,11 +134,11 @@ db::Region *LayoutToNetlist::make_polygon_layer (unsigned int layer_index, const
|
|||
si.set_layer (layer_index);
|
||||
si.shape_flags (db::ShapeIterator::Paths | db::ShapeIterator::Polygons | db::ShapeIterator::Boxes);
|
||||
|
||||
db::Region *region = new db::Region (si, m_dss);
|
||||
std::auto_ptr <db::Region> region (new db::Region (si, m_dss));
|
||||
if (! n.empty ()) {
|
||||
name (*region, n);
|
||||
register_layer (*region, n);
|
||||
}
|
||||
return region;
|
||||
return region.release ();
|
||||
}
|
||||
|
||||
void LayoutToNetlist::extract_devices (db::NetlistDeviceExtractor &extractor, const std::map<std::string, db::Region *> &layers)
|
||||
|
|
@ -148,6 +160,9 @@ void LayoutToNetlist::connect (const db::Region &l)
|
|||
if (! is_deep (l)) {
|
||||
throw (tl::Exception (tl::to_string (tr ("Non-hierarchical layers cannot be used in intra-layer connectivity for netlist extraction"))));
|
||||
}
|
||||
if (! is_persisted (l)) {
|
||||
throw (tl::Exception (tl::to_string (tr ("Only named layers can be used in intra-layer connectivity for netlist extraction"))));
|
||||
}
|
||||
|
||||
// we need to keep a reference, so we can safely delete the region
|
||||
db::DeepLayer dl (l);
|
||||
|
|
@ -167,6 +182,12 @@ void LayoutToNetlist::connect (const db::Region &a, const db::Region &b)
|
|||
if (! is_deep (b)) {
|
||||
throw (tl::Exception (tl::to_string (tr ("Non-hierarchical layers cannot be used in inter-layer connectivity (second layer) for netlist extraction"))));
|
||||
}
|
||||
if (! is_persisted (a)) {
|
||||
throw (tl::Exception (tl::to_string (tr ("Only named layers can be used in inter-layer connectivity (first layer) for netlist extraction"))));
|
||||
}
|
||||
if (! is_persisted (b)) {
|
||||
throw (tl::Exception (tl::to_string (tr ("Only named layers can be used in inter-layer connectivity (second layer) for netlist extraction"))));
|
||||
}
|
||||
|
||||
// we need to keep a reference, so we can safely delete the region
|
||||
db::DeepLayer dla (a), dlb (b);
|
||||
|
|
@ -182,7 +203,10 @@ size_t LayoutToNetlist::connect_global (const db::Region &l, const std::string &
|
|||
throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted")));
|
||||
}
|
||||
if (! is_deep (l)) {
|
||||
throw (tl::Exception (tl::to_string (tr ("Non-hierarchical layers cannot be used in intra-layer connectivity for netlist extraction"))));
|
||||
throw (tl::Exception (tl::to_string (tr ("Non-hierarchical layers cannot be used in global connectivity for netlist extraction"))));
|
||||
}
|
||||
if (! is_persisted (l)) {
|
||||
throw (tl::Exception (tl::to_string (tr ("Only named layers can be used in global connectivity for netlist extraction"))));
|
||||
}
|
||||
|
||||
// we need to keep a reference, so we can safely delete the region
|
||||
|
|
@ -232,6 +256,14 @@ const db::Cell *LayoutToNetlist::internal_top_cell () const
|
|||
return &m_dss.const_initial_cell ();
|
||||
}
|
||||
|
||||
void LayoutToNetlist::ensure_internal_layout ()
|
||||
{
|
||||
if (m_dss.layouts () == 0) {
|
||||
// the dummy layer acts as a reference holder for the layout
|
||||
m_dummy_layer = m_dss.create_polygon_layer (db::RecursiveShapeIterator ());
|
||||
}
|
||||
}
|
||||
|
||||
db::Layout *LayoutToNetlist::internal_layout ()
|
||||
{
|
||||
return &m_dss.layout ();
|
||||
|
|
@ -242,13 +274,69 @@ db::Cell *LayoutToNetlist::internal_top_cell ()
|
|||
return &m_dss.initial_cell ();
|
||||
}
|
||||
|
||||
void LayoutToNetlist::name (const db::Region ®ion, const std::string &name)
|
||||
void LayoutToNetlist::register_layer (const db::Region ®ion, const std::string &n)
|
||||
{
|
||||
unsigned int li = layer_of (region);
|
||||
db::Layout &ly = m_dss.layout ();
|
||||
db::LayerProperties lp = ly.get_properties (li);
|
||||
lp.name = name;
|
||||
ly.set_properties (li, lp);
|
||||
if (m_named_regions.find (n) != m_named_regions.end ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n);
|
||||
}
|
||||
|
||||
db::DeepRegion *delegate = dynamic_cast<db::DeepRegion *> (region.delegate());
|
||||
if (! delegate) {
|
||||
throw tl::Exception (tl::to_string (tr ("Layer is not a deep region")));
|
||||
}
|
||||
|
||||
if (is_persisted (region)) {
|
||||
std::string prev_name = name (region);
|
||||
m_named_regions.erase (prev_name);
|
||||
}
|
||||
|
||||
m_named_regions [n] = delegate->deep_layer ();
|
||||
m_name_of_layer [layer_of (region)] = n;
|
||||
}
|
||||
|
||||
std::string LayoutToNetlist::name (const db::Region ®ion) const
|
||||
{
|
||||
std::map<unsigned int, std::string>::const_iterator n = m_name_of_layer.find (layer_of (region));
|
||||
if (n != m_name_of_layer.end ()) {
|
||||
return n->second;
|
||||
} else {
|
||||
return std::string ();
|
||||
}
|
||||
}
|
||||
|
||||
std::string LayoutToNetlist::name (unsigned int l) const
|
||||
{
|
||||
std::map<unsigned int, std::string>::const_iterator n = m_name_of_layer.find (l);
|
||||
if (n != m_name_of_layer.end ()) {
|
||||
return n->second;
|
||||
} else {
|
||||
return std::string ();
|
||||
}
|
||||
}
|
||||
|
||||
bool LayoutToNetlist::is_persisted (const db::Region ®ion) const
|
||||
{
|
||||
return m_name_of_layer.find (layer_of (region)) != m_name_of_layer.end ();
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::layer_by_name (const std::string &name)
|
||||
{
|
||||
std::map<std::string, db::DeepLayer>::const_iterator l = m_named_regions.find (name);
|
||||
if (l == m_named_regions.end ()) {
|
||||
return 0;
|
||||
} else {
|
||||
return new db::Region (new db::DeepRegion (l->second));
|
||||
}
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::layer_by_index (unsigned int index)
|
||||
{
|
||||
std::map<unsigned int, std::string>::const_iterator n = m_name_of_layer.find (index);
|
||||
if (n == m_name_of_layer.end ()) {
|
||||
return 0;
|
||||
} else {
|
||||
return layer_by_name (n->second);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int LayoutToNetlist::layer_of (const db::Region ®ion) const
|
||||
|
|
@ -433,8 +521,10 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
|
|||
|
||||
bool consider_cell = any_connections;
|
||||
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end () && !consider_cell; ++l) {
|
||||
StopOnFirst sof;
|
||||
consider_cell = deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, sof);
|
||||
if (l->second) {
|
||||
StopOnFirst sof;
|
||||
consider_cell = !deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, sof);
|
||||
}
|
||||
}
|
||||
|
||||
if (! consider_cell) {
|
||||
|
|
@ -452,7 +542,9 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
|
|||
}
|
||||
|
||||
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
|
||||
deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, target_cell->shapes (l->first));
|
||||
if (l->second) {
|
||||
deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, target_cell->shapes (l->first));
|
||||
}
|
||||
}
|
||||
|
||||
if (! circuit_cell_name_prefix && ! device_cell_name_prefix) {
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ class DB_PUBLIC LayoutToNetlist
|
|||
: public gsi::ObjectBase, public tl::Object
|
||||
{
|
||||
public:
|
||||
typedef std::map<unsigned int, std::string>::const_iterator layer_iterator;
|
||||
|
||||
/**
|
||||
* @brief The constructor
|
||||
*
|
||||
|
|
@ -80,6 +82,11 @@ public:
|
|||
*/
|
||||
LayoutToNetlist (const db::RecursiveShapeIterator &iter);
|
||||
|
||||
/**
|
||||
* @brief The default constructor
|
||||
*/
|
||||
LayoutToNetlist ();
|
||||
|
||||
/**
|
||||
* @brief Sets the number of threads to use for operations which support multiple threads
|
||||
*/
|
||||
|
|
@ -115,28 +122,74 @@ public:
|
|||
size_t max_vertex_count () const;
|
||||
|
||||
/**
|
||||
* @brief Names a layer
|
||||
* @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
|
||||
* if layers are involved. Use this method or the other variants to
|
||||
* attach a name or standard layer properties to a region delivered
|
||||
* by "make_layer" or derived from other regions through boolean
|
||||
* operations.
|
||||
* 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. Only
|
||||
* named regions can be put into "connect".
|
||||
*/
|
||||
void name (const db::Region ®ion, const std::string &name);
|
||||
void register_layer (const db::Region ®ion, const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the given layer
|
||||
* @brief Gets the name of the given region
|
||||
* Returns an empty string if the region does not have a name.
|
||||
*/
|
||||
std::string name (const db::Region ®ion) const
|
||||
std::string name (const db::Region ®ion) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the given layer by index
|
||||
* Returns an empty string if the layer does not have a name.
|
||||
*/
|
||||
std::string name (unsigned int) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the region is a persisted region
|
||||
* Persisted regions have a name and are kept inside the LayoutToNetlist
|
||||
* object.
|
||||
*/
|
||||
bool is_persisted (const db::Region ®ion) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the region (layer) with the given name
|
||||
* If the name is not valid, this method returns 0. Otherwise it
|
||||
* will return a new'd Region object referencing the layer with
|
||||
* the given name. It must be deleted by the caller.
|
||||
*/
|
||||
db::Region *layer_by_name (const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Gets the region (layer) by index
|
||||
* If the index is not valid, this method returns 0. Otherwise it
|
||||
* will return a new'd Region object referencing the layer with
|
||||
* the given name. It must be deleted by the caller.
|
||||
* Only named layers are managed by LayoutToNetlist and can
|
||||
* be retrieved with this method.
|
||||
*/
|
||||
db::Region *layer_by_index (unsigned int index);
|
||||
|
||||
/**
|
||||
* @brief Iterates over the layer indexes and names managed by this object (begin)
|
||||
*/
|
||||
layer_iterator begin_layers () const
|
||||
{
|
||||
return internal_layout ()->get_properties (layer_of (region)).name;
|
||||
return m_name_of_layer.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates over the layer indexes and names managed by this object (end)
|
||||
*/
|
||||
layer_iterator end_layers () const
|
||||
{
|
||||
return m_name_of_layer.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new empty region
|
||||
* This method returns a new'd object which must be deleted by the caller.
|
||||
*/
|
||||
db::Region *make_layer (const std::string &n);
|
||||
db::Region *make_layer (const std::string &name = std::string ());
|
||||
|
||||
/**
|
||||
* @brief Creates a new region representing an original layer
|
||||
|
|
@ -144,6 +197,11 @@ public:
|
|||
* This variant produces polygons and takes texts for net name annotation.
|
||||
* A variant not taking texts is "make_polygon_layer". A Variant only taking
|
||||
* texts is "make_text_layer".
|
||||
* All variants return a new'd object which must be deleted by the caller.
|
||||
* Named regions are considered "precious". The LayoutToNetlist object will
|
||||
* keep a reference on all named layers, so they persist during the lifetime
|
||||
* of the LayoutToNetlist object.
|
||||
* Only named layers can be used for connect (see below).
|
||||
*/
|
||||
db::Region *make_layer (unsigned int layer_index, const std::string &name = std::string ());
|
||||
|
||||
|
|
@ -179,18 +237,21 @@ public:
|
|||
* a derived layer. Certain limitations apply. It's safe to use
|
||||
* boolean operations for deriving layers. Other operations are applicable as long as they are
|
||||
* capable of delivering hierarchical layers.
|
||||
* Regions put into "connect" need to be named.
|
||||
*/
|
||||
void connect (const db::Region &l);
|
||||
|
||||
/**
|
||||
* @brief Defines an inter-layer connection for the given layers.
|
||||
* The conditions mentioned with intra-layer "connect" apply for this method too.
|
||||
* Regions put into "connect" need to be named.
|
||||
*/
|
||||
void connect (const db::Region &a, const db::Region &b);
|
||||
|
||||
/**
|
||||
* @brief Connects the given layer with a global net with the given name
|
||||
* Returns the global net ID
|
||||
* Regions put into "connect" need to be named.
|
||||
*/
|
||||
size_t connect_global (const db::Region &l, const std::string &gn);
|
||||
|
||||
|
|
@ -237,6 +298,11 @@ public:
|
|||
*/
|
||||
db::Cell *internal_top_cell ();
|
||||
|
||||
/**
|
||||
* @brief Ensures the internal layout is made
|
||||
*/
|
||||
void ensure_internal_layout ();
|
||||
|
||||
/**
|
||||
* @brief Gets the connectivity object
|
||||
*/
|
||||
|
|
@ -406,8 +472,12 @@ private:
|
|||
db::hier_clusters<db::PolygonRef> m_net_clusters;
|
||||
std::auto_ptr<db::Netlist> mp_netlist;
|
||||
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;
|
||||
bool m_netlist_extracted;
|
||||
db::DeepLayer m_dummy_layer;
|
||||
|
||||
void init ();
|
||||
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<db::PolygonRef> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
|
||||
void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const ICplxTrans &tr) const;
|
||||
void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const Net *net, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const ICplxTrans &tr) const;
|
||||
|
|
|
|||
|
|
@ -29,46 +29,6 @@ namespace db
|
|||
|
||||
namespace l2n_std_reader {
|
||||
|
||||
class Layers
|
||||
{
|
||||
public:
|
||||
Layers () { }
|
||||
|
||||
~Layers ()
|
||||
{
|
||||
for (std::map<std::string, db::Region *>::const_iterator i = m_layers.begin (); i != m_layers.end (); ++i) {
|
||||
delete i->second;
|
||||
}
|
||||
m_layers.clear ();
|
||||
}
|
||||
|
||||
void add (const std::string &name, db::Region *region)
|
||||
{
|
||||
if (m_layers.find (name) != m_layers.end ()) {
|
||||
delete region;
|
||||
throw tl::Exception (tl::to_string (tr ("Duplicate layer name: ")) + name);
|
||||
}
|
||||
m_layers.insert (std::make_pair (name, region));
|
||||
}
|
||||
|
||||
bool has_layer (const std::string &name) const
|
||||
{
|
||||
return m_layers.find (name) != m_layers.end ();
|
||||
}
|
||||
|
||||
db::Region &layer (const std::string &name)
|
||||
{
|
||||
std::map<std::string, db::Region *>::const_iterator l = m_layers.find (name);
|
||||
if (l == m_layers.end ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Not a valid layer name: ")) + name);
|
||||
}
|
||||
return *l->second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, db::Region *> m_layers;
|
||||
};
|
||||
|
||||
class Brace
|
||||
{
|
||||
public:
|
||||
|
|
@ -185,9 +145,13 @@ void LayoutToNetlistStandardReader::read (db::LayoutToNetlist *l2n)
|
|||
}
|
||||
}
|
||||
|
||||
const db::Region *LayoutToNetlistStandardReader::layer_by_name (const std::string &name)
|
||||
static db::Region &layer_by_name (db::LayoutToNetlist *l2n, const std::string &name)
|
||||
{
|
||||
return mp_layers->has_layer (name) ? &mp_layers->layer (name) : 0;
|
||||
db::Region *l = l2n->layer_by_name (name);
|
||||
if (! l) {
|
||||
throw tl::Exception (tl::to_string (tr ("Not a valid layer name: ")) + name);
|
||||
}
|
||||
return *l;
|
||||
}
|
||||
|
||||
void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
|
||||
|
|
@ -196,13 +160,17 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
|
|||
std::string description;
|
||||
|
||||
// TODO: there probably is a more efficient way to force the layout inside l2n to be made
|
||||
l2n->make_layer (std::string ());
|
||||
l2n->ensure_internal_layout ();
|
||||
tl_assert (l2n->internal_layout ());
|
||||
l2n->internal_layout ()->dbu (1.0); // mainly for testing
|
||||
|
||||
if (l2n->internal_layout ()->cells () == 0) {
|
||||
l2n->internal_layout ()->add_cell ("TOP");
|
||||
}
|
||||
tl_assert (l2n->internal_top_cell () != 0);
|
||||
|
||||
l2n->make_netlist ();
|
||||
|
||||
mp_layers.reset (new Layers ());
|
||||
|
||||
while (! at_end ()) {
|
||||
|
||||
if (test (skeys::version_key) || test (lkeys::version_key)) {
|
||||
|
|
@ -237,7 +205,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
|
|||
Brace br (this);
|
||||
std::string layer;
|
||||
read_word_or_quoted (layer);
|
||||
mp_layers->add (layer, l2n->make_layer (layer));
|
||||
delete l2n->make_layer (layer);
|
||||
br.done ();
|
||||
|
||||
} else if (test (skeys::connect_key) || test (lkeys::connect_key)) {
|
||||
|
|
@ -248,7 +216,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
|
|||
while (br) {
|
||||
std::string l2;
|
||||
read_word_or_quoted (l2);
|
||||
l2n->connect (mp_layers->layer (l1), mp_layers->layer (l2));
|
||||
l2n->connect (layer_by_name (l2n, l1), layer_by_name (l2n, l2));
|
||||
}
|
||||
br.done ();
|
||||
|
||||
|
|
@ -260,7 +228,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
|
|||
while (br) {
|
||||
std::string g;
|
||||
read_word_or_quoted (g);
|
||||
l2n->connect_global (mp_layers->layer (l1), g);
|
||||
l2n->connect_global (layer_by_name (l2n, l1), g);
|
||||
}
|
||||
br.done ();
|
||||
|
||||
|
|
@ -377,7 +345,7 @@ LayoutToNetlistStandardReader::read_geometry (db::LayoutToNetlist *l2n)
|
|||
Brace br (this);
|
||||
|
||||
read_word_or_quoted (lname);
|
||||
unsigned int lid = l2n->layer_of (mp_layers->layer (lname));
|
||||
unsigned int lid = l2n->layer_of (layer_by_name (l2n, lname));
|
||||
|
||||
db::Coord l = read_coord ();
|
||||
db::Coord b = read_coord ();
|
||||
|
|
@ -394,7 +362,7 @@ LayoutToNetlistStandardReader::read_geometry (db::LayoutToNetlist *l2n)
|
|||
Brace br (this);
|
||||
|
||||
read_word_or_quoted (lname);
|
||||
unsigned int lid = l2n->layer_of (mp_layers->layer (lname));
|
||||
unsigned int lid = l2n->layer_of (layer_by_name (l2n, lname));
|
||||
|
||||
std::vector<db::Point> pt;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,8 +65,6 @@ public:
|
|||
|
||||
void read (db::LayoutToNetlist *l2n);
|
||||
|
||||
const db::Region *layer_by_name (const std::string &name);
|
||||
|
||||
private:
|
||||
friend class l2n_std_reader::Brace;
|
||||
typedef l2n_std_reader::Brace Brace;
|
||||
|
|
@ -85,7 +83,6 @@ private:
|
|||
std::string m_path;
|
||||
std::string m_line;
|
||||
tl::Extractor m_ex;
|
||||
std::auto_ptr<Layers> mp_layers;
|
||||
|
||||
void do_read (db::LayoutToNetlist *l2n);
|
||||
|
||||
|
|
|
|||
|
|
@ -63,14 +63,13 @@ std_writer_impl<Keys>::std_writer_impl (tl::OutputStream &stream)
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
static std::string name_for_layer (const db::Layout *layout, unsigned int l)
|
||||
static std::string name_for_layer (const db::LayoutToNetlist *l2n, unsigned int l)
|
||||
{
|
||||
const db::LayerProperties &lp = layout->get_properties (l);
|
||||
if (lp.is_named ()) {
|
||||
return tl::to_word_or_quoted_string (lp.name);
|
||||
} else {
|
||||
return "L" + tl::to_string (l);
|
||||
std::string n = l2n->name (l);
|
||||
if (n.empty ()) {
|
||||
n = "L" + tl::to_string (l);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
template <class Keys>
|
||||
|
|
@ -104,7 +103,7 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n)
|
|||
*mp_stream << endl << "# Mask layers" << endl;
|
||||
}
|
||||
for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) {
|
||||
*mp_stream << Keys::layer_key << "(" << name_for_layer (ly, *l) << ")" << endl;
|
||||
*mp_stream << Keys::layer_key << "(" << name_for_layer (l2n, *l) << ")" << endl;
|
||||
}
|
||||
|
||||
if (! Keys::is_short ()) {
|
||||
|
|
@ -115,9 +114,9 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n)
|
|||
db::Connectivity::layer_iterator ce = l2n->connectivity ().end_connected (*l);
|
||||
db::Connectivity::layer_iterator cb = l2n->connectivity ().begin_connected (*l);
|
||||
if (cb != ce) {
|
||||
*mp_stream << Keys::connect_key << "(" << name_for_layer (ly, *l);
|
||||
*mp_stream << Keys::connect_key << "(" << name_for_layer (l2n, *l);
|
||||
for (db::Connectivity::layer_iterator c = l2n->connectivity ().begin_connected (*l); c != ce; ++c) {
|
||||
*mp_stream << " " << name_for_layer (ly, *c);
|
||||
*mp_stream << " " << name_for_layer (l2n, *c);
|
||||
}
|
||||
*mp_stream << ")" << endl;
|
||||
}
|
||||
|
|
@ -136,7 +135,7 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n)
|
|||
}
|
||||
any = true;
|
||||
}
|
||||
*mp_stream << Keys::global_key << "(" << name_for_layer (ly, *l);
|
||||
*mp_stream << Keys::global_key << "(" << name_for_layer (l2n, *l);
|
||||
for (db::Connectivity::global_nets_iterator g = gb; g != ge; ++g) {
|
||||
*mp_stream << " " << tl::to_word_or_quoted_string (l2n->connectivity ().global_net_name (*g));
|
||||
}
|
||||
|
|
@ -260,7 +259,6 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n, const db::Net
|
|||
throw tl::Exception (tl::to_string (tr ("Can't write annotated netlist before extraction has been done")));
|
||||
}
|
||||
|
||||
const db::Layout *ly = l2n->internal_layout ();
|
||||
const db::hier_clusters<db::PolygonRef> &clusters = l2n->net_clusters ();
|
||||
const db::Circuit *circuit = net.circuit ();
|
||||
const db::Connectivity &conn = l2n->connectivity ();
|
||||
|
|
@ -290,7 +288,7 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n, const db::Net
|
|||
}
|
||||
|
||||
*mp_stream << indent2;
|
||||
write (si.operator-> (), si.trans (), name_for_layer (ly, *l));
|
||||
write (si.operator-> (), si.trans (), name_for_layer (l2n, *l));
|
||||
*mp_stream << endl;
|
||||
|
||||
prev_ci = ci;
|
||||
|
|
@ -365,7 +363,6 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n, const db::Dev
|
|||
{
|
||||
const std::vector<db::DeviceTerminalDefinition> &td = device_model.device_class ()->terminal_definitions ();
|
||||
|
||||
const db::Layout *ly = l2n->internal_layout ();
|
||||
const db::hier_clusters<db::PolygonRef> &clusters = l2n->net_clusters ();
|
||||
const db::Connectivity &conn = l2n->connectivity ();
|
||||
|
||||
|
|
@ -379,7 +376,7 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n, const db::Dev
|
|||
for (db::local_cluster<db::PolygonRef>::shape_iterator s = lc.begin (*l); ! s.at_end (); ++s) {
|
||||
|
||||
*mp_stream << indent2;
|
||||
write (s.operator-> (), db::ICplxTrans (), name_for_layer (ly, *l));
|
||||
write (s.operator-> (), db::ICplxTrans (), name_for_layer (l2n, *l));
|
||||
*mp_stream << endl;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,12 +502,36 @@ public:
|
|||
Region &operator= (const Region &other);
|
||||
|
||||
/**
|
||||
* @brief Constructor from an object
|
||||
*
|
||||
* Creates a region representing a single instance of that object
|
||||
* @brief Constructor from a box
|
||||
*/
|
||||
template <class Sh>
|
||||
Region (const Sh &s)
|
||||
explicit Region (const db::Box &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a polygon
|
||||
*/
|
||||
explicit Region (const db::Polygon &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a simple polygon
|
||||
*/
|
||||
explicit Region (const db::SimplePolygon &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a path
|
||||
*/
|
||||
explicit Region (const db::Path &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
|
|
@ -521,7 +545,7 @@ public:
|
|||
* style.
|
||||
*/
|
||||
template <class Iter>
|
||||
Region (const Iter &b, const Iter &e)
|
||||
explicit Region (const Iter &b, const Iter &e)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
reserve (e - b);
|
||||
|
|
@ -536,7 +560,7 @@ public:
|
|||
* Creates a region from a recursive shape iterator. This allows feeding a region
|
||||
* from a hierarchy of cells.
|
||||
*/
|
||||
Region (const RecursiveShapeIterator &si);
|
||||
explicit Region (const RecursiveShapeIterator &si);
|
||||
|
||||
/**
|
||||
* @brief Constructor from a RecursiveShapeIterator with a transformation
|
||||
|
|
@ -545,7 +569,7 @@ public:
|
|||
* from a hierarchy of cells. The transformation is useful to scale to a specific
|
||||
* DBU for example.
|
||||
*/
|
||||
Region (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics = true);
|
||||
explicit Region (const RecursiveShapeIterator &si, const db::ICplxTrans &trans, bool merged_semantics = true);
|
||||
|
||||
/**
|
||||
* @brief Constructor from a RecursiveShapeIterator providing a deep representation
|
||||
|
|
@ -556,12 +580,12 @@ public:
|
|||
* "area_ratio" and "max_vertex_count" are optimization parameters for the
|
||||
* shape splitting algorithm.
|
||||
*/
|
||||
Region (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio = 3.0, size_t max_vertex_count = 16);
|
||||
explicit Region (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio = 3.0, size_t max_vertex_count = 16);
|
||||
|
||||
/**
|
||||
* @brief Constructor from a RecursiveShapeIterator providing a deep representation with transformation
|
||||
*/
|
||||
Region (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics = true, double area_ratio = 3.0, size_t max_vertex_count = 16);
|
||||
explicit Region (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics = true, double area_ratio = 3.0, size_t max_vertex_count = 16);
|
||||
|
||||
/**
|
||||
* @brief Gets the underlying delegate object
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "gsiDecl.h"
|
||||
#include "dbLayoutToNetlist.h"
|
||||
#include "dbLayoutToNetlistWriter.h"
|
||||
#include "dbLayoutToNetlistReader.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
namespace gsi
|
||||
|
|
@ -33,6 +34,11 @@ static db::LayoutToNetlist *make_l2n (const db::RecursiveShapeIterator &iter)
|
|||
return new db::LayoutToNetlist (iter);
|
||||
}
|
||||
|
||||
static db::LayoutToNetlist *make_l2n_default ()
|
||||
{
|
||||
return new db::LayoutToNetlist ();
|
||||
}
|
||||
|
||||
static db::Layout *l2n_internal_layout (db::LayoutToNetlist *l2n)
|
||||
{
|
||||
// although this isn't very clean, we dare to do so as const references are pretty useless in script languages.
|
||||
|
|
@ -67,10 +73,31 @@ static void write_l2n (const db::LayoutToNetlist *l2n, const std::string &path,
|
|||
writer.write (l2n);
|
||||
}
|
||||
|
||||
static void read_l2n (db::LayoutToNetlist *l2n, const std::string &path)
|
||||
{
|
||||
tl::InputStream stream (path);
|
||||
db::LayoutToNetlistStandardReader reader (stream);
|
||||
reader.read (l2n);
|
||||
}
|
||||
|
||||
static std::vector<std::string> l2n_layer_names (const db::LayoutToNetlist *l2n)
|
||||
{
|
||||
std::vector<std::string> ln;
|
||||
for (db::LayoutToNetlist::layer_iterator l = l2n->begin_layers (); l != l2n->end_layers (); ++l) {
|
||||
ln.push_back (l->second);
|
||||
}
|
||||
return ln;
|
||||
}
|
||||
|
||||
Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
||||
gsi::constructor ("new", &make_l2n, gsi::arg ("iter"),
|
||||
"@brief The constructor\n"
|
||||
"See the class description for details.\n"
|
||||
"@brief Creates a new extractor connected to an original layout\n"
|
||||
"This constructor will attach the extractor to an original layout through the "
|
||||
"shape iterator.\n"
|
||||
) +
|
||||
gsi::constructor ("new", &make_l2n_default,
|
||||
"@brief Creates a new and empty extractor object\n"
|
||||
"The main objective for this constructor is to create an object suitable for reading an annotated netlist.\n"
|
||||
) +
|
||||
gsi::method ("threads=", &db::LayoutToNetlist::set_threads, gsi::arg ("n"),
|
||||
"@brief Sets the number of threads to use for operations which support multiple threads\n"
|
||||
|
|
@ -95,34 +122,65 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
|||
gsi::method ("max_vertex_count", &db::LayoutToNetlist::max_vertex_count,
|
||||
"See \\max_vertex_count= for details about this attribute."
|
||||
) +
|
||||
gsi::method ("name", &db::LayoutToNetlist::name, gsi::arg ("l"),
|
||||
gsi::method ("name", (std::string (db::LayoutToNetlist::*) (const db::Region ®ion) const) &db::LayoutToNetlist::name, gsi::arg ("l"),
|
||||
"@brief Get the name of the given layer\n"
|
||||
) +
|
||||
gsi::method ("name", (std::string (db::LayoutToNetlist::*) (unsigned int) const) &db::LayoutToNetlist::name, gsi::arg ("l"),
|
||||
"@brief Get the name of the given layer (by index)\n"
|
||||
) +
|
||||
gsi::method ("register", (void (db::LayoutToNetlist::*) (const db::Region ®ion, const std::string &)) &db::LayoutToNetlist::register_layer, gsi::arg ("l"), gsi::arg ("n"),
|
||||
"@brief Names the given layer\n"
|
||||
"'l' must be a hierarchical region 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"
|
||||
"\n"
|
||||
"Naming a layer allows the system to indicate the layer in various contexts, i.e. "
|
||||
"when writing the data to a file.\n"
|
||||
"when writing the data to a file. Named layers are also persisted inside the LayoutToNetlist object. "
|
||||
"They are not discarded when the Region object is destroyed. Only named layers can be put into "
|
||||
"\\connect.\n"
|
||||
) +
|
||||
gsi::method ("make_layer", &db::LayoutToNetlist::make_layer, gsi::arg ("layer_index"), gsi::arg ("name", std::string ()),
|
||||
gsi::method_ext ("layer_names", &l2n_layer_names,
|
||||
"@brief Returns a list of names of the layer kept inside the LayoutToNetlist object."
|
||||
) +
|
||||
gsi::factory ("layer_by_name", &db::LayoutToNetlist::layer_by_name, gsi::arg ("name"),
|
||||
"@brief Gets a layer object for the given name.\n"
|
||||
"The returned object is a copy which represents the named layer."
|
||||
) +
|
||||
gsi::factory ("layer_by_index", &db::LayoutToNetlist::layer_by_index, gsi::arg ("index"),
|
||||
"@brief Gets a layer object for the given index.\n"
|
||||
"Only named layers can be retrieved with this method. "
|
||||
"The returned object is a copy which represents the named layer."
|
||||
) +
|
||||
gsi::method ("is_persisted?", &db::LayoutToNetlist::is_persisted, gsi::arg ("layer"),
|
||||
"@brief Returns true, if the given layer is a persisted region.\n"
|
||||
"Persisted layers are kept inside the LayoutToNetlist object and are not released "
|
||||
"if their object is destroyed. Named layers are persisted, unnamed layers are not. "
|
||||
"Only persisted, named layers can be put into \\connect."
|
||||
) +
|
||||
gsi::factory ("make_layer", (db::Region *(db::LayoutToNetlist::*) (const std::string &)) &db::LayoutToNetlist::make_layer, gsi::arg ("name", std::string ()),
|
||||
"@brief Creates a new, empty hierarchical region\n"
|
||||
"\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\register).\n"
|
||||
) +
|
||||
gsi::factory ("make_layer", (db::Region *(db::LayoutToNetlist::*) (unsigned int, const std::string &)) &db::LayoutToNetlist::make_layer, gsi::arg ("layer_index"), gsi::arg ("name", std::string ()),
|
||||
"@brief Creates a new hierarchical region representing an original layer\n"
|
||||
"'layer_index' is the layer index of the desired layer in the original layout.\n"
|
||||
"This variant produces polygons and takes texts for net name annotation.\n"
|
||||
"A variant not taking texts is \\make_polygon_layer. A Variant only taking\n"
|
||||
"texts is \\make_text_layer.\n"
|
||||
"\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\name).\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\register).\n"
|
||||
) +
|
||||
gsi::method ("make_text_layer", &db::LayoutToNetlist::make_text_layer, gsi::arg ("layer_index"), gsi::arg ("name", std::string ()),
|
||||
gsi::factory ("make_text_layer", &db::LayoutToNetlist::make_text_layer, gsi::arg ("layer_index"), gsi::arg ("name", std::string ()),
|
||||
"@brief Creates a new region representing an original layer taking texts only\n"
|
||||
"See \\make_layer for details.\n"
|
||||
"\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\name).\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\register).\n"
|
||||
) +
|
||||
gsi::method ("make_polygon_layer", &db::LayoutToNetlist::make_polygon_layer, gsi::arg ("layer_index"), gsi::arg ("name", std::string ()),
|
||||
gsi::factory ("make_polygon_layer", &db::LayoutToNetlist::make_polygon_layer, gsi::arg ("layer_index"), gsi::arg ("name", std::string ()),
|
||||
"@brief Creates a new region representing an original layer taking polygons and texts\n"
|
||||
"See \\make_layer for details.\n"
|
||||
"\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\name).\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\register).\n"
|
||||
) +
|
||||
gsi::method ("extract_devices", &db::LayoutToNetlist::extract_devices, gsi::arg ("extractor"), gsi::arg ("layers"),
|
||||
"@brief Extracts devices\n"
|
||||
|
|
@ -280,6 +338,10 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
|||
gsi::method_ext ("write", &write_l2n, gsi::arg ("path"), gsi::arg ("short_format", false),
|
||||
"@brief Writes the extracted netlist to a file.\n"
|
||||
"This method employs the native format of KLayout.\n"
|
||||
) +
|
||||
gsi::method_ext ("read", &read_l2n, gsi::arg ("path"),
|
||||
"@brief Reads the extracted netlist from the file.\n"
|
||||
"This method employs the native format of KLayout.\n"
|
||||
),
|
||||
"@brief A generic framework for extracting netlists from layouts\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -59,6 +59,41 @@ TEST(1)
|
|||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/hierarchy_builder_au1.gds");
|
||||
}
|
||||
|
||||
TEST(1_WithEmptyLayer)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/algo/hierarchy_builder_l1.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
|
||||
db::Layout target;
|
||||
db::HierarchyBuilder builder (&target);
|
||||
|
||||
db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), std::set<unsigned int> ());
|
||||
iter.push (&builder);
|
||||
|
||||
for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) {
|
||||
|
||||
unsigned int li1 = (*li).first;
|
||||
unsigned int target_layer = target.insert_layer (*(*li).second);
|
||||
builder.set_target_layer (target_layer);
|
||||
|
||||
db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1);
|
||||
|
||||
iter.push (&builder);
|
||||
|
||||
}
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/hierarchy_builder_au1.gds");
|
||||
}
|
||||
|
||||
TEST(2_WithoutClip)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
@ -251,6 +286,56 @@ TEST(2_WithEmptyResult)
|
|||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/hierarchy_builder_au2e.gds");
|
||||
}
|
||||
|
||||
TEST(2_WithClipAndSimplificationAndEmptyLayer)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/algo/hierarchy_builder_l1.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::Layout target;
|
||||
db::ReducingHierarchyBuilderShapeReceiver red(0, 1.2, 4);
|
||||
db::ClippingHierarchyBuilderShapeReceiver clip(&red);
|
||||
db::HierarchyBuilder builder (&target, &clip);
|
||||
|
||||
db::cell_index_type target_top = target.add_cell ("CLIP_TOP");
|
||||
|
||||
db::Box clip_box (5000, -2000, 18500, 6000);
|
||||
|
||||
builder.set_target_layer (target.insert_layer (db::LayerProperties (100, 0)));
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), std::set<unsigned int> (), clip_box);
|
||||
|
||||
iter.push (&builder);
|
||||
|
||||
target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ()));
|
||||
|
||||
for (db::Layout::layer_iterator li = ly.begin_layers (); li != ly.end_layers (); ++li) {
|
||||
|
||||
builder.reset ();
|
||||
|
||||
unsigned int li1 = (*li).first;
|
||||
unsigned int target_layer = target.insert_layer (*(*li).second);
|
||||
builder.set_target_layer (target_layer);
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
db::RecursiveShapeIterator iter (ly, ly.cell (top_cell_index), li1, clip_box);
|
||||
|
||||
iter.push (&builder);
|
||||
|
||||
target.cell (target_top).insert (db::CellInstArray (db::CellInst (builder.initial_cell ()->cell_index ()), db::Trans ()));
|
||||
|
||||
}
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/hierarchy_builder_au2f.gds");
|
||||
}
|
||||
|
||||
TEST(3_ComplexRegionWithClip)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
|
|||
|
|
@ -34,10 +34,7 @@
|
|||
|
||||
TEST(1_ReaderBasic)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
db::Cell &tc = ly.cell (ly.add_cell ("TOP"));
|
||||
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
|
||||
db::LayoutToNetlist l2n;
|
||||
|
||||
std::string in_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au.txt");
|
||||
tl::InputStream is_in (in_path);
|
||||
|
|
@ -69,20 +66,20 @@ TEST(1_ReaderBasic)
|
|||
|
||||
{
|
||||
db::Layout ly2;
|
||||
ly2.dbu (ly.dbu ());
|
||||
ly2.dbu (l2n.internal_layout ()->dbu ());
|
||||
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
||||
|
||||
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
|
||||
|
||||
std::map<unsigned int, const db::Region *> lmap;
|
||||
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = reader.layer_by_name ("psd");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = reader.layer_by_name ("nsd");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = reader.layer_by_name ("poly");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = reader.layer_by_name ("diff_cont");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = reader.layer_by_name ("poly_cont");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = reader.layer_by_name ("metal1");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = reader.layer_by_name ("via1");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = reader.layer_by_name ("metal2");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_by_name ("psd");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_by_name ("nsd");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_by_name ("poly");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_by_name ("diff_cont");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_by_name ("poly_cont");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_by_name ("metal1");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_by_name ("via1");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_by_name ("metal2");
|
||||
|
||||
l2n.build_all_nets (cm, ly2, lmap, "NET_", 0, "DEVICE_");
|
||||
|
||||
|
|
@ -97,10 +94,7 @@ TEST(1_ReaderBasic)
|
|||
|
||||
TEST(1b_ReaderBasicShort)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
db::Cell &tc = ly.cell (ly.add_cell ("TOP"));
|
||||
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
|
||||
db::LayoutToNetlist l2n;
|
||||
|
||||
std::string in_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au_s.txt");
|
||||
tl::InputStream is_in (in_path);
|
||||
|
|
@ -132,10 +126,7 @@ TEST(1b_ReaderBasicShort)
|
|||
|
||||
TEST(2_ReaderWithGlobalNets)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
db::Cell &tc = ly.cell (ly.add_cell ("TOP"));
|
||||
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
|
||||
db::LayoutToNetlist l2n;
|
||||
|
||||
std::string in_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au_2.txt");
|
||||
tl::InputStream is_in (in_path);
|
||||
|
|
@ -167,24 +158,24 @@ TEST(2_ReaderWithGlobalNets)
|
|||
|
||||
{
|
||||
db::Layout ly2;
|
||||
ly2.dbu (ly.dbu ());
|
||||
ly2.dbu (l2n.internal_layout ()->dbu ());
|
||||
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
||||
|
||||
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
|
||||
|
||||
std::map<unsigned int, const db::Region *> lmap;
|
||||
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = reader.layer_by_name ("psd");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = reader.layer_by_name ("nsd");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (12, 0))] = reader.layer_by_name ("rbulk");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (13, 0))] = reader.layer_by_name ("ptie");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (14, 0))] = reader.layer_by_name ("ntie");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (1, 0)) ] = reader.layer_by_name ("nwell");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = reader.layer_by_name ("poly");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = reader.layer_by_name ("diff_cont");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = reader.layer_by_name ("poly_cont");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = reader.layer_by_name ("metal1");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = reader.layer_by_name ("via1");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = reader.layer_by_name ("metal2");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_by_name ("psd");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_by_name ("nsd");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (12, 0))] = l2n.layer_by_name ("rbulk");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (13, 0))] = l2n.layer_by_name ("ptie");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (14, 0))] = l2n.layer_by_name ("ntie");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (1, 0)) ] = l2n.layer_by_name ("nwell");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_by_name ("poly");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_by_name ("diff_cont");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_by_name ("poly_cont");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_by_name ("metal1");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_by_name ("via1");
|
||||
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_by_name ("metal2");
|
||||
|
||||
l2n.build_all_nets (cm, ly2, lmap, "NET_", "CIRCUIT_", "DEVICE_");
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,52 @@ static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_la
|
|||
return lid;
|
||||
}
|
||||
|
||||
TEST(1_Basic)
|
||||
TEST(0_Basic)
|
||||
{
|
||||
db::LayoutToNetlist l2n;
|
||||
|
||||
std::auto_ptr<db::Region> reg (l2n.make_layer ("l1"));
|
||||
EXPECT_EQ (l2n.is_persisted (*reg), true);
|
||||
EXPECT_EQ (l2n.name (*reg), "l1");
|
||||
EXPECT_EQ (l2n.layer_of (*reg), 0u);
|
||||
EXPECT_EQ (l2n.internal_layout ()->is_valid_layer (0), true);
|
||||
reg.reset (0);
|
||||
EXPECT_EQ (l2n.internal_layout ()->is_valid_layer (0), true);
|
||||
EXPECT_EQ (l2n.name (0u), "l1");
|
||||
|
||||
EXPECT_EQ (l2n.layer_by_index (1) == 0, true);
|
||||
EXPECT_EQ (l2n.layer_by_name ("l2") == 0, true);
|
||||
|
||||
std::auto_ptr<db::Region> reg_copy (l2n.layer_by_name ("l1"));
|
||||
EXPECT_EQ (reg_copy.get () != 0, true);
|
||||
EXPECT_EQ (l2n.name (*reg_copy), "l1");
|
||||
EXPECT_EQ (l2n.layer_of (*reg_copy), 0u);
|
||||
reg_copy.reset (l2n.layer_by_index (0));
|
||||
EXPECT_EQ (reg_copy.get () != 0, true);
|
||||
EXPECT_EQ (l2n.name (*reg_copy), "l1");
|
||||
EXPECT_EQ (l2n.layer_of (*reg_copy), 0u);
|
||||
reg_copy.reset (0);
|
||||
|
||||
std::auto_ptr<db::Region> reg2 (l2n.make_layer ());
|
||||
EXPECT_EQ (l2n.name (1u), "");
|
||||
EXPECT_EQ (l2n.name (*reg2), "");
|
||||
EXPECT_EQ (l2n.layer_of (*reg2), 1u);
|
||||
EXPECT_EQ (l2n.internal_layout ()->is_valid_layer (1), true);
|
||||
reg2.reset (0);
|
||||
EXPECT_EQ (l2n.internal_layout ()->is_valid_layer (1), false);
|
||||
|
||||
std::auto_ptr<db::Region> reg3 (l2n.make_layer ("l3"));
|
||||
EXPECT_EQ (l2n.name (*reg3), "l3");
|
||||
EXPECT_EQ (l2n.layer_of (*reg3), 1u);
|
||||
|
||||
std::string s;
|
||||
for (db::LayoutToNetlist::layer_iterator l = l2n.begin_layers (); l != l2n.end_layers (); ++l) {
|
||||
s += tl::to_string (l->first) + ":" + l->second + ";";
|
||||
}
|
||||
EXPECT_EQ (s, "0:l1;1:l3;");
|
||||
}
|
||||
|
||||
TEST(1_BasicExtraction)
|
||||
{
|
||||
db::Layout ly;
|
||||
db::LayerMap lmap;
|
||||
|
|
@ -157,17 +202,17 @@ TEST(1_Basic)
|
|||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
|
||||
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl));
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell, "nwell"));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active, "active"));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly, "poly"));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl, "poly_lbl"));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont, "diff_cont"));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont, "poly_cont"));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1, "metal1"));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl, "metal1_lbl"));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1, "via1"));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2, "metal2"));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl, "metal2_lbl"));
|
||||
|
||||
// derived regions
|
||||
|
||||
|
|
@ -215,6 +260,9 @@ TEST(1_Basic)
|
|||
|
||||
// net extraction
|
||||
|
||||
l2n.register_layer (rpsd, "psd");
|
||||
l2n.register_layer (rnsd, "nsd");
|
||||
|
||||
// Intra-layer
|
||||
l2n.connect (rpsd);
|
||||
l2n.connect (rnsd);
|
||||
|
|
@ -513,17 +561,17 @@ TEST(2_Probing)
|
|||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
|
||||
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl));
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell, "nwell"));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active, "active"));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly, "poly"));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl, "poly_lbl"));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont, "diff_cont"));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont, "poly_cont"));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1, "metal1"));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl, "metal1_lbl"));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1, "via1"));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2, "metal2"));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl, "metal2_lbl"));
|
||||
|
||||
// derived regions
|
||||
|
||||
|
|
@ -568,6 +616,9 @@ TEST(2_Probing)
|
|||
|
||||
// net extraction
|
||||
|
||||
l2n.register_layer (rpsd, "psd");
|
||||
l2n.register_layer (rnsd, "nsd");
|
||||
|
||||
// Intra-layer
|
||||
l2n.connect (rpsd);
|
||||
l2n.connect (rnsd);
|
||||
|
|
@ -754,19 +805,19 @@ TEST(3_GlobalNetConnections)
|
|||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
|
||||
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active));
|
||||
std::auto_ptr<db::Region> rpplus (l2n.make_layer (pplus));
|
||||
std::auto_ptr<db::Region> rnplus (l2n.make_layer (nplus));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl));
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell, "nwell"));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active, "active"));
|
||||
std::auto_ptr<db::Region> rpplus (l2n.make_layer (pplus, "pplus"));
|
||||
std::auto_ptr<db::Region> rnplus (l2n.make_layer (nplus, "nplus"));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly, "poly"));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl, "poly_lbl"));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont, "diff_cont"));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont, "poly_cont"));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1, "metal1"));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl, "metal1_lbl"));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1, "via1"));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2, "metal2"));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl, "metal2_lbl"));
|
||||
|
||||
// derived regions
|
||||
|
||||
|
|
@ -819,6 +870,11 @@ TEST(3_GlobalNetConnections)
|
|||
|
||||
// net extraction
|
||||
|
||||
l2n.register_layer (rpsd, "psd");
|
||||
l2n.register_layer (rnsd, "nsd");
|
||||
l2n.register_layer (rptie, "ptie");
|
||||
l2n.register_layer (rntie, "ntie");
|
||||
|
||||
// Intra-layer
|
||||
l2n.connect (rpsd);
|
||||
l2n.connect (rnsd);
|
||||
|
|
@ -1021,20 +1077,20 @@ TEST(4_GlobalNetDeviceExtraction)
|
|||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
|
||||
|
||||
std::auto_ptr<db::Region> rbulk (l2n.make_layer (ly.insert_layer ()));
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active));
|
||||
std::auto_ptr<db::Region> rpplus (l2n.make_layer (pplus));
|
||||
std::auto_ptr<db::Region> rnplus (l2n.make_layer (nplus));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl));
|
||||
std::auto_ptr<db::Region> rbulk (l2n.make_layer (ly.insert_layer (), "bulk"));
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell, "nwell"));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active, "active"));
|
||||
std::auto_ptr<db::Region> rpplus (l2n.make_layer (pplus, "pplus"));
|
||||
std::auto_ptr<db::Region> rnplus (l2n.make_layer (nplus, "nplus"));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly, "poly"));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl, "poly_lbl"));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont, "diff_cont"));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont, "poly_cont"));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1, "metal1"));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl, "metal1_lbl"));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1, "via1"));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2, "metal2"));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl, "metal2_lbl"));
|
||||
|
||||
// derived regions
|
||||
|
||||
|
|
@ -1089,6 +1145,11 @@ TEST(4_GlobalNetDeviceExtraction)
|
|||
|
||||
// net extraction
|
||||
|
||||
l2n.register_layer (rpsd, "psd");
|
||||
l2n.register_layer (rnsd, "nsd");
|
||||
l2n.register_layer (rptie, "ptie");
|
||||
l2n.register_layer (rntie, "ntie");
|
||||
|
||||
// Intra-layer
|
||||
l2n.connect (rpsd);
|
||||
l2n.connect (rnsd);
|
||||
|
|
@ -1294,20 +1355,20 @@ TEST(5_DeviceExtractionWithDeviceCombination)
|
|||
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
||||
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
|
||||
|
||||
std::auto_ptr<db::Region> rbulk (l2n.make_layer (ly.insert_layer ()));
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active));
|
||||
std::auto_ptr<db::Region> rpplus (l2n.make_layer (pplus));
|
||||
std::auto_ptr<db::Region> rnplus (l2n.make_layer (nplus));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl));
|
||||
std::auto_ptr<db::Region> rbulk (l2n.make_layer ("bulk"));
|
||||
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell, "nwell"));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active, "active"));
|
||||
std::auto_ptr<db::Region> rpplus (l2n.make_layer (pplus, "pplus"));
|
||||
std::auto_ptr<db::Region> rnplus (l2n.make_layer (nplus, "nplus"));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly, "poly"));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl, "poly_lbl"));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont, "diff_cont"));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont, "poly_cont"));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1, "metal1"));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl, "metal1_lbl"));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1, "via1"));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2, "metal2"));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl, "metal2_lbl"));
|
||||
|
||||
// derived regions
|
||||
|
||||
|
|
@ -1362,6 +1423,11 @@ TEST(5_DeviceExtractionWithDeviceCombination)
|
|||
|
||||
// net extraction
|
||||
|
||||
l2n.register_layer (rpsd, "psd");
|
||||
l2n.register_layer (rnsd, "nsd");
|
||||
l2n.register_layer (rptie, "ptie");
|
||||
l2n.register_layer (rntie, "ntie");
|
||||
|
||||
// Intra-layer
|
||||
l2n.connect (rpsd);
|
||||
l2n.connect (rnsd);
|
||||
|
|
|
|||
|
|
@ -90,16 +90,16 @@ TEST(1_WriterBasic)
|
|||
db::Region rpactive = *ractive & *rnwell;
|
||||
db::Region rpgate = rpactive & *rpoly;
|
||||
db::Region rpsd = rpactive - rpgate;
|
||||
l2n.name (rpactive, "pactive");
|
||||
l2n.name (rpgate, "pgate");
|
||||
l2n.name (rpsd, "psd");
|
||||
l2n.register_layer (rpactive, "pactive");
|
||||
l2n.register_layer (rpgate, "pgate");
|
||||
l2n.register_layer (rpsd, "psd");
|
||||
|
||||
db::Region rnactive = *ractive - *rnwell;
|
||||
db::Region rngate = rnactive & *rpoly;
|
||||
db::Region rnsd = rnactive - rngate;
|
||||
l2n.name (rnactive, "nactive");
|
||||
l2n.name (rngate, "ngate");
|
||||
l2n.name (rnsd, "nsd");
|
||||
l2n.register_layer (rnactive, "nactive");
|
||||
l2n.register_layer (rngate, "ngate");
|
||||
l2n.register_layer (rnsd, "nsd");
|
||||
|
||||
db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS");
|
||||
db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS");
|
||||
|
|
@ -296,20 +296,20 @@ TEST(2_WriterWithGlobalNets)
|
|||
db::Region rntie = ractive_in_nwell & *rnplus;
|
||||
db::Region rpgate = rpactive & *rpoly;
|
||||
db::Region rpsd = rpactive - rpgate;
|
||||
l2n.name (rpactive, "pactive");
|
||||
l2n.name (rntie, "ntie");
|
||||
l2n.name (rpgate, "pgate");
|
||||
l2n.name (rpsd, "psd");
|
||||
l2n.register_layer (rpactive, "pactive");
|
||||
l2n.register_layer (rntie, "ntie");
|
||||
l2n.register_layer (rpgate, "pgate");
|
||||
l2n.register_layer (rpsd, "psd");
|
||||
|
||||
db::Region ractive_outside_nwell = *ractive - *rnwell;
|
||||
db::Region rnactive = ractive_outside_nwell & *rnplus;
|
||||
db::Region rptie = ractive_outside_nwell & *rpplus;
|
||||
db::Region rngate = rnactive & *rpoly;
|
||||
db::Region rnsd = rnactive - rngate;
|
||||
l2n.name (rnactive, "nactive");
|
||||
l2n.name (rptie, "ptie");
|
||||
l2n.name (rngate, "ngate");
|
||||
l2n.name (rnsd, "nsd");
|
||||
l2n.register_layer (rnactive, "nactive");
|
||||
l2n.register_layer (rptie, "ptie");
|
||||
l2n.register_layer (rngate, "ngate");
|
||||
l2n.register_layer (rnsd, "nsd");
|
||||
|
||||
// return the computed layers into the original layout and write it for debugging purposes
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -61,7 +61,7 @@ class DBLayoutToNetlist_TestClass < TestBase
|
|||
assert_equal(l2n.internal_layout.cell(ci).name, ly2.cell(cm.cell_mapping(ci)).name)
|
||||
end
|
||||
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0) )
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0), "metal1" )
|
||||
bulk_id = l2n.connect_global(rmetal1, "BULK")
|
||||
assert_equal(l2n.global_net_name(bulk_id), "BULK")
|
||||
|
||||
|
|
@ -76,11 +76,11 @@ class DBLayoutToNetlist_TestClass < TestBase
|
|||
|
||||
# only plain backend connectivity
|
||||
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0) )
|
||||
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1) )
|
||||
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0) )
|
||||
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0) )
|
||||
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1) )
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0), "metal1" )
|
||||
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1), "metal1_lbl" )
|
||||
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0), "via1" )
|
||||
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0), "metal2" )
|
||||
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1), "metal2_lbl" )
|
||||
|
||||
# Intra-layer
|
||||
l2n.connect(rmetal1)
|
||||
|
|
@ -141,19 +141,21 @@ END
|
|||
|
||||
# only plain connectivity
|
||||
|
||||
ractive = l2n.make_layer( ly.layer(2, 0) )
|
||||
rpoly = l2n.make_polygon_layer( ly.layer(3, 0) )
|
||||
rpoly_lbl = l2n.make_text_layer( ly.layer(3, 1) )
|
||||
rdiff_cont = l2n.make_polygon_layer( ly.layer(4, 0) )
|
||||
rpoly_cont = l2n.make_polygon_layer( ly.layer(5, 0) )
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0) )
|
||||
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1) )
|
||||
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0) )
|
||||
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0) )
|
||||
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1) )
|
||||
ractive = l2n.make_layer( ly.layer(2, 0), "active" )
|
||||
rpoly = l2n.make_polygon_layer( ly.layer(3, 0), "poly" )
|
||||
rpoly_lbl = l2n.make_text_layer( ly.layer(3, 1), "poly_lbl" )
|
||||
rdiff_cont = l2n.make_polygon_layer( ly.layer(4, 0), "diff_cont" )
|
||||
rpoly_cont = l2n.make_polygon_layer( ly.layer(5, 0), "poly_cont" )
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0), "metal1" )
|
||||
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1), "metal1_lbl" )
|
||||
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0), "via1" )
|
||||
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0), "metal2" )
|
||||
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1), "metal2_lbl" )
|
||||
|
||||
rsd = ractive - rpoly
|
||||
|
||||
l2n.register(rsd, "sd")
|
||||
|
||||
# Intra-layer
|
||||
l2n.connect(rsd)
|
||||
l2n.connect(rpoly)
|
||||
|
|
@ -206,17 +208,17 @@ END
|
|||
|
||||
l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, []))
|
||||
|
||||
rnwell = l2n.make_layer( ly.layer(1, 0) )
|
||||
ractive = l2n.make_layer( ly.layer(2, 0) )
|
||||
rpoly = l2n.make_polygon_layer( ly.layer(3, 0) )
|
||||
rpoly_lbl = l2n.make_text_layer( ly.layer(3, 1) )
|
||||
rdiff_cont = l2n.make_polygon_layer( ly.layer(4, 0) )
|
||||
rpoly_cont = l2n.make_polygon_layer( ly.layer(5, 0) )
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0) )
|
||||
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1) )
|
||||
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0) )
|
||||
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0) )
|
||||
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1) )
|
||||
rnwell = l2n.make_layer( ly.layer(1, 0), "nwell" )
|
||||
ractive = l2n.make_layer( ly.layer(2, 0), "active" )
|
||||
rpoly = l2n.make_polygon_layer( ly.layer(3, 0), "poly" )
|
||||
rpoly_lbl = l2n.make_text_layer( ly.layer(3, 1), "poly_lbl" )
|
||||
rdiff_cont = l2n.make_polygon_layer( ly.layer(4, 0), "diff_cont" )
|
||||
rpoly_cont = l2n.make_polygon_layer( ly.layer(5, 0), "poly_cont" )
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0), "metal1" )
|
||||
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1), "metal1_lbl" )
|
||||
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0), "via1" )
|
||||
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0), "metal2" )
|
||||
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1), "metal2_lbl" )
|
||||
|
||||
rpactive = ractive & rnwell
|
||||
rpgate = rpactive & rpoly
|
||||
|
|
@ -236,6 +238,9 @@ END
|
|||
|
||||
# Define connectivity for netlist extraction
|
||||
|
||||
l2n.register(rpsd, "psd")
|
||||
l2n.register(rnsd, "nsd")
|
||||
|
||||
# Intra-layer
|
||||
l2n.connect(rpsd)
|
||||
l2n.connect(rnsd)
|
||||
|
|
@ -297,20 +302,20 @@ END
|
|||
|
||||
l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, []))
|
||||
|
||||
rbulk = l2n.make_polygon_layer( ly.layer )
|
||||
rnwell = l2n.make_polygon_layer( ly.layer(1, 0) )
|
||||
ractive = l2n.make_polygon_layer( ly.layer(2, 0) )
|
||||
rpoly = l2n.make_polygon_layer( ly.layer(3, 0) )
|
||||
rpoly_lbl = l2n.make_text_layer( ly.layer(3, 1) )
|
||||
rdiff_cont = l2n.make_polygon_layer( ly.layer(4, 0) )
|
||||
rpoly_cont = l2n.make_polygon_layer( ly.layer(5, 0) )
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0) )
|
||||
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1) )
|
||||
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0) )
|
||||
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0) )
|
||||
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1) )
|
||||
rpplus = l2n.make_polygon_layer( ly.layer(10, 0) )
|
||||
rnplus = l2n.make_polygon_layer( ly.layer(11, 0) )
|
||||
rbulk = l2n.make_layer( "bulk" )
|
||||
rnwell = l2n.make_polygon_layer( ly.layer(1, 0) , "nwell" )
|
||||
ractive = l2n.make_polygon_layer( ly.layer(2, 0) , "active" )
|
||||
rpoly = l2n.make_polygon_layer( ly.layer(3, 0) , "poly" )
|
||||
rpoly_lbl = l2n.make_text_layer( ly.layer(3, 1) , "poly_lbl" )
|
||||
rdiff_cont = l2n.make_polygon_layer( ly.layer(4, 0) , "diff_cont" )
|
||||
rpoly_cont = l2n.make_polygon_layer( ly.layer(5, 0) , "poly_cont" )
|
||||
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0) , "metal1" )
|
||||
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1) , "metal1_lbl" )
|
||||
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0) , "via1" )
|
||||
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0) , "metal2" )
|
||||
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1) , "metal2_lbl" )
|
||||
rpplus = l2n.make_polygon_layer( ly.layer(10, 0) , "pplus" )
|
||||
rnplus = l2n.make_polygon_layer( ly.layer(11, 0) , "nplus" )
|
||||
|
||||
ractive_in_nwell = ractive & rnwell
|
||||
rpactive = ractive_in_nwell & rpplus
|
||||
|
|
@ -334,6 +339,11 @@ END
|
|||
|
||||
# Define connectivity for netlist extraction
|
||||
|
||||
l2n.register(rpsd, "psd")
|
||||
l2n.register(rnsd, "nsd")
|
||||
l2n.register(rptie, "ptie")
|
||||
l2n.register(rntie, "ntie")
|
||||
|
||||
# Intra-layer
|
||||
l2n.connect(rpsd)
|
||||
l2n.connect(rnsd)
|
||||
|
|
@ -417,6 +427,24 @@ END
|
|||
|
||||
end
|
||||
|
||||
def test_13_ReadAndWrite
|
||||
|
||||
l2n = RBA::LayoutToNetlist::new
|
||||
|
||||
input = File.join($ut_testsrc, "testdata", "algo", "l2n_writer_au.txt")
|
||||
l2n.read(input)
|
||||
|
||||
tmp = File::join($ut_testtmp, "tmp.txt")
|
||||
l2n.write(tmp)
|
||||
|
||||
assert_equal(File.open(tmp, "r").read, File.open(input, "r").read)
|
||||
|
||||
assert_equal(l2n.layer_names.join(","), "poly,poly_lbl,diff_cont,poly_cont,metal1,metal1_lbl,via1,metal2,metal2_lbl,psd,nsd")
|
||||
assert_equal(l2n.name(l2n.layer_by_name("metal1")), "metal1")
|
||||
assert_equal(l2n.name(l2n.layer_by_index(l2n.layer_of(l2n.layer_by_name("metal1")))), "metal1")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue