Merge pull request #385 from KLayout/dvb

Dvb
This commit is contained in:
Matthias Köfferlein 2019-11-06 01:00:33 +01:00 committed by GitHub
commit a351bc8085
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
91 changed files with 9922 additions and 1030 deletions

View File

@ -527,7 +527,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
db::BoolAndOrNotLocalOperation op (and_op);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), m_deep_layer.breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (m_deep_layer.store ()->threads ());
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
@ -1501,7 +1501,9 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&polygons.layout ()),
const_cast<db::Cell *> (&polygons.initial_cell ()),
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&polygons.layout ()),
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&polygons.initial_cell ()));
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&polygons.initial_cell ()),
m_deep_layer.breakout_cells (),
other_deep ? other_deep->deep_layer ().breakout_cells () : 0);
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
@ -1892,7 +1894,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
db::InteractingLocalOperation op (mode, touching, inverse);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
@ -1929,7 +1931,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) cons
db::InteractingWithEdgeLocalOperation op (inverse);
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
@ -1968,7 +1970,7 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
db::PullLocalOperation op (mode, touching);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
@ -2004,7 +2006,7 @@ DeepRegion::pull_generic (const Edges &other) const
db::PullWithEdgeLocalOperation op;
db::local_processor<db::PolygonRef, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell ());
db::local_processor<db::PolygonRef, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell (), polygons.breakout_cells (), other_edges.breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
proc.run (&op, polygons.layer (), other_edges.layer (), dl_out.layer ());

View File

@ -81,7 +81,6 @@ DeepLayer &DeepLayer::operator= (const DeepLayer &other)
return *this;
}
DeepLayer::~DeepLayer ()
{
if (mp_store.get ()) {
@ -139,6 +138,12 @@ DeepLayer::add_from (const DeepLayer &dl)
}
}
const std::set<db::cell_index_type> *
DeepLayer::breakout_cells () const
{
return store ()->breakout_cells (layout_index ());
}
void
DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
@ -251,16 +256,114 @@ struct DeepShapeStore::LayoutHolder
// ----------------------------------------------------------------------------------
DeepShapeStoreState::DeepShapeStoreState ()
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_text_property_name (), m_text_enlargement (-1)
{
// .. nothing yet ..
}
void DeepShapeStoreState::set_text_enlargement (int enl)
{
m_text_enlargement = enl;
}
int DeepShapeStoreState::text_enlargement () const
{
return m_text_enlargement;
}
void DeepShapeStoreState::set_text_property_name (const tl::Variant &pn)
{
m_text_property_name = pn;
}
const tl::Variant &
DeepShapeStoreState::text_property_name () const
{
return m_text_property_name;
}
const std::set<db::cell_index_type> *
DeepShapeStoreState::breakout_cells (unsigned int layout_index) const
{
const std::set<db::cell_index_type> &boc = (const_cast<DeepShapeStoreState *> (this))->ensure_breakout_cells (layout_index);
if (boc.empty ()) {
return 0;
} else {
return &boc;
}
}
void
DeepShapeStoreState::clear_breakout_cells (unsigned int layout_index)
{
ensure_breakout_cells (layout_index).clear ();
}
void
DeepShapeStoreState::set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc)
{
ensure_breakout_cells (layout_index) = boc;
}
void
DeepShapeStoreState::add_breakout_cell (unsigned int layout_index, db::cell_index_type ci)
{
ensure_breakout_cells (layout_index).insert (ci);
}
void
DeepShapeStoreState::add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc)
{
ensure_breakout_cells (layout_index).insert (cc.begin (), cc.end ());
}
void
DeepShapeStoreState::set_threads (int n)
{
m_threads = n;
}
int
DeepShapeStoreState::threads () const
{
return m_threads;
}
void
DeepShapeStoreState::set_max_area_ratio (double ar)
{
m_max_area_ratio = ar;
}
double
DeepShapeStoreState::max_area_ratio () const
{
return m_max_area_ratio;
}
void
DeepShapeStoreState::set_max_vertex_count (size_t n)
{
m_max_vertex_count = n;
}
size_t
DeepShapeStoreState::max_vertex_count () const
{
return m_max_vertex_count;
}
// ----------------------------------------------------------------------------------
static size_t s_instance_count = 0;
DeepShapeStore::DeepShapeStore ()
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_text_property_name (), m_text_enlargement (-1)
{
++s_instance_count;
}
DeepShapeStore::DeepShapeStore (const std::string &topcell_name, double dbu)
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_text_property_name (), m_text_enlargement (-1)
{
++s_instance_count;
@ -292,17 +395,17 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Region &region, bool for_n
unsigned int layer = layout ().insert_layer ();
if (max_area_ratio == 0.0) {
max_area_ratio = m_max_area_ratio;
max_area_ratio = m_state.max_area_ratio ();
}
if (max_vertex_count == 0) {
max_vertex_count = m_max_vertex_count;
max_vertex_count = m_state.max_vertex_count ();
}
db::Shapes *shapes = &initial_cell ().shapes (layer);
db::Box world = db::Box::world ();
// The chain of operators for producing clipped and reduced polygon references
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout (), m_text_enlargement, m_text_property_name);
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout (), text_enlargement (), text_property_name ());
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count);
// try to maintain the texts on top level - go through shape iterator
@ -399,12 +502,95 @@ const db::Cell &DeepShapeStore::const_initial_cell (unsigned int n) const
void DeepShapeStore::set_text_enlargement (int enl)
{
m_text_enlargement = enl;
m_state.set_text_enlargement (enl);
}
int DeepShapeStore::text_enlargement () const
{
return m_state.text_enlargement ();
}
void DeepShapeStore::set_text_property_name (const tl::Variant &pn)
{
m_text_property_name = pn;
m_state.set_text_property_name (pn);
}
const tl::Variant &DeepShapeStore::text_property_name () const
{
return m_state.text_property_name ();
}
const std::set<db::cell_index_type> *
DeepShapeStore::breakout_cells (unsigned int layout_index) const
{
return m_state.breakout_cells (layout_index);
}
void
DeepShapeStore::clear_breakout_cells (unsigned int layout_index)
{
m_state.clear_breakout_cells (layout_index);
}
void
DeepShapeStore::set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc)
{
m_state.set_breakout_cells (layout_index, boc);
}
void
DeepShapeStore::add_breakout_cell (unsigned int layout_index, db::cell_index_type ci)
{
m_state.add_breakout_cell (layout_index, ci);
}
void
DeepShapeStore::add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc)
{
m_state.add_breakout_cells (layout_index, cc);
}
void DeepShapeStore::set_threads (int n)
{
m_state.set_threads (n);
}
int DeepShapeStore::threads () const
{
return m_state.threads ();
}
void DeepShapeStore::set_max_area_ratio (double ar)
{
m_state.set_max_area_ratio (ar);
}
double DeepShapeStore::max_area_ratio () const
{
return m_state.max_area_ratio ();
}
void DeepShapeStore::set_max_vertex_count (size_t n)
{
m_state.set_max_vertex_count (n);
}
size_t DeepShapeStore::max_vertex_count () const
{
return m_state.max_vertex_count ();
}
void DeepShapeStore::push_state ()
{
m_state_stack.push_back (m_state);
}
void DeepShapeStore::pop_state ()
{
if (! m_state_stack.empty ()) {
m_state = m_state_stack.back ();
m_state_stack.pop_back ();
}
}
bool DeepShapeStore::is_valid_layout_index (unsigned int n) const
@ -429,21 +615,6 @@ size_t DeepShapeStore::instance_count ()
return s_instance_count;
}
void DeepShapeStore::set_threads (int n)
{
m_threads = n;
}
void DeepShapeStore::set_max_area_ratio (double ar)
{
m_max_area_ratio = ar;
}
void DeepShapeStore::set_max_vertex_count (size_t n)
{
m_max_vertex_count = n;
}
void DeepShapeStore::add_ref (unsigned int layout, unsigned int layer)
{
tl::MutexLocker locker (&m_lock);
@ -474,6 +645,7 @@ void DeepShapeStore::remove_ref (unsigned int layout, unsigned int layer)
if ((m_layouts[layout]->refs -= 1) <= 0) {
delete m_layouts[layout];
m_layouts[layout] = 0;
clear_breakout_cells (layout);
}
}
@ -542,10 +714,10 @@ static unsigned int init_layer (db::Layout &layout, const db::RecursiveShapeIter
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count, const db::ICplxTrans &trans)
{
if (max_area_ratio == 0.0) {
max_area_ratio = m_max_area_ratio;
max_area_ratio = m_state.max_area_ratio ();
}
if (max_vertex_count == 0) {
max_vertex_count = m_max_vertex_count;
max_vertex_count = m_state.max_vertex_count ();
}
unsigned int layout_index = layout_for_iter (si, trans);
@ -557,7 +729,7 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
builder.set_target_layer (layer_index);
// The chain of operators for producing clipped and reduced polygon references
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (& layout, m_text_enlargement, m_text_property_name);
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (& layout, text_enlargement (), text_property_name ());
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count);
db::ClippingHierarchyBuilderShapeReceiver clip (&red);

View File

@ -40,6 +40,7 @@
namespace db {
class DeepShapeStore;
class DeepShapeStoreState;
class Region;
class Edges;
@ -132,6 +133,13 @@ public:
return m_layout;
}
/**
* @brief Gets the list of breakout cells if there are some
* "breakout cells" are cells which are not considered to participate in hierarchical operations,
* neither as sibling nor in parent-child relationships.
*/
const std::set<db::cell_index_type> *breakout_cells () const;
/**
* @brief Inserts the layer into the given layout, starting from the given cell and into the given layer
*/
@ -200,6 +208,52 @@ private:
unsigned int m_layer;
};
/**
* @brief An object holding the state of a DeepShapeStore
*/
class DB_PUBLIC DeepShapeStoreState
{
public:
DeepShapeStoreState ();
void set_threads (int n);
int threads () const;
void set_max_vertex_count (size_t n);
size_t max_vertex_count () const;
void set_max_area_ratio (double ar);
double max_area_ratio () const;
void set_text_property_name (const tl::Variant &pn);
const tl::Variant &text_property_name () const;
void set_text_enlargement (int enl);
int text_enlargement () const;
const std::set<db::cell_index_type> *breakout_cells (unsigned int layout_index) const;
void clear_breakout_cells (unsigned int layout_index);
void set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc);
void add_breakout_cell (unsigned int layout_index, db::cell_index_type ci);
void add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc);
private:
int m_threads;
double m_max_area_ratio;
size_t m_max_vertex_count;
tl::Variant m_text_property_name;
std::vector<std::set<db::cell_index_type> > m_breakout_cells;
int m_text_enlargement;
std::set<db::cell_index_type> &ensure_breakout_cells (unsigned int layout_index)
{
if (m_breakout_cells.size () <= size_t (layout_index)) {
m_breakout_cells.resize (layout_index + 1, std::set<db::cell_index_type> ());
}
return m_breakout_cells [layout_index];
}
};
struct DB_PUBLIC RecursiveShapeIteratorCompareForTargetHierarchy
{
bool operator () (const std::pair<db::RecursiveShapeIterator, db::ICplxTrans> &a, const std::pair<db::RecursiveShapeIterator, db::ICplxTrans> &b) const
@ -514,10 +568,7 @@ public:
/**
* @brief Gets the number of threads
*/
int threads () const
{
return m_threads;
}
int threads () const;
/**
* @brief Sets the maximum vertex count default value
@ -531,10 +582,7 @@ public:
/**
* @brief Gets the maximum vertex count
*/
size_t max_vertex_count () const
{
return m_max_vertex_count;
}
size_t max_vertex_count () const;
/**
* @brief Sets the max. area ratio for bounding box vs. polygon area
@ -548,10 +596,7 @@ public:
/**
* @brief Gets the max. area ratio
*/
double max_area_ratio () const
{
return m_max_area_ratio;
}
double max_area_ratio () const;
/**
* @brief Sets the text property name
@ -566,10 +611,7 @@ public:
/**
* @brief Gets the text property name
*/
const tl::Variant &text_property_name () const
{
return m_text_property_name;
}
const tl::Variant &text_property_name () const;
/**
* @brief Sets the text enlargement value
@ -584,10 +626,45 @@ public:
/**
* @brief Gets the text enlargement value
*/
int text_enlargement () const
{
return m_text_enlargement;
}
int text_enlargement () const;
/**
* @brief Gets the breakout cells for a given layout
* Returns 0 if there are no breakout cells for this layout.
*/
const std::set<db::cell_index_type> *breakout_cells (unsigned int layout_index) const;
/**
* @brief Clears the breakout cell list for a given layout
*/
void clear_breakout_cells (unsigned int layout_index);
/**
* @brief Sets the breakout cell list for a given layout
*/
void set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc);
/**
* @brief Adds a breakout cell for a given layout
*/
void add_breakout_cell (unsigned int layout_index, db::cell_index_type ci);
/**
* @brief Adds breakout cells for a given layout
*/
void add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc);
/**
* @brief Pushes the state on the state stack
* The state involves threads, max_area_ratio, max_vertex_count, the breakout cells and
* the text representation properties (enlargement, property name).
*/
void push_state ();
/**
* @brief Pops the state (see @ref push_state)
*/
void pop_state ();
private:
friend class DeepLayer;
@ -614,11 +691,8 @@ private:
std::map<size_t, std::pair<unsigned int, unsigned int> > m_layers_for_flat;
std::map<std::pair<unsigned int, unsigned int>, size_t> m_flat_region_id;
layout_map_type m_layout_map;
int m_threads;
double m_max_area_ratio;
size_t m_max_vertex_count;
tl::Variant m_text_property_name;
int m_text_enlargement;
DeepShapeStoreState m_state;
std::list<DeepShapeStoreState> m_state_stack;
tl::Mutex m_lock;
struct DeliveryMappingCacheKey

View File

@ -136,13 +136,13 @@ bool AllDeviceParametersAreEqual::equal (const db::Device &a, const db::Device &
// DeviceClass class implementation
DeviceClass::DeviceClass ()
: mp_netlist (0), m_strict (false)
: m_strict (false), mp_netlist (0)
{
// .. nothing yet ..
}
DeviceClass::DeviceClass (const DeviceClass &other)
: gsi::ObjectBase (other), tl::Object (other), tl::UniqueId (other), mp_netlist (0), m_strict (false)
: gsi::ObjectBase (other), tl::Object (other), tl::UniqueId (other), m_strict (false), mp_netlist (0)
{
operator= (other);
}

View File

@ -60,6 +60,13 @@ template <class Container, class Trans> void insert_transformed (db::Layout & /*
shapes.insert (s.transformed (t));
}
// ------------------------------------------------------------------------------
static bool is_breakout_cell (const std::set<db::cell_index_type> *breakout_cells, db::cell_index_type ci)
{
return breakout_cells && breakout_cells->find (ci) != breakout_cells->end ();
}
// ------------------------------------------------------------------------------
// Connectivity implementation
@ -1117,11 +1124,11 @@ void hier_clusters<T>::clear ()
template <class T>
void
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence)
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
{
clear ();
cell_clusters_box_converter<T> cbc (layout, *this);
do_build (cbc, layout, cell, shape_flags, conn, attr_equivalence);
do_build (cbc, layout, cell, shape_flags, conn, attr_equivalence, breakout_cells);
}
namespace
@ -1159,8 +1166,8 @@ public:
/**
* @brief Constructor
*/
hc_receiver (const db::Layout &layout, const db::Cell &cell, db::connected_clusters<T> &cell_clusters, hier_clusters<T> &tree, const cell_clusters_box_converter<T> &cbc, const db::Connectivity &conn)
: mp_layout (&layout), mp_cell (&cell), mp_tree (&tree), mp_cbc (&cbc), mp_conn (&conn)
hc_receiver (const db::Layout &layout, const db::Cell &cell, db::connected_clusters<T> &cell_clusters, hier_clusters<T> &tree, const cell_clusters_box_converter<T> &cbc, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, typename hier_clusters<T>::instance_interaction_cache_type *instance_interaction_cache)
: mp_layout (&layout), mp_cell (&cell), mp_tree (&tree), mp_cbc (&cbc), mp_conn (&conn), mp_breakout_cells (breakout_cells), mp_instance_interaction_cache (instance_interaction_cache)
{
mp_cell_clusters = &cell_clusters;
}
@ -1170,9 +1177,37 @@ public:
*/
void add (const db::Instance *i1, unsigned int /*p1*/, const db::Instance *i2, unsigned int /*p2*/)
{
std::vector<ClusterInstElement> p;
db::ICplxTrans t;
add_pair (box_type::world (), *i1, p, t, *i2, p, t);
db::ICplxTrans t1 = i1->complex_trans ();
db::ICplxTrans t2 = i2->complex_trans ();
db::ICplxTrans t21 = t1.inverted () * t2;
InstanceToInstanceInteraction ii_key (i1->cell_index (), i2->cell_index (), t21);
instance_interaction_cache_type::iterator ii = mp_instance_interaction_cache->find (ii_key);
if (ii != mp_instance_interaction_cache->end ()) {
db::ICplxTrans ic_trans = t1 * ii->second.first.inverted ();
connect_clusters (ii->second.second, &ic_trans, i1->prop_id (), i2->prop_id ());
} else {
std::list<std::pair<ClusterInstance, ClusterInstance> > &ic = mp_instance_interaction_cache->insert (std::make_pair (ii_key, std::make_pair (t1, cluster_instance_pair_list_type ()))).first->second.second;
std::vector<ClusterInstElement> p;
db::ICplxTrans t;
add_pair (box_type::world (), *i1, p, t, *i2, p, t, ic);
#if 1
// For debugging: ensures the instance properties are configured properly (important for cache consistency)
for (cluster_instance_pair_list_type::const_iterator i = ic.begin (); i != ic.end (); ++i) {
tl_assert (i->first.inst_prop_id () == i1->prop_id ());
tl_assert (i->second.inst_prop_id () == i2->prop_id ());
}
#endif
connect_clusters (ic);
}
}
/**
@ -1180,9 +1215,7 @@ public:
*/
void finish (const db::Instance *i, unsigned int /*p1*/)
{
if (i->size () > 1) {
add_single_inst (*i);
}
add_single_inst (*i);
}
/**
@ -1243,16 +1276,45 @@ public:
}
private:
struct InteractionKeyForClustersType
: public InstanceToInstanceInteraction
{
InteractionKeyForClustersType (db::cell_index_type _ci1, db::cell_index_type _ci2, const db::ICplxTrans &_t21, const box_type &_box)
: InstanceToInstanceInteraction (_ci1, _ci2, _t21), box (_box)
{ }
bool operator== (const InteractionKeyForClustersType &other) const
{
return InstanceToInstanceInteraction::operator== (other) && box == other.box;
}
bool operator< (const InteractionKeyForClustersType &other) const
{
if (! InstanceToInstanceInteraction::operator== (other)) {
return InstanceToInstanceInteraction::operator< (other);
}
if (box != other.box) {
return box < other.box;
}
return false;
}
box_type box;
};
const db::Layout *mp_layout;
const db::Cell *mp_cell;
db::connected_clusters<T> *mp_cell_clusters;
hier_clusters<T> *mp_tree;
const cell_clusters_box_converter<T> *mp_cbc;
const db::Connectivity *mp_conn;
const std::set<db::cell_index_type> *mp_breakout_cells;
typedef std::list<std::set<id_type> > join_set_list;
std::map<id_type, typename join_set_list::iterator> m_cm2join_map;
join_set_list m_cm2join_sets;
std::list<ClusterInstanceInteraction> m_ci_interactions;
std::map<InteractionKeyForClustersType, std::vector<std::pair<size_t, size_t> > > m_interaction_cache_for_clusters;
instance_interaction_cache_type *mp_instance_interaction_cache;
/**
* @brief Handles the cluster interactions between two instances or instance arrays
@ -1264,8 +1326,12 @@ private:
* @param p2 The instantiation path to the child cell (not including i2)
* @param t2 The accumulated transformation of the path, not including i2
*/
void add_pair (const box_type &common, const db::Instance &i1, const std::vector<ClusterInstElement> &p1, const db::ICplxTrans &t1, const db::Instance &i2, const std::vector<ClusterInstElement> &p2, const db::ICplxTrans &t2)
void add_pair (const box_type &common, const db::Instance &i1, const std::vector<ClusterInstElement> &p1, const db::ICplxTrans &t1, const db::Instance &i2, const std::vector<ClusterInstElement> &p2, const db::ICplxTrans &t2, std::list<std::pair<ClusterInstance, ClusterInstance> > &interacting_clusters)
{
if (is_breakout_cell (mp_breakout_cells, i1.cell_index ()) || is_breakout_cell (mp_breakout_cells, i2.cell_index ())) {
return;
}
box_type bb1 = (*mp_cbc) (i1.cell_index ());
box_type b1 = i1.cell_inst ().bbox (*mp_cbc).transformed (t1);
@ -1310,12 +1376,12 @@ private:
pp2.insert (pp2.end (), p2.begin (), p2.end ());
pp2.push_back (ClusterInstElement (i2.cell_index (), i2.complex_trans (*ii2), i2.prop_id ()));
add_single_pair (common12, i1.cell_index (), pp1, tt1, i2.cell_index (), pp2, tt2);
add_single_pair (common12, i1.cell_index (), pp1, tt1, i2.cell_index (), pp2, tt2, interacting_clusters);
// dive into cell of ii2
const db::Cell &cell2 = mp_layout->cell (i2.cell_index ());
for (db::Cell::touching_iterator jj2 = cell2.begin_touching (common12.transformed (tt2.inverted ())); ! jj2.at_end (); ++jj2) {
add_pair (common12, i1, p1, t1, *jj2, pp2, tt2);
add_pair (common12, i1, p1, t1, *jj2, pp2, tt2, interacting_clusters);
}
}
@ -1329,7 +1395,7 @@ private:
// dive into cell of ii1
const db::Cell &cell1 = mp_layout->cell (i1.cell_index ());
for (db::Cell::touching_iterator jj1 = cell1.begin_touching (common1.transformed (tt1.inverted ())); ! jj1.at_end (); ++jj1) {
add_pair (common1, *jj1, pp1, tt1, i2, p2, t2);
add_pair (common1, *jj1, pp1, tt1, i2, p2, t2, interacting_clusters);
}
}
@ -1349,75 +1415,70 @@ private:
*/
void add_single_pair (const box_type &common,
db::cell_index_type ci1, const std::vector<ClusterInstElement> &p1, const db::ICplxTrans &t1,
db::cell_index_type ci2, const std::vector<ClusterInstElement> &p2, const db::ICplxTrans &t2)
db::cell_index_type ci2, const std::vector<ClusterInstElement> &p2, const db::ICplxTrans &t2,
cluster_instance_pair_list_type &interacting_clusters)
{
const db::Cell &cell2 = mp_layout->cell (ci2);
const db::local_clusters<T> &cl1 = mp_tree->clusters_per_cell (ci1);
const db::local_clusters<T> &cl2 = mp_tree->clusters_per_cell (ci2);
if (is_breakout_cell (mp_breakout_cells, ci1) || is_breakout_cell (mp_breakout_cells, ci2)) {
return;
}
db::ICplxTrans t1i = t1.inverted ();
db::ICplxTrans t2i = t2.inverted ();
db::ICplxTrans t21 = t1i * t2;
box_type common2 = common.transformed (t2i);
// NOTE: make_path may disturb the iteration (because of modification), hence
// we first collect and then process the interactions.
std::vector<std::pair<size_t, size_t> > interactions;
const std::vector<std::pair<size_t, size_t> > *interactions;
for (typename db::local_clusters<T>::touching_iterator i = cl1.begin_touching (common.transformed (t1i)); ! i.at_end (); ++i) {
InteractionKeyForClustersType ikey (ci1, ci2, t21, common2);
// skip the test, if this cluster doesn't interact with the whole cell2
if (! i->interacts (cell2, t21, *mp_conn)) {
continue;
}
typename std::map<InteractionKeyForClustersType, std::vector<std::pair<size_t, size_t> > >::const_iterator ici = m_interaction_cache_for_clusters.find (ikey);
if (ici != m_interaction_cache_for_clusters.end ()) {
box_type bc1 = common & i->bbox ().transformed (t1);
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (bc1.transformed (t2i)); ! j.at_end (); ++j) {
interactions = &ici->second;
} else {
const db::Cell &cell2 = mp_layout->cell (ci2);
const db::local_clusters<T> &cl1 = mp_tree->clusters_per_cell (ci1);
const db::local_clusters<T> &cl2 = mp_tree->clusters_per_cell (ci2);
std::vector<std::pair<size_t, size_t> > new_interactions;
db::ICplxTrans t12 = t2i * t1;
for (typename db::local_clusters<T>::touching_iterator i = cl1.begin_touching (common2.transformed (t21)); ! i.at_end (); ++i) {
// skip the test, if this cluster doesn't interact with the whole cell2
if (! i->interacts (cell2, t21, *mp_conn)) {
continue;
}
box_type bc2 = (common2 & i->bbox ().transformed (t12));
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (bc2); ! j.at_end (); ++j) {
if (i->interacts (*j, t21, *mp_conn)) {
new_interactions.push_back (std::make_pair (i->id (), j->id ()));
}
if (i->interacts (*j, t21, *mp_conn)) {
interactions.push_back (std::make_pair (i->id (), j->id ()));
}
}
std::vector<std::pair<size_t, size_t> > &out = m_interaction_cache_for_clusters [ikey];
out = new_interactions;
interactions = &out;
}
for (std::vector<std::pair<size_t, size_t> >::const_iterator ii = interactions.begin (); ii != interactions.end (); ++ii) {
for (std::vector<std::pair<size_t, size_t> >::const_iterator ii = interactions->begin (); ii != interactions->end (); ++ii) {
ClusterInstance k1 = make_path (ii->first, p1);
ClusterInstance k2 = make_path (ii->second, p2);
id_type x1 = mp_cell_clusters->find_cluster_with_connection (k1);
id_type x2 = mp_cell_clusters->find_cluster_with_connection (k2);
if (x1 == 0) {
if (x2 == 0) {
id_type connector = mp_cell_clusters->insert_dummy ();
mp_cell_clusters->add_connection (connector, k1);
mp_cell_clusters->add_connection (connector, k2);
} else {
mp_cell_clusters->add_connection (x2, k1);
}
} else if (x2 == 0) {
mp_cell_clusters->add_connection (x1, k2);
} else if (x1 != x2) {
// for instance-to-instance interactions the number of connections is more important for the
// cost of the join operation: make the one with more connections the target
if (mp_cell_clusters->connections_for_cluster (x1).size () < mp_cell_clusters->connections_for_cluster (x2).size ()) {
std::swap (x1, x2);
}
mp_cell_clusters->join_cluster_with (x1, x2);
mp_cell_clusters->remove_cluster (x2);
}
interacting_clusters.push_back (std::make_pair (k1, k2));
}
}
@ -1427,6 +1488,10 @@ private:
*/
void add_single_inst (const db::Instance &i)
{
if (is_breakout_cell (mp_breakout_cells, i.cell_index ())) {
return;
}
box_type bb = (*mp_cbc) (i.cell_index ());
const db::Cell &cell = mp_layout->cell (i.cell_index ());
@ -1456,8 +1521,10 @@ private:
std::vector<ClusterInstElement> pp2;
pp2.push_back (ClusterInstElement (i.cell_index (), i.complex_trans (*ii2), i.prop_id ()));
cluster_instance_pair_list_type interacting_clusters;
box_type common = (ib & ib2);
add_single_pair (common, i.cell_index (), pp, tt, i.cell_index (), pp2, tt2);
add_single_pair (common, i.cell_index (), pp, tt, i.cell_index (), pp2, tt2, interacting_clusters);
// dive into cell of ii2 - this is a self-interaction of a cell with parts of itself
// as these self-interactions are expected to be the same always (regular array), we can skip this test the next times.
@ -1465,10 +1532,12 @@ private:
for (db::Cell::touching_iterator jj2 = cell.begin_touching (common.transformed (tt2.inverted ())); ! jj2.at_end (); ++jj2) {
std::vector<ClusterInstElement> p;
db::ICplxTrans t;
add_pair (common, i, p, t, *jj2, pp2, tt2);
add_pair (common, i, p, t, *jj2, pp2, tt2, interacting_clusters);
}
}
connect_clusters (interacting_clusters);
any = true;
}
@ -1494,6 +1563,10 @@ private:
*/
void add_pair (const local_cluster<T> &c1, const db::Instance &i2, const std::vector<ClusterInstElement> &p2, const db::ICplxTrans &t2)
{
if (is_breakout_cell (mp_breakout_cells, i2.cell_index ())) {
return;
}
box_type b1 = c1.bbox ();
box_type bb2 = (*mp_cbc) (i2.cell_index ());
@ -1519,6 +1592,7 @@ private:
if (b1.touches (ib2) && c1.interacts (cell2, tt2, *mp_conn)) {
pp2.back () = ClusterInstElement (i2.cell_index (), i2.complex_trans (*ii2), i2.prop_id ());
add_single_pair (c1, i2.cell_index (), pp2, tt2);
// dive into cell of ii2
@ -1541,6 +1615,10 @@ private:
void add_single_pair (const local_cluster<T> &c1,
db::cell_index_type ci2, const std::vector<ClusterInstElement> &p2, const db::ICplxTrans &t2)
{
if (is_breakout_cell (mp_breakout_cells, ci2)) {
return;
}
// NOTE: make_path may disturb the iteration (because of modification), hence
// we first collect and then process the interactions.
@ -1638,6 +1716,58 @@ private:
{
return mp_tree->make_path (*mp_layout, *mp_cell, id, path);
}
/**
* @brief Establishes connections between the cluster instances listed in the argument
*/
void connect_clusters (const cluster_instance_pair_list_type &interacting_clusters, const db::ICplxTrans *ic_trans = 0, db::properties_id_type prop_id1 = 0, db::properties_id_type prop_id2 = 0)
{
for (cluster_instance_pair_list_type::const_iterator ic = interacting_clusters.begin (); ic != interacting_clusters.end (); ++ic) {
ClusterInstance k1 = ic->first;
ClusterInstance k2 = ic->second;
if (ic_trans) {
k1.transform (*ic_trans);
k1.set_inst_prop_id (prop_id1);
k2.transform (*ic_trans);
k2.set_inst_prop_id (prop_id2);
}
id_type x1 = mp_cell_clusters->find_cluster_with_connection (k1);
id_type x2 = mp_cell_clusters->find_cluster_with_connection (k2);
if (x1 == 0) {
if (x2 == 0) {
id_type connector = mp_cell_clusters->insert_dummy ();
mp_cell_clusters->add_connection (connector, k1);
mp_cell_clusters->add_connection (connector, k2);
} else {
mp_cell_clusters->add_connection (x2, k1);
}
} else if (x2 == 0) {
mp_cell_clusters->add_connection (x1, k2);
} else if (x1 != x2) {
// for instance-to-instance interactions the number of connections is more important for the
// cost of the join operation: make the one with more connections the target
if (mp_cell_clusters->connections_for_cluster (x1).size () < mp_cell_clusters->connections_for_cluster (x2).size ()) {
std::swap (x1, x2);
}
mp_cell_clusters->join_cluster_with (x1, x2);
mp_cell_clusters->remove_cluster (x2);
}
}
}
};
template <class T>
@ -1793,7 +1923,7 @@ hier_clusters<T>::make_path (const db::Layout &layout, const db::Cell &cell, siz
template <class T>
void
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence)
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
{
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity, tl::to_string (tr ("Computing shape clusters")));
@ -1815,6 +1945,8 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
// build the hierarchical connections bottom-up and for all cells whose children are computed already
instance_interaction_cache_type instance_interaction_cache;
{
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity + 10, tl::to_string (tr ("Computing hierarchical shape clusters")));
tl::RelativeProgress progress (tl::to_string (tr ("Computing hierarchical clusters")), called.size (), 1);
@ -1835,7 +1967,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
todo.push_back (*c);
} else {
tl_assert (! todo.empty ());
build_hier_connections_for_cells (cbc, layout, todo, conn, progress);
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache);
done.insert (todo.begin (), todo.end ());
todo.clear ();
todo.push_back (*c);
@ -1845,7 +1977,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
}
build_hier_connections_for_cells (cbc, layout, todo, conn, progress);
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache);
}
}
@ -1865,10 +1997,10 @@ hier_clusters<T>::build_local_cluster (const db::Layout &layout, const db::Cell
template <class T>
void
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, tl::RelativeProgress &progress)
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache)
{
for (std::vector<db::cell_index_type>::const_iterator c = cells.begin (); c != cells.end (); ++c) {
build_hier_connections (cbc, layout, layout.cell (*c), conn);
build_hier_connections (cbc, layout, layout.cell (*c), conn, breakout_cells, instance_interaction_cache);
++progress;
}
}
@ -1952,7 +2084,7 @@ private:
template <class T>
void
hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn)
hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache)
{
std::string msg = tl::to_string (tr ("Computing hierarchical clusters for cell: ")) + std::string (layout.cell_name (cell.cell_index ()));
if (tl::verbosity () >= m_base_verbosity + 20) {
@ -1964,7 +2096,7 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
// NOTE: this is a receiver for both the child-to-child and
// local to child interactions.
std::auto_ptr<hc_receiver<T> > rec (new hc_receiver<T> (layout, cell, local, *this, cbc, conn));
std::auto_ptr<hc_receiver<T> > rec (new hc_receiver<T> (layout, cell, local, *this, cbc, conn, breakout_cells, &instance_interaction_cache));
cell_inst_clusters_box_converter<T> cibc (cbc);
// The box scanner needs pointers so we have to first store the instances
@ -1992,7 +2124,9 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
db::box_scanner<db::Instance, unsigned int> bs (true, desc);
for (std::vector<db::Instance>::const_iterator inst = inst_storage.begin (); inst != inst_storage.end (); ++inst) {
bs.insert (inst.operator-> (), 0);
if (! is_breakout_cell (breakout_cells, inst->cell_index ())) {
bs.insert (inst.operator-> (), 0);
}
}
bs.process (*rec, 1 /*touching*/, cibc);
@ -2026,7 +2160,9 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
}
for (std::vector<db::Instance>::const_iterator inst = inst_storage.begin (); inst != inst_storage.end (); ++inst) {
bs2.insert2 (inst.operator-> (), 0);
if (! is_breakout_cell (breakout_cells, inst->cell_index ())) {
bs2.insert2 (inst.operator-> (), 0);
}
}
bs2.process (*rec, 1 /*touching*/, local_cluster_box_convert<T> (), cibc);

View File

@ -33,6 +33,8 @@
#include "tlEquivalenceClusters.h"
#include <map>
#include <list>
#include <vector>
#include <set>
#include <limits>
@ -608,6 +610,14 @@ public:
return m_inst_prop_id;
}
/**
* @brief Sets the instance properties id
*/
void set_inst_prop_id (db::properties_id_type pid)
{
m_inst_prop_id = pid;
}
/**
* @brief Transform with the given transformation
*/
@ -722,6 +732,42 @@ private:
size_t m_id;
};
typedef std::list<std::pair<ClusterInstance, ClusterInstance> > cluster_instance_pair_list_type;
/**
* @brief A helper struct to describe a pair of cell instances with a specific relative transformation
*/
struct InstanceToInstanceInteraction
{
InstanceToInstanceInteraction (db::cell_index_type _ci1, db::cell_index_type _ci2, const db::ICplxTrans &_t21)
: ci1 (_ci1), ci2 (_ci2), t21 (_t21)
{ }
bool operator== (const InstanceToInstanceInteraction &other) const
{
return ci1 == other.ci1 && ci2 == other.ci2 && t21.equal (other.t21);
}
bool operator< (const InstanceToInstanceInteraction &other) const
{
if (ci1 != other.ci1) {
return ci1 < other.ci1;
}
if (ci2 != other.ci2) {
return ci2 < other.ci2;
}
if (! t21.equal (other.t21)) {
return t21.less (other.t21);
}
return false;
}
db::cell_index_type ci1, ci2;
db::ICplxTrans t21;
};
typedef std::map<InstanceToInstanceInteraction, std::pair<db::ICplxTrans, cluster_instance_pair_list_type> > instance_interaction_cache_type;
template <class T> class hier_clusters;
template <class T> class connected_clusters;
@ -895,6 +941,7 @@ class DB_PUBLIC hier_clusters
{
public:
typedef typename local_cluster<T>::box_type box_type;
typedef std::map<InstanceToInstanceInteraction, std::pair<db::ICplxTrans, cluster_instance_pair_list_type> > instance_interaction_cache_type;
/**
* @brief Creates an empty set of clusters
@ -912,7 +959,7 @@ public:
/**
* @brief Builds a hierarchy of clusters from a cell hierarchy and given connectivity
*/
void build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence = 0);
void build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence = 0, const std::set<cell_index_type> *breakout_cells = 0);
/**
* @brief Gets the connected clusters for a given cell
@ -951,9 +998,9 @@ public:
private:
void build_local_cluster (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence);
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn);
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, tl::RelativeProgress &progress);
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence = 0);
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache);
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache);
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence, const std::set<cell_index_type> *breakout_cells);
std::map<db::cell_index_type, connected_clusters<T> > m_per_cell_clusters;
int m_base_verbosity;

View File

@ -1046,15 +1046,21 @@ template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::E
// LocalProcessor implementation
template <class TS, class TI, class TR>
local_processor<TS, TI, TR>::local_processor (db::Layout *layout, db::Cell *top)
: mp_subject_layout (layout), mp_intruder_layout (layout), mp_subject_top (top), mp_intruder_top (top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
local_processor<TS, TI, TR>::local_processor (db::Layout *layout, db::Cell *top, const std::set<db::cell_index_type> *breakout_cells)
: mp_subject_layout (layout), mp_intruder_layout (layout),
mp_subject_top (top), mp_intruder_top (top),
mp_subject_breakout_cells (breakout_cells), mp_intruder_breakout_cells (breakout_cells),
m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
{
// .. nothing yet ..
}
template <class TS, class TI, class TR>
local_processor<TS, TI, TR>::local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_top)
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), mp_subject_top (subject_top), mp_intruder_top (intruder_top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
local_processor<TS, TI, TR>::local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_top, const std::set<cell_index_type> *subject_breakout_cells, const std::set<cell_index_type> *intruder_breakout_cells)
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout),
mp_subject_top (subject_top), mp_intruder_top (intruder_top),
mp_subject_breakout_cells (subject_breakout_cells), mp_intruder_breakout_cells (intruder_breakout_cells),
m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
{
// .. nothing yet ..
}
@ -1265,10 +1271,10 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
unsigned int iid = ++id;
if (! inst_bcs (i->cell_inst ()).empty ()) {
if (! inst_bcs (i->cell_inst ()).empty () && ! subject_cell_is_breakout (i->cell_index ())) {
scanner.insert1 (&i->cell_inst (), iid);
}
if (! inst_bci (i->cell_inst ()).empty ()) {
if (! inst_bci (i->cell_inst ()).empty () && ! intruder_cell_is_breakout (i->cell_index ())) {
scanner.insert2 (&i->cell_inst (), iid);
}
}
@ -1276,14 +1282,14 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
} else {
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
if (! inst_bcs (i->cell_inst ()).empty ()) {
if (! inst_bcs (i->cell_inst ()).empty () && ! subject_cell_is_breakout (i->cell_index ())) {
scanner.insert1 (&i->cell_inst (), ++id);
}
}
if (intruder_cell) {
for (db::Cell::const_iterator i = intruder_cell->begin (); !i.at_end (); ++i) {
if (! inst_bci (i->cell_inst ()).empty ()) {
if (! inst_bci (i->cell_inst ()).empty () && ! intruder_cell_is_breakout (i->cell_index ())) {
scanner.insert2 (&i->cell_inst (), ++id);
}
}
@ -1306,7 +1312,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
interaction_registration_inst2shape<TI> rec (mp_subject_layout, contexts.subject_layer (), dist, &interactions);
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
if (! inst_bcs (i->cell_inst ()).empty ()) {
if (! inst_bcs (i->cell_inst ()).empty () && ! subject_cell_is_breakout (i->cell_index ())) {
scanner.insert1 (&i->cell_inst (), 0);
}
}
@ -1701,7 +1707,7 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
} else if (intruder_cell) {
// TODO: can we confine this search to the subject's (sized) bounding box?
for (db::Cell::const_iterator i = intruder_cell->begin (); !i.at_end (); ++i) {
if (! inst_bci (i->cell_inst ()).empty ()) {
if (! inst_bci (i->cell_inst ()).empty () && ! intruder_cell_is_breakout (i->cell_index ())) {
scanner.insert2 (&i->cell_inst (), ++inst_id);
}
}

View File

@ -368,8 +368,8 @@ template <class TS, class TI, class TR>
class DB_PUBLIC local_processor
{
public:
local_processor (db::Layout *layout, db::Cell *top);
local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell);
local_processor (db::Layout *layout, db::Cell *top, const std::set<db::cell_index_type> *breakout_cells = 0);
local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set<db::cell_index_type> *subject_breakout_cells = 0, const std::set<db::cell_index_type> *intruder_breakout_cells = 0);
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer);
void compute_contexts (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer) const;
void compute_results (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, unsigned int output_layer) const;
@ -427,6 +427,8 @@ private:
const db::Layout *mp_intruder_layout;
db::Cell *mp_subject_top;
const db::Cell *mp_intruder_top;
const std::set<db::cell_index_type> *mp_subject_breakout_cells;
const std::set<db::cell_index_type> *mp_intruder_breakout_cells;
std::string m_description;
unsigned int m_nthreads;
size_t m_max_vertex_count;
@ -445,6 +447,16 @@ private:
void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set<TR> &result) const;
void compute_local_cell (const db::local_processor_contexts<TS, TI, TR> &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation<TS, TI, TR> *op, const typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, std::unordered_set<TR> &result) const;
std::pair<bool, db::CellInstArray> effective_instance (local_processor_contexts<TS, TI, TR> &contexts, db::cell_index_type subject_cell_index, db::cell_index_type intruder_cell_index, const db::ICplxTrans &ti2s, db::Coord dist) const;
bool subject_cell_is_breakout (db::cell_index_type ci) const
{
return mp_subject_breakout_cells && mp_subject_breakout_cells->find (ci) != mp_subject_breakout_cells->end ();
}
bool intruder_cell_is_breakout (db::cell_index_type ci) const
{
return mp_intruder_breakout_cells && mp_intruder_breakout_cells->find (ci) != mp_intruder_breakout_cells->end ();
}
};
}

View File

@ -36,7 +36,7 @@ Library::Library()
}
Library::Library(const Library &d)
: gsi::ObjectBase (), m_name (d.m_name), m_description (d.m_description), m_id (0), m_layout (d.m_layout)
: gsi::ObjectBase (), tl::Object (), m_name (d.m_name), m_description (d.m_description), m_id (0), m_layout (d.m_layout)
{
// .. nothing yet ..
}

View File

@ -603,9 +603,17 @@ public:
}
/**
* @brief Returns true, if the net is floating (there is no active element on the net)
* @brief Returns true, if the net is floating (there is no device, no subcircuit and no pin)
*/
bool is_floating () const
{
return (m_subcircuit_pins.size () + m_terminals.size () + m_pins.size ()) < 1;
}
/**
* @brief Returns true, if the net is passive (there is no active element on the net)
*/
bool is_passive () const
{
return (m_subcircuit_pins.size () + m_terminals.size ()) < 1;
}

View File

@ -380,6 +380,30 @@ void Netlist::purge_circuit (Circuit *circuit)
remove_circuit (circuit);
}
void Netlist::flatten_circuits (const std::vector<Circuit *> &circuits)
{
if (circuits.empty ()) {
return;
}
std::set<Circuit *> circuits_set (circuits.begin (), circuits.end ());
std::vector<Circuit *> to_flatten;
to_flatten.reserve (circuits.size ());
// Before flatten, we sort top-down. This optimizes for the case of flattening away
// some hierarchy above a certain circuit.
for (top_down_circuit_iterator c = begin_top_down (); c != end_top_down (); ++c) {
if (circuits_set.find (c.operator-> ()) != circuits_set.end ()) {
to_flatten.push_back (c.operator-> ());
}
}
for (std::vector<Circuit *>::const_iterator c = to_flatten.begin (); c != to_flatten.end (); ++c) {
flatten_circuit (*c);
}
}
void Netlist::flatten_circuit (Circuit *circuit)
{
tl_assert (circuit != 0);
@ -485,8 +509,16 @@ void Netlist::purge ()
Circuit *circuit = c.operator-> ();
// purge floating, disconnected nets
circuit->purge_nets ();
if (circuit->begin_nets () == circuit->end_nets () && ! circuit->dont_purge ()) {
// if only passive nets are left, consider this circuit for purging
bool purge_candidate = ! circuit->dont_purge ();
for (db::Circuit::net_iterator n = circuit->begin_nets (); n != circuit->end_nets () && purge_candidate; ++n) {
purge_candidate = n->is_passive ();
}
if (purge_candidate) {
// No nets left: delete the subcircuits that refer to us and finally delete the circuit
while (circuit->begin_refs () != circuit->end_refs ()) {

View File

@ -174,6 +174,12 @@ public:
*/
void flatten_circuit (Circuit *circuit);
/**
* @brief Flattens the given circuits
* This is basically equivalent to calling flatten on all given circuits, but more efficient.
*/
void flatten_circuits (const std::vector<Circuit *> &circuits);
/**
* @brief Flattens the netlist
*/

File diff suppressed because it is too large Load Diff

View File

@ -75,7 +75,7 @@ std::string NetlistDeviceExtractorError::to_string () const
// NetlistDeviceExtractor implementation
NetlistDeviceExtractor::NetlistDeviceExtractor (const std::string &name)
: mp_layout (0), m_cell_index (0), m_device_scaling (1.0), mp_circuit (0)
: mp_layout (0), m_cell_index (0), mp_breakout_cells (0), m_device_scaling (1.0), mp_circuit (0)
{
m_name = name;
m_terminal_id_propname_id = 0;
@ -184,13 +184,13 @@ void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, unsigned int layo
}
extract_without_initialize (dss.layout (layout_index), dss.initial_cell (layout_index), clusters, layers, device_scaling);
extract_without_initialize (dss.layout (layout_index), dss.initial_cell (layout_index), clusters, layers, device_scaling, dss.breakout_cells (layout_index));
}
void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &layers, db::Netlist *nl, hier_clusters_type &clusters, double device_scaling)
void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &layers, db::Netlist *nl, hier_clusters_type &clusters, double device_scaling, const std::set<db::cell_index_type> *breakout_cells)
{
initialize (nl);
extract_without_initialize (layout, cell, clusters, layers, device_scaling);
extract_without_initialize (layout, cell, clusters, layers, device_scaling, breakout_cells);
}
namespace {
@ -203,7 +203,7 @@ struct ExtractorCacheValueType {
}
void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling)
void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling, const std::set<db::cell_index_type> *breakout_cells)
{
tl_assert (layers.size () == m_layer_definitions.size ());
@ -214,6 +214,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db:
m_layers = layers;
mp_clusters = &clusters;
m_device_scaling = device_scaling;
mp_breakout_cells = breakout_cells;
// terminal properties are kept in a property with the terminal_property_name name
m_terminal_id_propname_id = mp_layout->properties_repository ().prop_name_id (terminal_id_property_name ());
@ -246,7 +247,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db:
db::Connectivity device_conn = get_connectivity (layout, layers);
db::hier_clusters<shape_type> device_clusters;
device_clusters.build (layout, cell, shape_iter_flags, device_conn);
device_clusters.build (layout, cell, shape_iter_flags, device_conn, 0, breakout_cells);
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Extracting devices")));

View File

@ -263,7 +263,7 @@ public:
*
* NOTE: The extractor expects "PolygonRef" type layers.
*/
void extract (Layout &layout, Cell &cell, const std::vector<unsigned int> &layers, Netlist *netlist, hier_clusters_type &clusters, double device_scaling = 1.0);
void extract (Layout &layout, Cell &cell, const std::vector<unsigned int> &layers, Netlist *netlist, hier_clusters_type &clusters, double device_scaling = 1.0, const std::set<cell_index_type> *breakout_cells = 0);
/**
* @brief Extracts the devices from a list of regions
@ -533,6 +533,7 @@ private:
db::properties_id_type m_terminal_id_propname_id, m_device_id_propname_id, m_device_class_propname_id;
hier_clusters_type *mp_clusters;
db::cell_index_type m_cell_index;
const std::set<db::cell_index_type> *mp_breakout_cells;
double m_device_scaling;
db::Circuit *mp_circuit;
db::DeviceClass *mp_device_class;
@ -553,7 +554,7 @@ private:
*/
void initialize (db::Netlist *nl);
void extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling);
void extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling, const std::set<cell_index_type> *breakout_cells);
void push_new_devices (const Vector &disp_cache);
void push_cached_devices (const tl::vector<Device *> &cached_devices, const db::Vector &disp_cache, const db::Vector &new_disp);
};

View File

@ -92,7 +92,6 @@ db::Connectivity NetlistDeviceExtractorMOS3Transistor::get_connectivity (const d
} else {
tl_assert (layers.size () >= 4);
unsigned int sdiff = layers [0];

View File

@ -22,10 +22,78 @@
#include "gsiDecl.h"
#include "dbDeepShapeStore.h"
#include "tlGlobPattern.h"
namespace gsi
{
static void set_or_add_breakout_cells (db::DeepShapeStore *dss, const std::string &pattern, bool add, unsigned int layout_index = std::numeric_limits<unsigned int>::max ())
{
// set or add for all
if (layout_index == std::numeric_limits<unsigned int>::max ()) {
for (unsigned int l = 0; l < dss->layouts (); ++l) {
set_or_add_breakout_cells (dss, pattern, add, l);
}
return;
}
std::set<db::cell_index_type> cc;
if (! pattern.empty ()) {
tl::GlobPattern p (pattern);
const db::Layout &ly = dss->layout (layout_index);
for (db::Layout::const_iterator ci = ly.begin (); ci != ly.end (); ++ci) {
if (p.match (ly.cell_name (ci->cell_index ()))) {
cc.insert (ci->cell_index ());
}
}
}
if (! add) {
dss->clear_breakout_cells (layout_index);
}
if (! cc.empty ()) {
dss->add_breakout_cells (layout_index, cc);
}
}
static void clear_breakout_cells (db::DeepShapeStore *dss)
{
set_or_add_breakout_cells (dss, std::string (), false);
}
static void set_breakout_cells (db::DeepShapeStore *dss, unsigned int layout_index, const std::vector<db::cell_index_type> &cc)
{
std::set<db::cell_index_type> cs (cc.begin (), cc.end ());
dss->set_breakout_cells (layout_index, cs);
}
static void set_breakout_cells2 (db::DeepShapeStore *dss, unsigned int layout_index, const std::string &pattern)
{
set_or_add_breakout_cells (dss, pattern, false, layout_index);
}
static void set_breakout_cells3 (db::DeepShapeStore *dss, const std::string &pattern)
{
set_or_add_breakout_cells (dss, pattern, false);
}
static void add_breakout_cells (db::DeepShapeStore *dss, unsigned int layout_index, const std::vector<db::cell_index_type> &cc)
{
std::set<db::cell_index_type> cs (cc.begin (), cc.end ());
dss->add_breakout_cells (layout_index, cs);
}
static void add_breakout_cells2 (db::DeepShapeStore *dss, unsigned int layout_index, const std::string &pattern)
{
set_or_add_breakout_cells (dss, pattern, true, layout_index);
}
static void add_breakout_cells3 (db::DeepShapeStore *dss, const std::string &pattern)
{
set_or_add_breakout_cells (dss, pattern, true);
}
Class<db::DeepShapeStore> decl_dbDeepShapeStore ("db", "DeepShapeStore",
gsi::method ("instance_count", &db::DeepShapeStore::instance_count,
"@hide\n"
@ -84,6 +152,82 @@ Class<db::DeepShapeStore> decl_dbDeepShapeStore ("db", "DeepShapeStore",
) +
gsi::method ("text_enlargement", &db::DeepShapeStore::text_enlargement,
"@brief Gets the text enlargement value.\n"
) +
gsi::method ("clear_breakout_cells", &db::DeepShapeStore::clear_breakout_cells, gsi::arg ("layout_index"),
"@brief Clears the breakout cells\n"
"Breakout cells are a feature by which hierarchy handling can be disabled for specific cells. "
"If cells are specified as breakout cells, they don't interact with neighbor or parent cells, hence "
"are virtually isolated. Breakout cells are useful to shortcut hierarchy evaluation for cells which "
"are otherwise difficult to handle. An example are memory array cells with overlaps to their neighbors: "
"a precise handling of such cells would generate variants and the boundary of the array. Although precise, "
"this behavior leads to partial flattening and propagation of shapes. In consequence, this will also "
"result in wrong device detection in LVS applications. In such cases, these array cells can be declared "
"'breakout cells' which makes them isolated entities and variant generation does not happen.\n"
"\n"
"See also \\set_breakout_cells and \\add_breakout_cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("clear_breakout_cells", &clear_breakout_cells,
"@brief Clears the breakout cells\n"
"See the other variant of \\clear_breakout_cells for details.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("set_breakout_cells", &set_breakout_cells, gsi::arg ("layout_index"), gsi::arg ("cells"),
"@brief Sets the breakout cell list (as cell indexes) for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("set_breakout_cells", &set_breakout_cells2, gsi::arg ("layout_index"), gsi::arg ("pattern"),
"@brief Sets the breakout cell list (as cell name pattern) for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("set_breakout_cells", &set_breakout_cells3, gsi::arg ("pattern"),
"@brief Sets the breakout cell list (as cell name pattern) for the all layouts inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("add_breakout_cells", &add_breakout_cells, gsi::arg ("layout_index"), gsi::arg ("cells"),
"@brief Adds cell indexes to the breakout cell list for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("add_breakout_cell", &add_breakout_cells, gsi::arg ("layout_index"), gsi::arg ("cell_index"),
"@brief Adds a cell indexe to the breakout cell list for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("add_breakout_cells", &add_breakout_cells2, gsi::arg ("layout_index"), gsi::arg ("pattern"),
"@brief Adds cells (given by a cell name pattern) to the breakout cell list for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("add_breakout_cells", &add_breakout_cells3, gsi::arg ("pattern"),
"@brief Adds cells (given by a cell name pattern) to the breakout cell list to all layouts inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method ("push_state", &db::DeepShapeStore::push_state,
"@brief Pushes the store's state on the state state\n"
"This will save the stores state (\\threads, \\max_vertex_count, \\max_area_ratio, breakout cells ...) on "
"the state stack. \\pop_state can be used to restore the state.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method ("pop_state", &db::DeepShapeStore::pop_state,
"@brief Restores the store's state on the state state\n"
"This will restore the state pushed by \\push_state.\n"
"\n"
"This method has been added in version 0.26.1\n"
),
"@brief An opaque layout heap for the deep region processor\n"
"\n"

View File

@ -567,7 +567,14 @@ Class<db::Net> decl_dbNet ("db", "Net",
) +
gsi::method ("is_floating?", &db::Net::is_floating,
"@brief Returns true, if the net is floating.\n"
"Floating nets are those who don't have any or only a single connection (pin_count + terminal_count < 2)."
"Floating nets are those which don't have any device or subcircuit on it and are not connected through a pin."
) +
gsi::method ("is_passive?", &db::Net::is_passive,
"@brief Returns true, if the net is passive.\n"
"Passive nets don't have devices or subcircuits on it. They can be exposed through a pin.\n"
"\\is_floating? implies \\is_passive?.\n"
"\n"
"This method has been introduced in version 0.26.1.\n"
) +
gsi::method ("is_internal?", &db::Net::is_internal,
"@brief Returns true, if the net is an internal net.\n"
@ -1338,7 +1345,7 @@ static void read_netlist (db::Netlist *nl, const std::string &file, db::NetlistR
static void flatten_circuit_by_name (db::Netlist *nl, const std::string &name_pattern)
{
std::list<tl::weak_ptr<db::Circuit> > circuits_to_flatten;
std::vector<db::Circuit *> circuits_to_flatten;
tl::GlobPattern pat (name_pattern);
for (db::Netlist::circuit_iterator c = nl->begin_circuits (); c != nl->end_circuits (); ++c) {
if (pat.match (c->name ())) {
@ -1346,11 +1353,7 @@ static void flatten_circuit_by_name (db::Netlist *nl, const std::string &name_pa
}
}
for (std::list<tl::weak_ptr<db::Circuit> >::iterator c = circuits_to_flatten.begin (); c != circuits_to_flatten.end (); ++c) {
if (c->get ()) {
nl->flatten_circuit (c->get ());
}
}
nl->flatten_circuits (circuits_to_flatten);
}
static void blank_circuit_by_name (db::Netlist *nl, const std::string &name_pattern)
@ -1392,6 +1395,12 @@ Class<db::Netlist> decl_dbNetlist ("db", "Netlist",
"@brief Flattens all circuits of the netlist\n"
"After calling this method, only the top circuits will remain."
) +
gsi::method ("flatten_circuits", &db::Netlist::flatten_circuits,
"@brief Flattens all given circuits of the netlist\n"
"This method is equivalent to calling \\flatten_circuit for all given circuits, but more efficient.\n"
"\n"
"This method has been introduced in version 0.26.1"
) +
gsi::method ("flatten_circuit", &db::Netlist::flatten_circuit, gsi::arg ("circuit"),
"@brief Flattens a subcircuit\n"
"This method will substitute all instances (subcircuits) of the given circuit by it's "

View File

@ -35,6 +35,8 @@
#include "tlGlobPattern.h"
#include <memory>
#include <vector>
#include <set>
namespace gsi
{
@ -801,7 +803,7 @@ Class<db::Region> decl_Region ("db", "Region",
"See \\strict_handling= for a description of this attribute.\n"
"\n"
"This method has been introduced in version 0.23.2."
) +
) +
method ("min_coherence=", &db::Region::set_min_coherence, gsi::arg ("f"),
"@brief Enable or disable minimum coherence\n"
"If minimum coherence is set, the merge operations (explicit merge with \\merge or\n"

View File

@ -1452,6 +1452,44 @@ TEST(25_Pull)
}
}
TEST(26_BreakoutCells)
{
db::Layout ly;
{
std::string fn (tl::testsrc ());
fn += "/testdata/algo/deep_region_l26.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
dss.add_breakout_cell (0, ly.cell_by_name ("CHILD").second);
db::Region r12 = r1 & r2;
db::Region r1m2 = r1 - r2;
db::Region r21 = r2 & r1;
db::Region r2m1 = r2 - r1;
ly.insert (top_cell.cell_index (), ly.get_layer (db::LayerProperties (100, 0)), r12);
ly.insert (top_cell.cell_index (), ly.get_layer (db::LayerProperties (101, 0)), r1m2);
ly.insert (top_cell.cell_index (), ly.get_layer (db::LayerProperties (102, 0)), r21);
ly.insert (top_cell.cell_index (), ly.get_layer (db::LayerProperties (103, 0)), r2m1);
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au26.gds");
}
TEST(100_Integration)
{
db::Layout ly;

View File

@ -208,3 +208,60 @@ TEST(4_FlatAndEmptyInput)
EXPECT_EQ ((dr1 - dr3).to_string (), "(0,0;0,1000;1000,1000;1000,0)");
}
TEST(5_State)
{
db::DeepShapeStore store ("TOP", 0.01);
EXPECT_EQ (store.layout ().dbu (), 0.01);
store.set_threads (4);
EXPECT_EQ (store.threads (), 4);
store.set_max_area_ratio (2.5);
EXPECT_EQ (store.max_area_ratio (), 2.5);
store.set_max_vertex_count (100);
EXPECT_EQ (store.max_vertex_count (), size_t (100));
store.set_text_enlargement (5);
EXPECT_EQ (store.text_enlargement (), 5);
store.set_text_property_name (tl::Variant ("x"));
EXPECT_EQ (store.text_property_name ().to_string (), "x");
EXPECT_EQ (store.breakout_cells (0) == 0, true);
{
std::set<db::cell_index_type> boc;
boc.insert (5);
store.set_breakout_cells (0, boc);
EXPECT_EQ (store.breakout_cells (0) == 0, false);
EXPECT_EQ (store.breakout_cells (0)->find (5) != store.breakout_cells (0)->end (), true);
EXPECT_EQ (store.breakout_cells (0)->find (3) != store.breakout_cells (0)->end (), false);
store.add_breakout_cell (0, 3);
EXPECT_EQ (store.breakout_cells (0)->find (5) != store.breakout_cells (0)->end (), true);
EXPECT_EQ (store.breakout_cells (0)->find (3) != store.breakout_cells (0)->end (), true);
}
store.push_state ();
store.set_threads (2);
store.set_max_area_ratio (1);
store.set_max_vertex_count (10);
store.set_text_enlargement (1);
store.set_text_property_name (tl::Variant ("y"));
EXPECT_EQ (store.threads (), 2);
EXPECT_EQ (store.max_area_ratio (), 1.0);
EXPECT_EQ (store.max_vertex_count (), size_t (10));
EXPECT_EQ (store.text_enlargement (), 1);
EXPECT_EQ (store.text_property_name ().to_string (), "y");
store.clear_breakout_cells (0);
EXPECT_EQ (store.breakout_cells (0) == 0, true);
store.pop_state ();
EXPECT_EQ (store.threads (), 4);
EXPECT_EQ (store.max_area_ratio (), 2.5);
EXPECT_EQ (store.max_vertex_count (), size_t (100));
EXPECT_EQ (store.text_enlargement (), 5);
EXPECT_EQ (store.text_property_name ().to_string (), "x");
EXPECT_EQ (store.breakout_cells (0) == 0, false);
EXPECT_EQ (store.breakout_cells (0)->find (5) != store.breakout_cells (0)->end (), true);
EXPECT_EQ (store.breakout_cells (0)->find (3) != store.breakout_cells (0)->end (), true);
}

View File

@ -792,7 +792,7 @@ TEST(2_Probing)
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (5.3, 0.0))), "RINGO:VSS");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (2.6, 1.0))), "RINGO:$I18");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I3");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I5");
// doesn't do anything here, but we test that this does not destroy anything:
l2n.netlist ()->combine_devices ();
@ -835,7 +835,7 @@ TEST(2_Probing)
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (5.3, 0.0))), "(null)");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (2.6, 1.0))), "RINGO:$I18");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I3");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I5");
}
TEST(3_GlobalNetConnections)
@ -1073,7 +1073,7 @@ TEST(3_GlobalNetConnections)
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (5.3, 0.0))), "RINGO:VSS");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (2.6, 1.0))), "RINGO:$I22");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I4");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I6");
// doesn't do anything here, but we test that this does not destroy anything:
l2n.netlist ()->combine_devices ();
@ -1096,7 +1096,7 @@ TEST(3_GlobalNetConnections)
" subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);\n"
" subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);\n"
"end;\n"
"circuit INV2 ($1=(null),IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=(null));\n"
"circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
@ -1116,7 +1116,7 @@ TEST(3_GlobalNetConnections)
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (5.3, 0.0))), "(null)");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (2.6, 1.0))), "RINGO:$I22");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I4");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I6");
}
TEST(4_GlobalNetDeviceExtraction)
@ -1360,7 +1360,7 @@ TEST(4_GlobalNetDeviceExtraction)
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (5.3, 0.0))), "RINGO:VSS");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (2.6, 1.0))), "RINGO:$I22");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I4");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I6");
// doesn't do anything here, but we test that this does not destroy anything:
l2n.netlist ()->combine_devices ();
@ -1403,7 +1403,7 @@ TEST(4_GlobalNetDeviceExtraction)
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (5.3, 0.0))), "(null)");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (2.6, 1.0))), "RINGO:$I22");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I4");
EXPECT_EQ (qnet_name (l2n.probe_net (*rmetal1, db::DPoint (6.4, 1.0))), "INV2PAIR:$I6");
}
TEST(5_DeviceExtractionWithDeviceCombination)

View File

@ -2605,8 +2605,8 @@ TEST(17_InherentlyAmbiguousDecoder)
"match_nets NQ1 NQ1\n"
"match_nets NQ2 NQ2\n"
"match_nets NQ3 NQ3\n"
"match_ambiguous_nets NA NA\n"
"match_ambiguous_nets NB NB\n"
"match_nets NA NA\n"
"match_nets NB NB\n"
"match_nets B B\n"
"match_nets A A\n"
"match_pins $0 $1\n"
@ -2796,3 +2796,573 @@ TEST(18_ClockTree)
EXPECT_EQ (good, true);
}
TEST(19_SymmetricCircuit)
{
// Test test requires a certain depth, name sensitivity to resolve ambiguities and
// tests the backtracking paths.
const char *nls1 =
"circuit DECODE (VDD=VDD,nn1_=nn1_,nn1=nn1,q0=q0,q0_=q0_,q1_=q1_,q1=q1,nn2=nn2,nn2_=nn2_,a0=a0,a0_=a0_,g1=g1,g0=g0,gtp=gtp,VSS=VSS,WELL=$14);"
" device PMOS4 $1 (S=VDD,G=$44,D=q1_,B=VDD) (L=1.2,W=7);"
" device PMOS4 $2 (S=q1_,G=$44,D=q1,B=VDD) (L=1.2,W=7);"
" device PMOS4 $3 (S=q1,G=$44,D=VDD,B=VDD) (L=1.2,W=7);"
" device PMOS4 $4 (S=VDD,G=$44,D=q0,B=VDD) (L=1.2,W=7);"
" device PMOS4 $5 (S=q0,G=$44,D=q0_,B=VDD) (L=1.2,W=7);"
" device PMOS4 $6 (S=q0_,G=$44,D=VDD,B=VDD) (L=1.2,W=7);"
" device PMOS4 $7 (S=q0_,G=$11,D=nn2_,B=VDD) (L=1.2,W=5);"
" device PMOS4 $8 (S=nn2_,G=$13,D=q1_,B=VDD) (L=1.2,W=5);"
" device PMOS4 $9 (S=VDD,G=g0,D=$39,B=VDD) (L=1.2,W=3);"
" device PMOS4 $10 (S=$39,G=g1,D=VDD,B=VDD) (L=1.2,W=3);"
" device PMOS4 $11 (S=VDD,G=a0_,D=$11,B=VDD) (L=1.2,W=10);"
" device PMOS4 $12 (S=$11,G=$44,D=VDD,B=VDD) (L=1.2,W=10);"
" device PMOS4 $13 (S=q0,G=$11,D=nn2,B=VDD) (L=1.2,W=5);"
" device PMOS4 $14 (S=nn1_,G=$13,D=$9,B=$14) (L=1.2,W=11);"
" device PMOS4 $15 (S=$4,G=$11,D=nn1_,B=$14) (L=1.2,W=11);"
" device PMOS4 $16 (S=VDD,G=$44,D=$13,B=VDD) (L=1.2,W=10);"
" device PMOS4 $17 (S=$13,G=a0,D=VDD,B=VDD) (L=1.2,W=10);"
" device PMOS4 $18 (S=$6,G=$11,D=nn1,B=$14) (L=1.2,W=11);"
" device PMOS4 $19 (S=nn1,G=$13,D=$8,B=$14) (L=1.2,W=11);"
" device PMOS4 $20 (S=VDD,G=$41,D=$44,B=VDD) (L=1.2,W=15);"
" device PMOS4 $21 (S=nn2,G=$13,D=q1,B=VDD) (L=1.2,W=5);"
" device PMOS4 $22 (S=VDD,G=$39,D=$37,B=VDD) (L=1.2,W=6);"
" device PMOS4 $23 (S=VDD,G=$42,D=$41,B=VDD) (L=1.2,W=3);"
" device PMOS4 $24 (S=gtp,G=$39,D=$42,B=VDD) (L=1.2,W=16);"
" device NMOS4 $25 (S=$44,G=$41,D=VSS,B=VSS) (L=1.2,W=22);"
" device NMOS4 $26 (S=VSS,G=$39,D=$37,B=VSS) (L=1.2,W=9);"
" device NMOS4 $27 (S=q0_,G=$6,D=VSS,B=VSS) (L=1.2,W=1);"
" device NMOS4 $28 (S=VSS,G=$8,D=q1_,B=VSS) (L=1.2,W=1);"
" device NMOS4 $29 (S=$13,G=$44,D=$35,B=VSS) (L=1.2,W=19);"
" device NMOS4 $30 (S=$35,G=a0,D=VSS,B=VSS) (L=1.2,W=19);"
" device NMOS4 $31 (S=gtp,G=$37,D=$42,B=VSS) (L=1.2,W=16);"
" device NMOS4 $32 (S=VSS,G=$39,D=$42,B=VSS) (L=1.2,W=20);"
" device NMOS4 $33 (S=VSS,G=$4,D=q0,B=VSS) (L=1.2,W=1);"
" device NMOS4 $34 (S=VSS,G=$11,D=$6,B=VSS) (L=1.2,W=18);"
" device NMOS4 $35 (S=$9,G=$13,D=VSS,B=VSS) (L=1.2,W=18);"
" device NMOS4 $36 (S=VSS,G=$11,D=$4,B=VSS) (L=1.2,W=18);"
" device NMOS4 $37 (S=q1,G=$9,D=VSS,B=VSS) (L=1.2,W=1);"
" device NMOS4 $38 (S=$8,G=$13,D=VSS,B=VSS) (L=1.2,W=18);"
" device NMOS4 $39 (S=VSS,G=a0_,D=$34,B=VSS) (L=1.2,W=19);"
" device NMOS4 $40 (S=$34,G=$44,D=$11,B=VSS) (L=1.2,W=19);"
" device NMOS4 $41 (S=VSS,G=g0,D=$40,B=VSS) (L=1.2,W=17);"
" device NMOS4 $42 (S=$40,G=g1,D=$39,B=VSS) (L=1.2,W=17);"
" device NMOS4 $43 (S=VSS,G=$42,D=$41,B=VSS) (L=1.2,W=2);"
"end;"
;
const char *nls2 =
"circuit DECODE (A0=A0,A0_=A0_,Q0=Q0,Q0_=Q0_,Q1=Q1,Q1_=Q1_,NN2=NN2,NN2_=NN2_,NN1=NN1,NN1_=NN1_,G0=G0,G1=G1,NN3=NN3,VDD=VDD,VSS=VSS,WELL=WELL);"
" device NMOS4 '0' (S=HNET44,G=A0,D=VSS,B=VSS) (L=1.2,W=19);"
" device NMOS4 '1' (S=CS1,G=YI,D=HNET44,B=VSS) (L=1.2,W=19);"
" device PMOS4 '10' (S=VDD,G=G0,D=NET194,B=VDD) (L=1.2,W=3);"
" device PMOS4 '11' (S=VDD,G=G1,D=NET194,B=VDD) (L=1.2,W=3);"
" device NMOS4 '12' (S=NET200,G=CS0,D=VSS,B=VSS) (L=1.2,W=18);"
" device NMOS4 '13' (S=VSS,G=CS1,D=NET175,B=VSS) (L=1.2,W=18);"
" device NMOS4 '14' (S=VSS,G=CS0,D=NET181,B=VSS) (L=1.2,W=18);"
" device NMOS4 '15' (S=NET215,G=CS1,D=VSS,B=VSS) (L=1.2,W=18);"
" device NMOS4 '16' (S=Q1,G=NET175,D=VSS,B=VSS) (L=1.2,W=1);"
" device NMOS4 '17' (S=VSS,G=NET200,D=Q0,B=VSS) (L=1.2,W=1);"
" device NMOS4 '18' (S=Q0_,G=NET181,D=VSS,B=VSS) (L=1.2,W=1);"
" device NMOS4 '19' (S=VSS,G=NET215,D=Q1_,B=VSS) (L=1.2,W=1);"
" device PMOS4 '2' (S=VDD,G=A0,D=CS1,B=VDD) (L=1.2,W=10);"
" device NMOS4 '20' (S=NET189,G=NET193,D=NN3,B=VSS) (L=1.2,W=16);"
" device NMOS4 '21' (S=VSS,G=NET194,D=NET189,B=VSS) (L=1.2,W=20);"
" device PMOS4 '22' (S=VDD,G=NET194,D=NET193,B=VDD) (L=1.2,W=6);"
" device NMOS4 '23' (S=NET193,G=NET194,D=VSS,B=VSS) (L=1.2,W=9);"
" device PMOS4 '24' (S=VDD,G=NET189,D=WL1_EN_,B=VDD) (L=1.2,W=3);"
" device NMOS4 '25' (S=WL1_EN_,G=NET189,D=VSS,B=VSS) (L=1.2,W=2);"
" device PMOS4 '26' (S=VDD,G=WL1_EN_,D=YI,B=VDD) (L=1.2,W=15);"
" device NMOS4 '27' (S=YI,G=WL1_EN_,D=VSS,B=VSS) (L=1.2,W=22);"
" device PMOS4 '28' (S=NN1_,G=CS0,D=NET200,B=WELL) (L=1.2,W=11);"
" device PMOS4 '29' (S=NET175,G=CS1,D=NN1_,B=WELL) (L=1.2,W=11);"
" device PMOS4 '3' (S=VDD,G=YI,D=CS1,B=VDD) (L=1.2,W=10);"
" device PMOS4 '30' (S=NET181,G=CS0,D=NN1,B=WELL) (L=1.2,W=11);"
" device PMOS4 '31' (S=Q1,G=CS1,D=NN2,B=VDD) (L=1.2,W=5);"
" device PMOS4 '32' (S=NN2,G=CS0,D=Q0,B=VDD) (L=1.2,W=5);"
" device PMOS4 '33' (S=NN1,G=CS1,D=NET215,B=WELL) (L=1.2,W=11);"
" device PMOS4 '34' (S=Q0_,G=CS0,D=NN2_,B=VDD) (L=1.2,W=5);"
" device PMOS4 '35' (S=NN2_,G=CS1,D=Q1_,B=VDD) (L=1.2,W=5);"
" device PMOS4 '36' (S=NN3,G=NET194,D=NET189,B=VDD) (L=1.2,W=16);"
" device PMOS4 '37' (S=VDD,G=YI,D=Q1,B=VDD) (L=1.2,W=7);"
" device PMOS4 '38' (S=VDD,G=YI,D=Q0_,B=VDD) (L=1.2,W=7);"
" device PMOS4 '39' (S=VDD,G=YI,D=Q0,B=VDD) (L=1.2,W=7);"
" device NMOS4 '4' (S=HNET48,G=A0_,D=VSS,B=VSS) (L=1.2,W=19);"
" device PMOS4 '40' (S=Q0_,G=YI,D=Q0,B=VDD) (L=1.2,W=7);"
" device PMOS4 '41' (S=Q1,G=YI,D=Q1_,B=VDD) (L=1.2,W=7);"
" device PMOS4 '42' (S=VDD,G=YI,D=Q1_,B=VDD) (L=1.2,W=7);"
" device NMOS4 '5' (S=CS0,G=YI,D=HNET48,B=VSS) (L=1.2,W=19);"
" device PMOS4 '6' (S=VDD,G=A0_,D=CS0,B=VDD) (L=1.2,W=10);"
" device PMOS4 '7' (S=VDD,G=YI,D=CS0,B=VDD) (L=1.2,W=10);"
" device NMOS4 '8' (S=HNET52,G=G0,D=VSS,B=VSS) (L=1.2,W=17);"
" device NMOS4 '9' (S=NET194,G=G1,D=HNET52,B=VSS) (L=1.2,W=17);"
"end;"
;
db::Netlist nl1, nl2;
prep_nl (nl1, nls1);
prep_nl (nl2, nls2);
NetlistCompareTestLogger logger;
db::NetlistComparer comp (&logger);
bool good = comp.compare (&nl1, &nl2);
std::string txt = logger.text ();
EXPECT_EQ (txt,
"begin_circuit DECODE DECODE\n"
"match_nets $41 WL1_EN_\n"
"match_nets VDD VDD\n"
"match_nets $39 NET194\n"
"match_nets g0 G0\n"
"match_nets $40 HNET52\n"
"match_nets VSS VSS\n"
"match_nets $42 NET189\n"
"match_nets gtp NN3\n"
"match_nets $37 NET193\n"
"match_nets g1 G1\n"
"match_nets $44 YI\n"
"match_nets $14 WELL\n"
"match_nets $8 NET215\n"
"match_nets $9 NET175\n"
"match_nets $6 NET181\n"
"match_nets $4 NET200\n"
"match_nets nn1 NN1\n"
"match_nets $11 CS0\n"
"match_nets $13 CS1\n"
"match_nets nn2 NN2\n"
"match_nets nn2_ NN2_\n"
"match_nets q0 Q0\n"
"match_nets q1 Q1\n"
"match_nets q0_ Q0_\n"
"match_nets q1_ Q1_\n"
"match_nets a0_ A0_\n"
"match_nets $34 HNET48\n"
"match_nets nn1_ NN1_\n"
"match_nets a0 A0\n"
"match_nets $35 HNET44\n"
"match_pins VDD VDD\n"
"match_pins nn1_ NN1_\n"
"match_pins nn1 NN1\n"
"match_pins q0 Q0\n"
"match_pins q0_ Q0_\n"
"match_pins q1_ Q1_\n"
"match_pins q1 Q1\n"
"match_pins nn2 NN2\n"
"match_pins nn2_ NN2_\n"
"match_pins a0 A0\n"
"match_pins a0_ A0_\n"
"match_pins g1 G1\n"
"match_pins g0 G0\n"
"match_pins gtp NN3\n"
"match_pins VSS VSS\n"
"match_pins WELL WELL\n"
"match_devices $30 0\n"
"match_devices $29 1\n"
"match_devices $9 10\n"
"match_devices $10 11\n"
"match_devices $36 12\n"
"match_devices $35 13\n"
"match_devices $34 14\n"
"match_devices $38 15\n"
"match_devices $37 16\n"
"match_devices $33 17\n"
"match_devices $27 18\n"
"match_devices $28 19\n"
"match_devices $17 2\n"
"match_devices $31 20\n"
"match_devices $32 21\n"
"match_devices $22 22\n"
"match_devices $26 23\n"
"match_devices $23 24\n"
"match_devices $43 25\n"
"match_devices $20 26\n"
"match_devices $25 27\n"
"match_devices $15 28\n"
"match_devices $14 29\n"
"match_devices $16 3\n"
"match_devices $18 30\n"
"match_devices $21 31\n"
"match_devices $13 32\n"
"match_devices $19 33\n"
"match_devices $7 34\n"
"match_devices $8 35\n"
"match_devices $24 36\n"
"match_devices $3 37\n"
"match_devices $6 38\n"
"match_devices $4 39\n"
"match_devices $39 4\n"
"match_devices $5 40\n"
"match_devices $2 41\n"
"match_devices $1 42\n"
"match_devices $40 5\n"
"match_devices $11 6\n"
"match_devices $12 7\n"
"match_devices $41 8\n"
"match_devices $42 9\n"
"end_circuit DECODE DECODE MATCH"
);
EXPECT_EQ (good, true);
}
TEST(20_BusLikeConnections)
{
// Test test requires a certain depth and tests the backtracking paths.
const char *nls1 =
"circuit INV (IN=IN,OUT=OUT,VDD=VDD,VSS=VSS);\n"
" device PMOS $1 (S=VDD,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $2 (S=VSS,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
"end;\n"
"circuit INV8 (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I1 (IN=IN1,OUT=OUT1,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I2 (IN=IN2,OUT=OUT2,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I3 (IN=IN3,OUT=OUT3,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I4 (IN=IN4,OUT=OUT4,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I5 (IN=IN5,OUT=OUT5,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I6 (IN=IN6,OUT=OUT6,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I7 (IN=IN7,OUT=OUT7,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I8 (IN=IN8,OUT=OUT8,VDD=VDD,VSS=VSS);\n"
"end;\n"
"circuit INV8_WRAP (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV8 INV8 (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
"end;\n"
"circuit TOP (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV8_WRAP INV8 (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
"end;\n"
;
const char *nls2 =
"circuit INV (OUT=OUT,IN=IN,VDD=VDD,VSS=VSS);\n"
" device PMOS $1 (S=VDD,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $2 (S=VSS,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
"end;\n"
"circuit INV8 (Q1=Q1,A1=A1,Q2=Q2,A2=A2,Q3=Q3,A3=A3,Q4=Q4,A4=A4,Q5=Q5,A5=A5,Q6=Q6,A6=A6,Q7=Q7,A7=A7,Q8=Q8,A8=A8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I1 (OUT=Q1,IN=A1,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I8 (OUT=Q8,IN=A8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I3 (OUT=Q3,IN=A3,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I7 (OUT=Q7,IN=A7,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I4 (OUT=Q4,IN=A4,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I2 (OUT=Q2,IN=A2,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I6 (OUT=Q6,IN=A6,VDD=VDD,VSS=VSS);\n"
" subcircuit INV I5 (OUT=Q5,IN=A5,VDD=VDD,VSS=VSS);\n"
"end;\n"
"circuit INV8_WRAP (Q1=Q1,A1=A1,Q2=Q2,A2=A2,Q3=Q3,A3=A3,Q4=Q4,A4=A4,Q5=Q5,A5=A5,Q6=Q6,A6=A6,Q7=Q7,A7=A7,Q8=Q8,A8=A8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV8 INV8 (Q1=Q1,A1=A1,Q2=Q2,A2=A2,Q3=Q3,A3=A3,Q4=Q4,A4=A4,Q5=Q5,A5=A5,Q6=Q6,A6=A6,Q7=Q7,A7=A7,Q8=Q8,A8=A8,VDD=VDD,VSS=VSS);\n"
"end;\n"
"circuit TOP (Q1=Q1,A1=A1,Q2=Q2,A2=A2,Q3=Q3,A3=A3,Q4=Q4,A4=A4,Q5=Q5,A5=A5,Q6=Q6,A6=A6,Q7=Q7,A7=A7,Q8=Q8,A8=A8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV8_WRAP INV8 (Q1=Q1,A1=A1,Q2=Q2,A2=A2,Q3=Q3,A3=A3,Q4=Q4,A4=A4,Q5=Q5,A5=A5,Q6=Q6,A6=A6,Q7=Q7,A7=A7,Q8=Q8,A8=A8,VDD=VDD,VSS=VSS);\n"
"end;\n"
;
db::Netlist nl1, nl2;
prep_nl (nl1, nls1);
prep_nl (nl2, nls2);
NetlistCompareTestLogger logger;
db::NetlistComparer comp (&logger);
bool good = comp.compare (&nl1, &nl2);
std::string txt = logger.text ();
EXPECT_EQ (txt,
"begin_circuit INV INV\n"
"match_nets VDD VDD\n"
"match_nets OUT OUT\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_pins IN IN\n"
"match_pins OUT OUT\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_devices $1 $1\n"
"match_devices $2 $2\n"
"end_circuit INV INV MATCH\n"
"begin_circuit INV8 INV8\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_ambiguous_nets IN1 A1\n"
"match_ambiguous_nets IN2 A2\n"
"match_ambiguous_nets IN3 A3\n"
"match_ambiguous_nets IN4 A4\n"
"match_ambiguous_nets IN5 A5\n"
"match_ambiguous_nets IN6 A6\n"
"match_ambiguous_nets IN7 A7\n"
"match_ambiguous_nets IN8 A8\n"
"match_nets OUT1 Q1\n"
"match_nets OUT2 Q2\n"
"match_nets OUT3 Q3\n"
"match_nets OUT4 Q4\n"
"match_nets OUT5 Q5\n"
"match_nets OUT6 Q6\n"
"match_nets OUT7 Q7\n"
"match_nets OUT8 Q8\n"
"match_pins IN1 A1\n"
"match_pins OUT1 Q1\n"
"match_pins IN2 A2\n"
"match_pins OUT2 Q2\n"
"match_pins IN3 A3\n"
"match_pins OUT3 Q3\n"
"match_pins IN4 A4\n"
"match_pins OUT4 Q4\n"
"match_pins IN5 A5\n"
"match_pins OUT5 Q5\n"
"match_pins IN6 A6\n"
"match_pins OUT6 Q6\n"
"match_pins IN7 A7\n"
"match_pins OUT7 Q7\n"
"match_pins IN8 A8\n"
"match_pins OUT8 Q8\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_subcircuits I1 I1\n"
"match_subcircuits I8 I8\n"
"match_subcircuits I3 I3\n"
"match_subcircuits I7 I7\n"
"match_subcircuits I4 I4\n"
"match_subcircuits I2 I2\n"
"match_subcircuits I6 I6\n"
"match_subcircuits I5 I5\n"
"end_circuit INV8 INV8 MATCH\n"
"begin_circuit INV8_WRAP INV8_WRAP\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets IN8 A8\n"
"match_nets OUT8 Q8\n"
"match_nets IN7 A7\n"
"match_nets OUT7 Q7\n"
"match_nets IN6 A6\n"
"match_nets OUT6 Q6\n"
"match_nets IN5 A5\n"
"match_nets OUT5 Q5\n"
"match_nets IN4 A4\n"
"match_nets OUT4 Q4\n"
"match_nets IN3 A3\n"
"match_nets OUT3 Q3\n"
"match_nets IN2 A2\n"
"match_nets OUT2 Q2\n"
"match_nets IN1 A1\n"
"match_nets OUT1 Q1\n"
"match_pins IN1 A1\n"
"match_pins OUT1 Q1\n"
"match_pins IN2 A2\n"
"match_pins OUT2 Q2\n"
"match_pins IN3 A3\n"
"match_pins OUT3 Q3\n"
"match_pins IN4 A4\n"
"match_pins OUT4 Q4\n"
"match_pins IN5 A5\n"
"match_pins OUT5 Q5\n"
"match_pins IN6 A6\n"
"match_pins OUT6 Q6\n"
"match_pins IN7 A7\n"
"match_pins OUT7 Q7\n"
"match_pins IN8 A8\n"
"match_pins OUT8 Q8\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_subcircuits INV8 INV8\n"
"end_circuit INV8_WRAP INV8_WRAP MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets IN8 A8\n"
"match_nets OUT8 Q8\n"
"match_nets IN7 A7\n"
"match_nets OUT7 Q7\n"
"match_nets IN6 A6\n"
"match_nets OUT6 Q6\n"
"match_nets IN5 A5\n"
"match_nets OUT5 Q5\n"
"match_nets IN4 A4\n"
"match_nets OUT4 Q4\n"
"match_nets IN3 A3\n"
"match_nets OUT3 Q3\n"
"match_nets IN2 A2\n"
"match_nets OUT2 Q2\n"
"match_nets IN1 A1\n"
"match_nets OUT1 Q1\n"
"match_pins IN1 A1\n"
"match_pins OUT1 Q1\n"
"match_pins IN2 A2\n"
"match_pins OUT2 Q2\n"
"match_pins IN3 A3\n"
"match_pins OUT3 Q3\n"
"match_pins IN4 A4\n"
"match_pins OUT4 Q4\n"
"match_pins IN5 A5\n"
"match_pins OUT5 Q5\n"
"match_pins IN6 A6\n"
"match_pins OUT6 Q6\n"
"match_pins IN7 A7\n"
"match_pins OUT7 Q7\n"
"match_pins IN8 A8\n"
"match_pins OUT8 Q8\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_subcircuits INV8 INV8\n"
"end_circuit TOP TOP MATCH"
);
EXPECT_EQ (good, true);
}
TEST(21_BusLikeAmbiguousConnections)
{
// Test test requires a certain depth and tests the backtracking paths.
const char *nls1 =
"circuit INV8 (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
// NOTE: passive nets make the pins ambiguous
"end;\n"
"circuit INV8_WRAP (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV8 INV8 (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
"end;\n"
"circuit TOP (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV8_WRAP INV8 (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
"end;\n"
;
const char *nls2 =
"circuit INV8 (IN1=IN1,OUT1=OUT1,IN2=IN2,OUT2=OUT2,IN3=IN3,OUT3=OUT3,IN4=IN4,OUT4=OUT4,IN5=IN5,OUT5=OUT5,IN6=IN6,OUT6=OUT6,IN7=IN7,OUT7=OUT7,IN8=IN8,OUT8=OUT8,VDD=VDD,VSS=VSS);\n"
// NOTE: passive nets make the pins ambiguous
"end;\n"
"circuit INV8_WRAP (Q1=Q1,A1=A1,Q2=Q2,A2=A2,Q3=Q3,A3=A3,Q4=Q4,A4=A4,Q5=Q5,A5=A5,Q6=Q6,A6=A6,Q7=Q7,A7=A7,Q8=Q8,A8=A8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV8 INV8 (IN1=A1,OUT1=Q1,IN2=A2,OUT2=Q2,IN3=A3,OUT3=Q3,IN4=A4,OUT4=Q4,IN5=A5,OUT5=Q5,IN6=A6,OUT6=Q6,IN7=A7,OUT7=Q7,IN8=A8,OUT8=Q8,VDD=VDD,VSS=VSS);\n"
"end;\n"
"circuit TOP (Q1=Q1,A1=A1,Q2=Q2,A2=A2,Q3=Q3,A3=A3,Q4=Q4,A4=A4,Q5=Q5,A5=A5,Q6=Q6,A6=A6,Q7=Q7,A7=A7,Q8=Q8,A8=A8,VDD=VDD,VSS=VSS);\n"
" subcircuit INV8_WRAP INV8 (Q1=Q1,A1=A1,Q2=Q2,A2=A2,Q3=Q3,A3=A3,Q4=Q4,A4=A4,Q5=Q5,A5=A5,Q6=Q6,A6=A6,Q7=Q7,A7=A7,Q8=Q8,A8=A8,VDD=VDD,VSS=VSS);\n"
"end;\n"
;
db::Netlist nl1, nl2;
prep_nl (nl1, nls1);
prep_nl (nl2, nls2);
NetlistCompareTestLogger logger;
db::NetlistComparer comp (&logger);
bool good = comp.compare (&nl1, &nl2);
std::string txt = logger.text ();
EXPECT_EQ (txt,
"begin_circuit INV8 INV8\n"
"match_nets IN1 IN1\n"
"match_nets IN2 IN2\n"
"match_nets IN3 IN3\n"
"match_nets IN4 IN4\n"
"match_nets IN5 IN5\n"
"match_nets IN6 IN6\n"
"match_nets IN7 IN7\n"
"match_nets IN8 IN8\n"
"match_nets OUT1 OUT1\n"
"match_nets OUT2 OUT2\n"
"match_nets OUT3 OUT3\n"
"match_nets OUT4 OUT4\n"
"match_nets OUT5 OUT5\n"
"match_nets OUT6 OUT6\n"
"match_nets OUT7 OUT7\n"
"match_nets OUT8 OUT8\n"
"match_nets VDD VDD\n"
"match_nets VSS VSS\n"
"match_pins IN1 IN1\n"
"match_pins OUT1 OUT1\n"
"match_pins IN2 IN2\n"
"match_pins OUT2 OUT2\n"
"match_pins IN3 IN3\n"
"match_pins OUT3 OUT3\n"
"match_pins IN4 IN4\n"
"match_pins OUT4 OUT4\n"
"match_pins IN5 IN5\n"
"match_pins OUT5 OUT5\n"
"match_pins IN6 IN6\n"
"match_pins OUT6 OUT6\n"
"match_pins IN7 IN7\n"
"match_pins OUT7 OUT7\n"
"match_pins IN8 IN8\n"
"match_pins OUT8 OUT8\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"end_circuit INV8 INV8 MATCH\n"
"begin_circuit INV8_WRAP INV8_WRAP\n"
"match_ambiguous_nets VDD VDD\n"
"match_ambiguous_nets VSS VSS\n"
"match_ambiguous_nets IN1 A1\n"
"match_ambiguous_nets IN2 A2\n"
"match_ambiguous_nets IN3 A3\n"
"match_ambiguous_nets IN4 A4\n"
"match_ambiguous_nets IN5 A5\n"
"match_ambiguous_nets IN6 A6\n"
"match_ambiguous_nets IN7 A7\n"
"match_ambiguous_nets IN8 A8\n"
"match_ambiguous_nets OUT1 Q1\n"
"match_ambiguous_nets OUT2 Q2\n"
"match_ambiguous_nets OUT3 Q3\n"
"match_ambiguous_nets OUT4 Q4\n"
"match_ambiguous_nets OUT5 Q5\n"
"match_ambiguous_nets OUT6 Q6\n"
"match_ambiguous_nets OUT7 Q7\n"
"match_ambiguous_nets OUT8 Q8\n"
"match_pins IN1 A1\n"
"match_pins OUT1 Q1\n"
"match_pins IN2 A2\n"
"match_pins OUT2 Q2\n"
"match_pins IN3 A3\n"
"match_pins OUT3 Q3\n"
"match_pins IN4 A4\n"
"match_pins OUT4 Q4\n"
"match_pins IN5 A5\n"
"match_pins OUT5 Q5\n"
"match_pins IN6 A6\n"
"match_pins OUT6 Q6\n"
"match_pins IN7 A7\n"
"match_pins OUT7 Q7\n"
"match_pins IN8 A8\n"
"match_pins OUT8 Q8\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_subcircuits INV8 INV8\n"
"end_circuit INV8_WRAP INV8_WRAP MATCH\n"
"begin_circuit TOP TOP\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets IN8 A8\n"
"match_nets OUT8 Q8\n"
"match_nets IN7 A7\n"
"match_nets OUT7 Q7\n"
"match_nets IN6 A6\n"
"match_nets OUT6 Q6\n"
"match_nets IN5 A5\n"
"match_nets OUT5 Q5\n"
"match_nets IN4 A4\n"
"match_nets OUT4 Q4\n"
"match_nets IN3 A3\n"
"match_nets OUT3 Q3\n"
"match_nets IN2 A2\n"
"match_nets OUT2 Q2\n"
"match_nets IN1 A1\n"
"match_nets OUT1 Q1\n"
"match_pins IN1 A1\n"
"match_pins OUT1 Q1\n"
"match_pins IN2 A2\n"
"match_pins OUT2 Q2\n"
"match_pins IN3 A3\n"
"match_pins OUT3 Q3\n"
"match_pins IN4 A4\n"
"match_pins OUT4 Q4\n"
"match_pins IN5 A5\n"
"match_pins OUT5 Q5\n"
"match_pins IN6 A6\n"
"match_pins OUT6 Q6\n"
"match_pins IN7 A7\n"
"match_pins OUT7 Q7\n"
"match_pins IN8 A8\n"
"match_pins OUT8 Q8\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_subcircuits INV8 INV8\n"
"end_circuit TOP TOP MATCH"
);
EXPECT_EQ (good, true);
}

View File

@ -2108,3 +2108,198 @@ TEST(9_StrictDeviceExtraction)
db::compare_layouts (_this, ly, au);
}
TEST(10_DeviceExtractionWithBreakoutCells)
{
db::Layout ly;
db::LayerMap lmap;
unsigned int nwell = define_layer (ly, lmap, 1);
unsigned int active = define_layer (ly, lmap, 2);
unsigned int poly = define_layer (ly, lmap, 3);
unsigned int poly_lbl = define_layer (ly, lmap, 3, 1);
unsigned int diff_cont = define_layer (ly, lmap, 4);
unsigned int poly_cont = define_layer (ly, lmap, 5);
unsigned int metal1 = define_layer (ly, lmap, 6);
unsigned int metal1_lbl = define_layer (ly, lmap, 6, 1);
unsigned int via1 = define_layer (ly, lmap, 7);
unsigned int metal2 = define_layer (ly, lmap, 8);
unsigned int metal2_lbl = define_layer (ly, lmap, 8, 1);
{
db::LoadLayoutOptions options;
options.get_options<db::CommonReaderOptions> ().layer_map = lmap;
options.get_options<db::CommonReaderOptions> ().create_other_layers = false;
std::string fn (tl::testsrc ());
fn = tl::combine_path (fn, "testdata");
fn = tl::combine_path (fn, "algo");
fn = tl::combine_path (fn, "device_extract_l10.gds");
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly, options);
}
db::Cell &tc = ly.cell (*ly.begin_top_down ());
db::DeepShapeStore dss;
dss.set_text_enlargement (1);
dss.set_text_property_name (tl::Variant ("LABEL"));
// original layers
db::Region rnwell (db::RecursiveShapeIterator (ly, tc, nwell), dss);
db::Region ractive (db::RecursiveShapeIterator (ly, tc, active), dss);
db::Region rpoly (db::RecursiveShapeIterator (ly, tc, poly), dss);
db::Region rpoly_lbl (db::RecursiveShapeIterator (ly, tc, poly_lbl), dss);
db::Region rdiff_cont (db::RecursiveShapeIterator (ly, tc, diff_cont), dss);
db::Region rpoly_cont (db::RecursiveShapeIterator (ly, tc, poly_cont), dss);
db::Region rmetal1 (db::RecursiveShapeIterator (ly, tc, metal1), dss);
db::Region rmetal1_lbl (db::RecursiveShapeIterator (ly, tc, metal1_lbl), dss);
db::Region rvia1 (db::RecursiveShapeIterator (ly, tc, via1), dss);
db::Region rmetal2 (db::RecursiveShapeIterator (ly, tc, metal2), dss);
db::Region rmetal2_lbl (db::RecursiveShapeIterator (ly, tc, metal2_lbl), dss);
// derived regions
db::Region rpactive = ractive & rnwell;
db::Region rpgate = rpactive & rpoly;
db::Region rpsd = rpactive - rpgate;
db::Region rnactive = ractive - rnwell;
db::Region rngate = rnactive & rpoly;
db::Region rnsd = rnactive - rngate;
// return the computed layers into the original layout and write it for debugging purposes
unsigned int lpgate = ly.insert_layer (db::LayerProperties (20, 0)); // 20/0 -> P Gate
unsigned int lngate = ly.insert_layer (db::LayerProperties (21, 0)); // 21/0 -> N Gate
unsigned int lpdiff = ly.insert_layer (db::LayerProperties (22, 0)); // 22/0 -> P Diffusion
unsigned int lndiff = ly.insert_layer (db::LayerProperties (23, 0)); // 23/0 -> N Diffusion
rpgate.insert_into (&ly, tc.cell_index (), lpgate);
rngate.insert_into (&ly, tc.cell_index (), lngate);
rpsd.insert_into (&ly, tc.cell_index (), lpdiff);
rnsd.insert_into (&ly, tc.cell_index (), lndiff);
// perform the extraction
db::Netlist nl;
db::hier_clusters<db::PolygonRef> cl;
db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS");
db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS");
db::NetlistDeviceExtractor::input_layers dl;
dss.push_state ();
std::set<db::cell_index_type> boc;
boc.insert (dss.layout (0).cell_by_name ("INV").second);
dss.set_breakout_cells (0, boc);
dl["SD"] = &rpsd;
dl["G"] = &rpgate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
pmos_ex.extract (dss, 0, dl, nl, cl);
dl["SD"] = &rnsd;
dl["G"] = &rngate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
nmos_ex.extract (dss, 0, dl, nl, cl);
dss.pop_state ();
// perform the net extraction
db::NetlistExtractor net_ex;
db::Connectivity conn;
// Intra-layer
conn.connect (rpsd);
conn.connect (rnsd);
conn.connect (rpoly);
conn.connect (rdiff_cont);
conn.connect (rpoly_cont);
conn.connect (rmetal1);
conn.connect (rvia1);
conn.connect (rmetal2);
// Inter-layer
conn.connect (rpsd, rdiff_cont);
conn.connect (rnsd, rdiff_cont);
conn.connect (rpoly, rpoly_cont);
conn.connect (rpoly_cont, rmetal1);
conn.connect (rdiff_cont, rmetal1);
conn.connect (rmetal1, rvia1);
conn.connect (rvia1, rmetal2);
conn.connect (rpoly, rpoly_lbl); // attaches labels
conn.connect (rmetal1, rmetal1_lbl); // attaches labels
conn.connect (rmetal2, rmetal2_lbl); // attaches labels
// extract the nets
net_ex.extract_nets (dss, 0, conn, nl, cl);
// debug layers produced for nets
// 202/0 -> Active
// 203/0 -> Poly
// 204/0 -> Diffusion contacts
// 205/0 -> Poly contacts
// 206/0 -> Metal1
// 207/0 -> Via1
// 208/0 -> Metal2
// 210/0 -> N source/drain
// 211/0 -> P source/drain
std::map<unsigned int, unsigned int> dump_map;
dump_map [layer_of (rpsd) ] = ly.insert_layer (db::LayerProperties (210, 0));
dump_map [layer_of (rnsd) ] = ly.insert_layer (db::LayerProperties (211, 0));
dump_map [layer_of (rpoly) ] = ly.insert_layer (db::LayerProperties (203, 0));
dump_map [layer_of (rdiff_cont)] = ly.insert_layer (db::LayerProperties (204, 0));
dump_map [layer_of (rpoly_cont)] = ly.insert_layer (db::LayerProperties (205, 0));
dump_map [layer_of (rmetal1) ] = ly.insert_layer (db::LayerProperties (206, 0));
dump_map [layer_of (rvia1) ] = ly.insert_layer (db::LayerProperties (207, 0));
dump_map [layer_of (rmetal2) ] = ly.insert_layer (db::LayerProperties (208, 0));
// write nets to layout
db::CellMapping cm = dss.cell_mapping_to_original (0, &ly, tc.cell_index ());
dump_nets_to_layout (nl, cl, ly, dump_map, cm);
std::string nl_au_string =
"circuit INVCHAIN ();"
" subcircuit INV3 $1 ($1=$9,$2=$7,$3=$8,$4=IN,$5=$9,$6=$6,$7=$2,$8=$6,$9=$4,$10=$3,$11=VDD,$12=VSS);"
" subcircuit INV2 $2 ($1=$8,$2=$11,$3=$9,$4=$10,$5=$8,$6=$11,$7=$3,$8=OUT,$9=$3,$10=OUT,$11=$6,$12=$5,$13=VDD,$14=VSS);"
" subcircuit INV $3 ($1=VSS,$2=VDD,$3=$11,$4=OUT,$5=$5,$6=$5,$7=$10,$8=$10);"
"end;"
"circuit INV2 ($1=$I16,$2=$I15,$3=$I14,$4=$I13,$5=$I12,$6=$I11,$7=$I10,$8=$I9,$9=$I8,$10=$I7,$11=$I6,$12=$I5,$13=$I4,$14=$I2);"
" subcircuit INV $1 ($1=$I2,$2=$I4,$3=$I14,$4=$I6,$5=$I8,$6=$I10,$7=$I16,$8=$I12);"
" subcircuit INV $2 ($1=$I2,$2=$I4,$3=$I13,$4=$I5,$5=$I7,$6=$I9,$7=$I15,$8=$I11);"
"end;"
"circuit INV ($1=$1,$2=$2,$3=$3,$4=$4,$5=$5,$6=$9,$7=$I8,$8=$I7);"
" device PMOS $1 (S=$4,G=$3,D=$2) (L=0.25,W=0.95,AS=0.79325,AD=0.26125,PS=3.57,PD=1.5);"
" device PMOS $2 (S=$2,G=$I8,D=$5) (L=0.25,W=0.95,AS=0.26125,AD=0.03325,PS=1.5,PD=1.97);"
" device NMOS $3 (S=$4,G=$3,D=$1) (L=0.25,W=0.95,AS=0.79325,AD=0.26125,PS=3.57,PD=1.5);"
" device NMOS $4 (S=$1,G=$I7,D=$9) (L=0.25,W=0.95,AS=0.26125,AD=0.03325,PS=1.5,PD=1.97);"
" subcircuit TRANS $1 ($1=$4,$2=$1,$3=$3);"
" subcircuit TRANS $2 ($1=$4,$2=$2,$3=$3);"
"end;"
"circuit TRANS ($1=$1,$2=$2,$3=$3);"
"end;"
"circuit INV3 ($1=$I17,$2=$I16,$3=$I15,$4=$I14,$5=$I12,$6=$I11,$7=$I9,$8=$I8,$9=$I7,$10=$I5,$11=$I4,$12=$I2);"
" subcircuit INV $1 ($1=$I2,$2=$I4,$3=$I15,$4=$I5,$5=$I8,$6=$I11,$7=$I17,$8=$I12);"
" subcircuit INV $2 ($1=$I2,$2=$I4,$3=$I14,$4=$I9,$5=$I7,$6=$I7,$7=$I16,$8=$I16);"
" subcircuit INV $3 ($1=$I2,$2=$I4,$3=$I16,$4=$I7,$5=$I9,$6=$I9,$7=$I14,$8=$I14);"
"end;"
;
// compare netlist as string
CHECKPOINT ();
db::compare_netlist (_this, nl, nl_au_string);
// compare the collected test data
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "device_extract_au10.gds");
db::compare_layouts (_this, ly, au);
}

View File

@ -752,6 +752,7 @@ TEST(6_Net)
EXPECT_EQ (n.pin_count (), size_t (0));
EXPECT_EQ (n.terminal_count (), size_t (0));
EXPECT_EQ (n.is_floating (), true);
EXPECT_EQ (n.is_passive (), true);
EXPECT_EQ (n.is_internal (), false);
}
@ -781,6 +782,7 @@ TEST(7_NetTerminalsEditing)
EXPECT_EQ (n1->terminal_count (), size_t (1));
EXPECT_EQ (n1->pin_count (), size_t (0));
EXPECT_EQ (n1->is_floating (), false);
EXPECT_EQ (n1->is_passive (), false);
EXPECT_EQ (n1->is_internal (), false);
d2->connect_terminal (1, n1);
@ -789,6 +791,7 @@ TEST(7_NetTerminalsEditing)
EXPECT_EQ (n1->terminal_count (), size_t (2));
EXPECT_EQ (n1->pin_count (), size_t (0));
EXPECT_EQ (n1->is_floating (), false);
EXPECT_EQ (n1->is_passive (), false);
EXPECT_EQ (n1->is_internal (), true);
EXPECT_EQ (d1->net_for_terminal (0), n1);
@ -871,7 +874,8 @@ TEST(8_NetSubCircuitsEditing)
EXPECT_EQ (n1->terminal_count (), size_t (0));
EXPECT_EQ (n1->pin_count (), size_t (1));
EXPECT_EQ (n1->is_floating (), true);
EXPECT_EQ (n1->is_floating (), false);
EXPECT_EQ (n1->is_passive (), true);
EXPECT_EQ (n1->is_internal (), false);
EXPECT_NE (n1->pin_count (), size_t (0));
@ -886,6 +890,7 @@ TEST(8_NetSubCircuitsEditing)
EXPECT_EQ (n1->pin_count (), size_t (1));
EXPECT_EQ (n1->subcircuit_pin_count (), size_t (1));
EXPECT_EQ (n1->is_floating (), false);
EXPECT_EQ (n1->is_passive (), false);
EXPECT_EQ (n1->is_internal (), false);
sc2->connect_pin (1, n1);
@ -1380,7 +1385,7 @@ TEST(22_BlankCircuit)
nl2.purge ();
EXPECT_EQ (nl2.to_string (),
"circuit RINGO (IN=(null),OSC=OSC,VSS=VSS,VDD=VDD);\n"
"circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=VDD);\n"
" subcircuit INV2 INV2_SC1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);\n"
" subcircuit INV2 INV2_SC2 (IN=FB,$2=(null),OUT=$I8,$4=VSS,$5=VDD);\n"
"end;\n"

View File

@ -1120,6 +1120,108 @@ module DRC
@def_source = layout.clip(*args)
nil
end
# %DRC%
# @name cheat
# @brief Hierarchy cheats
# @synopsis cheat(args) { block }
#
# Hierarchy cheats can be used in deep mode to shortcut hierarchy evaluation
# for certain cells and consider their local configuration only.
# Cheats are useful for example when dealing with memory arrays. Often
# such arrays are build from unit cells and those often overlap with their
# neighbors. Now, if the hierarchical engine encounters such a situation, it
# will first analyse all these interactions (which can be expensive) and then
# it may come to the conclusion that boundary instances need to be handled
# differently than inside instances. This in turn might lead to propagation of
# shapes and in an LVS context to device externalisation: because some devices
# might have different parameters for boundary cells than for inside cells, the
# device instances can no longer be kept inside the unit cell. Specifically for
# memory arrays, this is not desired as eventually this leads to flattening
# of the whole array.
#
# The solution is to cheat: provided the unit cell is fully fledged and neighbors
# do not disturb the unit cell's configuration in critical ways, the unit cell
# can be treated as being isolated and results are put together in the usual way.
#
# Cheats can be applied on layout operations - specifically booleans - and device
# extraction operations. Cheats are only effective in \deep mode.
#
# For booleans, a cheat means that the cheating cell's boolean results are computed
# locally and are combined afterwards. A cheat is introduced this way:
#
# @code
# deep
#
# l1 = input(1, 0)
# l2 = input(2, 0)
#
# # usual booleans
# l1and2 = l1 & l2
#
# # will compute "UNIT_CELL" isolated and everything else in normal hierarchical mode:
# l1minus2 = cheat("UNIT_CELL) { l1 - l2 }
# @/code
#
# The cheat block can also be wrapped in do .. end statements and can return multiple
# layer objects:
#
# @code
# deep
#
# l1 = input(1, 0)
# l2 = input(2, 0)
#
# # computes both AND and NOT of l1 and l2 with cheating for "UNIT_CELL"
# l1and2, l1minus2 = cheat("UNIT_CELL) do
# [ l1 & l2, l1 - l2 ]
# end
# @/code
#
# (Technically, the cheat code block is a Ruby Proc and cannot create variables
# outside it's scope. Hence the results of this code block have to be passed
# through the "cheat" method).
#
# To apply cheats for device extraction, use the following scheme:
#
# @code
# deep
#
# poly = input(1, 0)
# active = input(2, 0)
#
# sd = active - poly
# gate = active & poly
#
# # device extraction with cheating for "UNIT_CELL":
# cheat("UNIT_CELL") do
# extract_devices(mos3("NMOS"), { "SD" => sd, "G" => gate, "tS" => sd, "tD" => sd, "tG" => poly }
# end
# @/code
#
# The argument to the cheat method is a list of cell name pattern (glob-style
# pattern). For example:
#
# @code
# cheat("UNIT_CELL*") { ... }
# cheat("UNIT_CELL1", "UNIT_CELL2") { ... }
# cheat("UNIT_CELL{1,2}") { ... }
# @/code
#
# For LVS applications, it's usually sufficient to cheat in the device extraction step.
# Cheats have been introduced in version 0.26.1.
def cheat(*args, &block)
if _dss
_dss.push_state
args.flatten.each { |a| _dss.add_breakout_cells(a.to_s) }
ret = block.call
_dss.pop_state
else
ret = block.call
end
ret
end
# make some DRCLayer methods available as functions
# for the engine
@ -1461,22 +1563,22 @@ CODE
end
# save the netlist if required
if @target_netlist_file && @netter && @netter.l2n_data
if @target_netlist_file && @netter && @netter._l2n_data
writer = @target_netlist_format || RBA::NetlistSpiceWriter::new
netlist_file = _make_path(@target_netlist_file)
info("Writing netlist: #{netlist_file} ..")
self.netlist.write(netlist_file, writer, @target_netlist_comment || "")
netlist.write(netlist_file, writer, @target_netlist_comment || "")
end
# save the netlist database if requested
if @output_l2ndb_file && @netter && @netter.l2n_data
if @output_l2ndb_file && @netter && @netter._l2n_data
l2ndb_file = _make_path(@output_l2ndb_file)
info("Writing netlist database: #{l2ndb_file} ..")
@netter.l2n_data.write_l2n(l2ndb_file, !@output_l2ndb_long)
@netter._l2n_data.write_l2n(l2ndb_file, !@output_l2ndb_long)
end
@ -1484,7 +1586,7 @@ CODE
_before_cleanup
# show the data in the browser
if view && @show_l2ndb && @netter && @netter.l2n_data
if view && @show_l2ndb && @netter && @netter._l2n_data
# NOTE: to prevent the netter destroying the database, we need to take it
l2ndb = _take_data

View File

@ -383,6 +383,10 @@ module DRC
l2ndb
end
def _l2n_data
@netlisted && self.l2n_data
end
private
def cleanup

View File

@ -92,6 +92,98 @@ cell("MACRO")
l1 = input(1, 0)
</pre>
</p>
<h2>"cheat" - Hierarchy cheats</h2>
<keyword name="cheat"/>
<a name="cheat"/><p>Usage:</p>
<ul>
<li><tt>cheat(args) { block }</tt></li>
</ul>
<p>
Hierarchy cheats can be used in deep mode to shortcut hierarchy evaluation
for certain cells and consider their local configuration only.
Cheats are useful for example when dealing with memory arrays. Often
such arrays are build from unit cells and those often overlap with their
neighbors. Now, if the hierarchical engine encounters such a situation, it
will first analyse all these interactions (which can be expensive) and then
it may come to the conclusion that boundary instances need to be handled
differently than inside instances. This in turn might lead to propagation of
shapes and in an LVS context to device externalisation: because some devices
might have different parameters for boundary cells than for inside cells, the
device instances can no longer be kept inside the unit cell. Specifically for
memory arrays, this is not desired as eventually this leads to flattening
of the whole array.
</p><p>
The solution is to cheat: provided the unit cell is fully fledged and neighbors
do not disturb the unit cell's configuration in critical ways, the unit cell
can be treated as being isolated and results are put together in the usual way.
</p><p>
Cheats can be applied on layout operations - specifically booleans - and device
extraction operations. Cheats are only effective in <a href="#deep">deep</a> mode.
</p><p>
For booleans, a cheat means that the cheating cell's boolean results are computed
locally and are combined afterwards. A cheat is introduced this way:
</p><p>
<pre>
deep
l1 = input(1, 0)
l2 = input(2, 0)
# usual booleans
l1and2 = l1 &amp; l2
# will compute "UNIT_CELL" isolated and everything else in normal hierarchical mode:
l1minus2 = cheat("UNIT_CELL) { l1 - l2 }
</pre>
</p><p>
The cheat block can also be wrapped in do .. end statements and can return multiple
layer objects:
</p><p>
<pre>
deep
l1 = input(1, 0)
l2 = input(2, 0)
# computes both AND and NOT of l1 and l2 with cheating for "UNIT_CELL"
l1and2, l1minus2 = cheat("UNIT_CELL) do
[ l1 &amp; l2, l1 - l2 ]
end
</pre>
</p><p>
(Technically, the check code block is a Ruby Proc and cannot create variables
outside it's scope. Hence the results of this code block have to be passed
through the "cheat" method).
</p><p>
To apply cheats for device extraction, use the following scheme:
</p><p>
<pre>
deep
poly = input(1, 0)
active = input(2, 0)
sd = active - poly
gate = active &amp; poly
# device extraction with cheating for "UNIT_CELL":
cheat("UNIT_CELL") do
extract_devices(mos3("NMOS"), { "SD" =&gt; sd, "G" =&gt; gate, "tS" =&gt; sd, "tD" =&gt; sd, "tG" =&gt; poly }
end
</pre>
</p><p>
The argument to the cheat method is a list of cell name pattern (glob-style
pattern). For example:
</p><p>
<pre>
cheat("UNIT_CELL*") { ... }
cheat("UNIT_CELL1", "UNIT_CELL2") { ... }
cheat("UNIT_CELL{1,2}") { ... }
</pre>
</p><p>
For LVS applications, it's usually sufficient to cheat in the device extraction step.
Cheats have been introduced in version 0.26.1.
</p>
<h2>"clear_connections" - Clears all connections stored so far</h2>
<keyword name="clear_connections"/>
<a name="clear_connections"/><p>Usage:</p>

View File

@ -735,7 +735,7 @@ This method is available for edge layers. The argument must be a polygon layer.
</ul>
<p>
This method selects all shapes or regions from self which touch or overlap shapes from the other
region. If self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
region. Unless self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
otherwise individual shapes are selected.
It returns a new layer containing the selected shapes. A version which modifies self
is <a href="#select_interacting">select_interacting</a>.
@ -1085,7 +1085,7 @@ The following image shows the effect of the "not_inside" method (input1: red, in
</ul>
<p>
This method selects all shapes or regions from self which do not touch or overlap shapes from the other
region. If self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
region. Unless self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
otherwise individual shapes are selected.
It returns a new layer containing the selected shapes. A version which modifies self
is <a href="#select_not_interacting">select_not_interacting</a>.
@ -1134,7 +1134,7 @@ The following image shows the effect of the "not_outside" method (input1: red, i
</ul>
<p>
This method selects all shapes or regions from self which do not overlap shapes from the other
region. If self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
region. Unless self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
otherwise individual shapes are selected.
</p><p>
The "not_overlapping" method is equivalent to the <a href="#outside">outside</a> method. It is provided
@ -1322,7 +1322,7 @@ The following images show the effect of the overlap check (layer1: red, layer2:
</ul>
<p>
This method selects all shapes or regions from self which overlap shapes from the other
region. If self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
region. Unless self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
otherwise individual shapes are selected.
It returns a new layer containing the selected shapes. A version which modifies self
is <a href="#select_overlapping">select_overlapping</a>.
@ -1372,6 +1372,60 @@ parameter is 0, special edge pairs with an area of 0 will be dropped.
<ul>
<li><tt>layer.polygons?</tt></li>
</ul>
<h2>"pull_inside" - Selects shapes or regions of other which are inside polygons from the this region</h2>
<keyword name="pull_inside"/>
<a name="pull_inside"/><p>Usage:</p>
<ul>
<li><tt>layer.pull_inside(other)</tt></li>
</ul>
<p>
This method selects all shapes or regions from other which are inside polygons from this
region. Unless other is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from other,
otherwise individual shapes are selected.
</p><p>
The functionality is similar to select_inside, but chosing shapes from other rather
than from self. Because in deep mode the hierarchy reference comes from self, this method
provides a way to pull shapes from other to the hierarchy to self.
</p><p>
This method is available for polygon layers. Other needs to be a polygon layer too.
</p>
<h2>"pull_interacting" - Selects shapes or edges of other which touch or overlap shapes from the this region</h2>
<keyword name="pull_interacting"/>
<a name="pull_interacting"/><p>Usage:</p>
<ul>
<li><tt>layer.pull_interacting(other)</tt></li>
</ul>
<p>
This method selects all shapes or regions from other which touch or overlap shapes from this
region. Unless other is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from other,
otherwise individual shapes are selected.
</p><p>
The functionality is similar to select_interacting, but chosing shapes from other rather
than from self. Because in deep mode the hierarchy reference comes from self, this method
provides a way to pull shapes from other to the hierarchy to self.
</p><p>
This method will neither modify self nor other.
</p><p>
This method is available for polygon layers. Other can be an edge or polygon layer.
Edges or polygons can be selected with respect to polygons of self.
</p>
<h2>"pull_overlapping" - Selects shapes or regions of other which overlap shapes from the this region</h2>
<keyword name="pull_overlapping"/>
<a name="pull_overlapping"/><p>Usage:</p>
<ul>
<li><tt>layer.pull_overlapping(other)</tt></li>
</ul>
<p>
This method selects all shapes or regions from other which overlap shapes from this
region. Unless other is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from other,
otherwise individual shapes are selected.
</p><p>
The functionality is similar to select_overlapping, but chosing shapes from other rather
than from self. Because in deep mode the hierarchy reference comes from self, this method
provides a way to pull shapes from other to the hierarchy to self.
</p><p>
This method is available for polygon layers. Other needs to be a polygon layer too.
</p>
<h2>"raw" - Marks a layer as raw</h2>
<keyword name="raw"/>
<a name="raw"/><p>Usage:</p>
@ -1562,7 +1616,7 @@ This method is available for polygon layers.
</ul>
<p>
This method selects all shapes or regions from self which touch or overlap shapes from the other
region. If self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
region. Unless self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
otherwise individual shapes are selected.
It modifies self to contain the selected shapes. A version which does not modify self
is <a href="#interacting">interacting</a>.
@ -1595,7 +1649,7 @@ This method is available for polygon layers.
</ul>
<p>
This method selects all shapes or regions from self which do not touch or overlap shapes from the other
region. If self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
region. Unless self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
otherwise individual shapes are selected.
It modifies self to contain the selected shapes. A version which does not modify self
is <a href="#not_interacting">not_interacting</a>.
@ -1628,7 +1682,7 @@ This method is available for polygon layers.
</ul>
<p>
This method selects all shapes or regions from self which do not overlap shapes from the other
region. If self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
region. Unless self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
otherwise individual shapes are selected.
It modifies self to contain the selected shapes. A version which does not modify self
is <a href="#not_overlapping">not_overlapping</a>.
@ -1661,7 +1715,7 @@ This method is available for polygon layers.
</ul>
<p>
This method selects all shapes or regions from self which overlap shapes from the other
region. If self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
region. Unless self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
otherwise individual shapes are selected.
It modifies self to contain the selected shapes. A version which does not modify self
is <a href="#overlapping">overlapping</a>.

View File

@ -43,11 +43,11 @@ module LVS
def _before_cleanup
# save the netlist database if requested
if @output_lvsdb_file && @netter && @netter.lvs_data && @netter.lvs_data.xref
if @output_lvsdb_file && @netter && @netter._lvs_data && @netter._lvs_data.xref
lvsdb_file = _make_path(@output_lvsdb_file)
info("Writing LVS database: #{lvsdb_file} ..")
@netter.lvs_data.write(lvsdb_file, !@output_lvsdb_long)
@netter._lvs_data.write(lvsdb_file, !@output_lvsdb_long)
end

View File

@ -48,6 +48,7 @@ module LVS
def initialize(engine)
super
@comparer_config = []
end
def _make_data
@ -65,7 +66,6 @@ module LVS
@lvs.generator = @engine._generator
@l2n = @lvs
@comparer = RBA::NetlistComparer::new
end
@ -94,6 +94,10 @@ module LVS
data
end
def _lvs_data
_l2n_data && @lvs
end
# %LVS%
# @name align
# @brief Aligns the extracted netlist vs. the schematic
@ -120,7 +124,9 @@ module LVS
nl = _ensure_two_netlists
unmatched_a = @comparer.unmatched_circuits_a(*nl)
comparer = self._comparer
unmatched_a = comparer.unmatched_circuits_a(*nl)
# check whether we're about to flatten away the internal top cell - that's bad
top_cell = l2n_data.internal_top_cell.name
@ -131,14 +137,15 @@ module LVS
# flatten layout cells for which there is no corresponding schematic circuit
unmatched_a.each do |c|
@engine.info("Flatten layout cell (no schematic): #{c.name}")
nl[0].flatten_circuit(c)
end
nl[0].flatten_circuits(unmatched_a)
# flatten schematic circuits for which there is no corresponding layout cell
@comparer.unmatched_circuits_b(*nl).each do |c|
unmatched_b = comparer.unmatched_circuits_b(*nl)
unmatched_b.each do |c|
@engine.info("Flatten schematic circuit (no layout): #{c.name}")
nl[1].flatten_circuit(c)
end
nl[1].flatten_circuits(unmatched_b)
end
@ -161,7 +168,20 @@ module LVS
nl = _ensure_two_netlists
lvs_data.reference = nl[1]
lvs_data.compare(@comparer)
lvs_data.compare(self._comparer)
end
def _comparer
comparer = RBA::NetlistComparer::new
# execute the configuration commands
@comparer_config.each do |cc|
cc.call(comparer)
end
return comparer
end
@ -217,6 +237,12 @@ module LVS
n.is_a?(String) || n.is_a?(RBA::Net) || raise("Net arguments of 'same_nets' must be strings or Net objects")
end
@comparer_config << lambda { |comparer| self._same_nets(comparer, ca, a, cb, b) }
end
def _same_nets(comparer, ca, a, cb, b)
( nl_a, nl_b ) = _ensure_two_netlists
if ca.is_a?(String)
@ -234,19 +260,19 @@ module LVS
if circuit_a && circuit_b
if a.is_a?(String)
net_a = circuit_a.net_by_name(a) || raise("Not a valid net name in extracted netlist: #{a} (for circuit #{circuit_a})")
net_a = circuit_a.net_by_name(a) || raise("Not a valid net name in extracted netlist in 'same_nets': #{a} (for circuit #{circuit_a})")
else
net_a = a
end
if b.is_a?(String)
net_b = circuit_b.net_by_name(b) || raise("Not a valid net name in extracted netlist: #{b} (for circuit #{circuit_b})")
net_b = circuit_b.net_by_name(b) || raise("Not a valid net name in extracted netlist in 'same_nets': #{b} (for circuit #{circuit_b})")
else
net_b = b
end
if net_a && net_b
@comparer.same_nets(net_a, net_b)
comparer.same_nets(net_a, net_b)
end
end
@ -271,13 +297,19 @@ module LVS
a.is_a?(String) || a == nil || b.is_a?(String) || b == nil || raise("Both arguments of 'same_circuits' need to be strings or nil")
@comparer_config << lambda { |comparer| self._same_circuits(comparer, a, b) }
end
def _same_circuits(comparer, a, b)
( nl_a, nl_b ) = _ensure_two_netlists
circuit_a = a && nl_a.circuit_by_name(a)
circuit_b = b && nl_b.circuit_by_name(b)
if circuit_a && circuit_b
@comparer.same_circuits(circuit_a, circuit_b)
comparer.same_circuits(circuit_a, circuit_b)
end
end
@ -301,15 +333,21 @@ module LVS
a.is_a?(String) || a == nil || b.is_a?(String) || b == nil || raise("Both arguments of 'same_device_classes' need to be strings or nil")
@comparer_config << lambda { |comparer| self._same_device_classes(comparer, a, b) }
end
def _same_device_classes(comparer, a, b)
( nl_a, nl_b ) = _ensure_two_netlists
dc_a = a && (nl_a.device_class_by_name(a) || raise("Not a valid device class in extracted netlist: #{a}"))
dc_a = a && (nl_a.device_class_by_name(a) || raise("Not a valid device class in extracted netlist in 'same_device_class': #{a}"))
dc_b = b && nl_b.device_class_by_name(b)
# NOTE: a device class is allowed to be missing in the reference netlist because the
# device may simply not be used there.
if dc_b
@comparer.same_device_classes(dc_a, dc_b)
comparer.same_device_classes(dc_a, dc_b)
end
end
@ -347,6 +385,12 @@ module LVS
raise("All pin arguments of 'equivalent_pins' need to be strings or numbers")
end
@comparer_config << lambda { |comparer| self._equivalent_pins(comparer, circuit, *pins) }
end
def _equivalent_pins(comparer, circuit, *pins)
( nl_a, nl_b ) = _ensure_two_netlists
circuit_b = nl_b.circuit_by_name(circuit)
@ -357,14 +401,14 @@ module LVS
pin_ids_b = pins.collect do |p|
if p.is_a?(String)
pin = circuit_b.pin_by_name(p) || raise("Not a valid pin name in circuit '#{circuit}': #{p}")
pin = circuit_b.pin_by_name(p) || raise("Not a valid pin name in circuit '#{circuit}' in 'equivalent_pins': #{p}")
else
pin = pins_by_index[p.to_i] || raise("Not a valid pin index in circuit '#{circuit}': #{p}")
pin = pins_by_index[p.to_i] || raise("Not a valid pin index in circuit '#{circuit}' in 'equivalent_pins': #{p}")
end
pin.id
end
@comparer.equivalent_pins(circuit_b, pin_ids_b)
comparer.equivalent_pins(circuit_b, pin_ids_b)
end
@ -428,8 +472,8 @@ module LVS
# with a capacitance values below the given threshold (in Farad).
def min_caps(value)
lvs_data
@comparer.min_capacitance = value.to_f
v = value.to_f
@comparer_config << lambda { |comparer| comparer.min_capacitance = v }
end
# %LVS%
@ -440,8 +484,8 @@ module LVS
# with a resistance value above the given threshold (in Farad).
def max_res(value)
lvs_data
@comparer.max_resistance = value.to_f
v = value.to_f
@comparer_config << lambda { |comparer| comparer.max_resistance = v }
end
# %LVS%
@ -459,8 +503,8 @@ module LVS
# as the seeds for this deduction path. The default value is 8.
def max_depth(value)
lvs_data
@comparer.max_depth = value.to_i
v = value.to_i
@comparer_config << lambda { |comparer| comparer.max_depth = v }
end
# @name max_branch_complexity
@ -480,8 +524,8 @@ module LVS
# complexity.
def max_branch_complexity(value)
lvs_data
@comparer.max_branch_complexity = value.to_i
v = value.to_i
@comparer_config << lambda { |comparer| comparer.max_branch_complexity = v }
end
end

View File

@ -154,3 +154,14 @@ TEST(16_floating)
{
run_test (_this, "floating", "floating.gds", false, "TOP");
}
TEST(17_layout_variants)
{
run_test (_this, "ringo_layout_var", "ringo_layout_var.gds");
}
TEST(18_cheats)
{
run_test (_this, "invchain_cheat", "invchain_for_cheat.gds");
}

View File

@ -238,6 +238,38 @@ private:
GlobPatternString &operator= (const GlobPatternString &);
};
class GlobPatternEmpty
: public GlobPatternOp
{
public:
GlobPatternEmpty ()
: GlobPatternOp ()
{
// .. nothing yet ..
}
virtual GlobPatternOp *clone () const
{
GlobPatternEmpty *op = new GlobPatternEmpty ();
init_clone (op);
return op;
}
virtual bool is_const () const
{
return next () == 0;
}
virtual bool match (const char *s, std::vector<std::string> *e) const
{
return GlobPatternOp::match (s, e);
}
private:
GlobPatternEmpty (const GlobPatternEmpty &);
GlobPatternEmpty &operator= (const GlobPatternString &);
};
class GlobPatternPass
: public GlobPatternOp
{
@ -602,6 +634,8 @@ compile_emit_alt (GlobPatternOp *&op_head, GlobPatternOp *&op, const char *&p, b
GlobPatternOp *alt = compile (p, false, cs, false, true);
if (alt) {
alt_op->add_choice (alt);
} else {
alt_op->add_choice (new GlobPatternEmpty ());
}
if (*p == ',') {
++p;

View File

@ -163,6 +163,7 @@ TEST(6)
EXPECT_EQ (a.match ("abcg"), true);
EXPECT_EQ (a.match ("adg"), true);
EXPECT_EQ (a.match ("ad"), false);
EXPECT_EQ (a.match ("ag"), false);
EXPECT_EQ (a.match ("abch"), false);
EXPECT_EQ (a.match ("adh"), false);
@ -173,11 +174,33 @@ TEST(6)
EXPECT_EQ (aa.match ("abcg"), true);
EXPECT_EQ (aa.match ("adg"), true);
EXPECT_EQ (aa.match ("ad"), false);
EXPECT_EQ (aa.match ("ag"), false);
EXPECT_EQ (aa.match ("abch"), false);
EXPECT_EQ (aa.match ("adh"), false);
EXPECT_EQ (aa.match ("ah"), false);
a = tl::GlobPattern ("a{,d}g");
EXPECT_EQ (a.match ("abcg"), false);
EXPECT_EQ (a.match ("ad"), false);
EXPECT_EQ (a.match ("adg"), true);
EXPECT_EQ (a.match ("ag"), true);
EXPECT_EQ (a.match ("a"), false);
EXPECT_EQ (a.match ("abch"), false);
EXPECT_EQ (a.match ("adh"), false);
EXPECT_EQ (a.match ("ah"), false);
a = tl::GlobPattern ("a{,d}");
EXPECT_EQ (a.match ("abcg"), false);
EXPECT_EQ (a.match ("ad"), true);
EXPECT_EQ (a.match ("adg"), false);
EXPECT_EQ (a.match ("ag"), false);
EXPECT_EQ (a.match ("a"), true);
EXPECT_EQ (a.match ("abch"), false);
EXPECT_EQ (a.match ("adh"), false);
EXPECT_EQ (a.match ("ah"), false);
}
TEST(7)

BIN
testdata/algo/deep_region_au26.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_l26.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/device_extract_au10.gds.1 vendored Normal file

Binary file not shown.

BIN
testdata/algo/device_extract_au10.gds.2 vendored Normal file

Binary file not shown.

BIN
testdata/algo/device_extract_au10.gds.3 vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
testdata/algo/device_extract_l10.gds vendored Normal file

Binary file not shown.

Binary file not shown.

View File

@ -270,6 +270,12 @@ circuit(INV2PAIR
rect(diff_cont (-220 180) (220 220))
)
net(4
rect(diff_cont (2390 3690) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -2620) (220 220))
rect(diff_cont (-220 -620) (220 220))
)
net(5
rect(diff_cont (4230 3290) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -220) (220 220))
@ -283,7 +289,7 @@ circuit(INV2PAIR
rect(metal1 (-3000 -760) (360 760))
rect(metal1 (-360 -760) (360 760))
)
net(5
net(6
rect(diff_cont (4230 490) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -220) (220 220))
@ -297,12 +303,6 @@ circuit(INV2PAIR
rect(metal1 (-3000 -760) (360 760))
rect(metal1 (-360 -760) (360 760))
)
net(6
rect(diff_cont (2390 3690) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -2620) (220 220))
rect(diff_cont (-220 -620) (220 220))
)
net(7)
net(8
rect(diff_cont (5030 3690) (220 220))
@ -315,8 +315,8 @@ circuit(INV2PAIR
# Outgoing pins and their connections to nets
pin(1 name(BULK))
pin(2)
pin(4)
pin(5)
pin(6)
pin(7)
pin(8)
pin(9)
@ -326,18 +326,18 @@ circuit(INV2PAIR
pin(0 9)
pin(1 7)
pin(2 3)
pin(3 6)
pin(4 5)
pin(5 4)
pin(3 4)
pin(4 6)
pin(5 5)
pin(6 1)
)
circuit(2 INV2 location(4340 800)
pin(0 9)
pin(1 6)
pin(1 4)
pin(2 2)
pin(3 8)
pin(4 5)
pin(5 4)
pin(4 6)
pin(5 5)
pin(6 1)
)

View File

@ -238,6 +238,12 @@ X(INV2PAIR
R(diff_cont (-220 180) (220 220))
)
N(4
R(diff_cont (2390 3690) (220 220))
R(diff_cont (-220 -620) (220 220))
R(diff_cont (-220 -2620) (220 220))
R(diff_cont (-220 -620) (220 220))
)
N(5
R(diff_cont (4230 3290) (220 220))
R(diff_cont (-220 180) (220 220))
R(diff_cont (-220 -220) (220 220))
@ -251,7 +257,7 @@ X(INV2PAIR
R(metal1 (-3000 -760) (360 760))
R(metal1 (-360 -760) (360 760))
)
N(5
N(6
R(diff_cont (4230 490) (220 220))
R(diff_cont (-220 180) (220 220))
R(diff_cont (-220 -220) (220 220))
@ -265,12 +271,6 @@ X(INV2PAIR
R(metal1 (-3000 -760) (360 760))
R(metal1 (-360 -760) (360 760))
)
N(6
R(diff_cont (2390 3690) (220 220))
R(diff_cont (-220 -620) (220 220))
R(diff_cont (-220 -2620) (220 220))
R(diff_cont (-220 -620) (220 220))
)
N(7)
N(8
R(diff_cont (5030 3690) (220 220))
@ -281,8 +281,8 @@ X(INV2PAIR
N(9)
P(1 I(BULK))
P(2)
P(4)
P(5)
P(6)
P(7)
P(8)
P(9)
@ -290,18 +290,18 @@ X(INV2PAIR
P(0 9)
P(1 7)
P(2 3)
P(3 6)
P(4 5)
P(5 4)
P(3 4)
P(4 6)
P(5 5)
P(6 1)
)
X(2 INV2 Y(4340 800)
P(0 9)
P(1 6)
P(1 4)
P(2 2)
P(3 8)
P(4 5)
P(5 4)
P(4 6)
P(5 5)
P(6 1)
)
)

View File

@ -268,6 +268,24 @@ layout(
# Nets with their geometries
net(1 name(BULK))
net(2
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(3
rect(diff_cont (4230 3290) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
@ -289,7 +307,7 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(3
net(4
rect(diff_cont (4230 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
@ -311,24 +329,6 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(4
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(5)
net(6
rect(diff_cont (3430 890) (220 220))
@ -363,17 +363,17 @@ layout(
circuit(1 INV2 location(1700 800)
pin(0 7)
pin(1 5)
pin(2 4)
pin(3 3)
pin(4 2)
pin(2 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
circuit(2 INV2 location(4340 800)
pin(0 7)
pin(1 4)
pin(1 2)
pin(2 6)
pin(3 3)
pin(4 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
@ -808,45 +808,45 @@ layout(
# Subcircuits and their connections
circuit(1 INV2PAIR location(19420 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 1)
pin(1 1)
pin(2 3)
pin(3 4)
pin(4 10)
pin(5 2)
pin(6 3)
)
circuit(2 INV2PAIR location(-1700 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 8)
pin(1 8)
pin(2 3)
pin(3 4)
pin(4 1)
pin(5 9)
pin(6 3)
)
circuit(3 INV2PAIR location(3580 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 7)
pin(1 7)
pin(2 3)
pin(3 4)
pin(4 9)
pin(5 12)
pin(6 3)
)
circuit(4 INV2PAIR location(8860 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 6)
pin(1 6)
pin(2 3)
pin(3 4)
pin(4 12)
pin(5 11)
pin(6 3)
)
circuit(5 INV2PAIR location(14140 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 5)
pin(1 5)
pin(2 3)
pin(3 4)
pin(4 11)
pin(5 10)
pin(6 3)
@ -1044,16 +1044,16 @@ xref(
)
circuit(INV2PAIR INV2PAIR match
xref(
net(2 2 match)
net(3 3 match)
net(4 4 match)
net(3 2 match)
net(4 3 match)
net(2 4 match)
net(5 5 match)
net(6 6 match)
net(7 7 match)
net(1 1 match)
pin(1 1 match)
pin(2 2 match)
pin(3 3 match)
pin(2 1 match)
pin(3 2 match)
pin(1 3 match)
pin(4 4 match)
pin(5 5 match)
pin(6 6 match)

View File

@ -268,6 +268,24 @@ layout(
# Nets with their geometries
net(1 name(BULK))
net(2
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(3
rect(diff_cont (4230 3290) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
@ -289,7 +307,7 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(3
net(4
rect(diff_cont (4230 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
@ -311,24 +329,6 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(4
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(5)
net(6
rect(diff_cont (3430 890) (220 220))
@ -363,17 +363,17 @@ layout(
circuit(1 INV2 location(1700 800)
pin(0 7)
pin(1 5)
pin(2 4)
pin(3 3)
pin(4 2)
pin(2 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
circuit(2 INV2 location(4340 800)
pin(0 7)
pin(1 4)
pin(1 2)
pin(2 6)
pin(3 3)
pin(4 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
@ -808,45 +808,45 @@ layout(
# Subcircuits and their connections
circuit(1 INV2PAIR location(19420 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 1)
pin(1 1)
pin(2 3)
pin(3 4)
pin(4 10)
pin(5 2)
pin(6 3)
)
circuit(2 INV2PAIR location(-1700 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 8)
pin(1 8)
pin(2 3)
pin(3 4)
pin(4 1)
pin(5 9)
pin(6 3)
)
circuit(3 INV2PAIR location(3580 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 7)
pin(1 7)
pin(2 3)
pin(3 4)
pin(4 9)
pin(5 12)
pin(6 3)
)
circuit(4 INV2PAIR location(8860 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 6)
pin(1 6)
pin(2 3)
pin(3 4)
pin(4 12)
pin(5 11)
pin(6 3)
)
circuit(5 INV2PAIR location(14140 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 5)
pin(1 5)
pin(2 3)
pin(3 4)
pin(4 11)
pin(5 10)
pin(6 3)
@ -1044,16 +1044,16 @@ xref(
)
circuit(INV2PAIR INV2PAIR match
xref(
net(2 2 match)
net(3 3 match)
net(4 4 match)
net(3 2 match)
net(4 3 match)
net(2 4 match)
net(5 5 match)
net(6 6 match)
net(7 7 match)
net(1 1 match)
pin(1 1 match)
pin(2 2 match)
pin(3 3 match)
pin(2 1 match)
pin(3 2 match)
pin(1 3 match)
pin(4 4 match)
pin(5 5 match)
pin(6 6 match)

View File

@ -268,6 +268,24 @@ layout(
# Nets with their geometries
net(1 name(BULK))
net(2
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(3
rect(diff_cont (4230 3290) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
@ -289,7 +307,7 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(3
net(4
rect(diff_cont (4230 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
@ -311,24 +329,6 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(4
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(5)
net(6
rect(diff_cont (3430 890) (220 220))
@ -363,17 +363,17 @@ layout(
circuit(1 INV2 location(1700 800)
pin(0 7)
pin(1 5)
pin(2 4)
pin(3 3)
pin(4 2)
pin(2 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
circuit(2 INV2 location(4340 800)
pin(0 7)
pin(1 4)
pin(1 2)
pin(2 6)
pin(3 3)
pin(4 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
@ -808,45 +808,45 @@ layout(
# Subcircuits and their connections
circuit(1 INV2PAIR location(19420 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 1)
pin(1 1)
pin(2 3)
pin(3 4)
pin(4 10)
pin(5 2)
pin(6 3)
)
circuit(2 INV2PAIR location(-1700 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 8)
pin(1 8)
pin(2 3)
pin(3 4)
pin(4 1)
pin(5 9)
pin(6 3)
)
circuit(3 INV2PAIR location(3580 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 7)
pin(1 7)
pin(2 3)
pin(3 4)
pin(4 9)
pin(5 12)
pin(6 3)
)
circuit(4 INV2PAIR location(8860 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 6)
pin(1 6)
pin(2 3)
pin(3 4)
pin(4 12)
pin(5 11)
pin(6 3)
)
circuit(5 INV2PAIR location(14140 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 5)
pin(1 5)
pin(2 3)
pin(3 4)
pin(4 11)
pin(5 10)
pin(6 3)
@ -1044,16 +1044,16 @@ xref(
)
circuit(INV2PAIR INV2PAIR match
xref(
net(2 2 match)
net(3 3 match)
net(4 4 match)
net(3 2 match)
net(4 3 match)
net(2 4 match)
net(5 5 match)
net(6 6 match)
net(7 7 match)
net(1 1 match)
pin(1 1 match)
pin(2 2 match)
pin(3 3 match)
pin(2 1 match)
pin(3 2 match)
pin(1 3 match)
pin(4 4 match)
pin(5 5 match)
pin(6 6 match)

View File

@ -268,6 +268,24 @@ layout(
# Nets with their geometries
net(1 name(BULK))
net(2
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(3
rect(diff_cont (4230 3290) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
@ -289,7 +307,7 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(3
net(4
rect(diff_cont (4230 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
@ -311,24 +329,6 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(4
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(5)
net(6
rect(diff_cont (3430 890) (220 220))
@ -363,17 +363,17 @@ layout(
circuit(1 INV2 location(1700 800)
pin(0 7)
pin(1 5)
pin(2 4)
pin(3 3)
pin(4 2)
pin(2 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
circuit(2 INV2 location(4340 800)
pin(0 7)
pin(1 4)
pin(1 2)
pin(2 6)
pin(3 3)
pin(4 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
@ -808,45 +808,45 @@ layout(
# Subcircuits and their connections
circuit(1 INV2PAIR location(19420 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 1)
pin(1 1)
pin(2 3)
pin(3 4)
pin(4 10)
pin(5 2)
pin(6 3)
)
circuit(2 INV2PAIR location(-1700 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 8)
pin(1 8)
pin(2 3)
pin(3 4)
pin(4 1)
pin(5 9)
pin(6 3)
)
circuit(3 INV2PAIR location(3580 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 7)
pin(1 7)
pin(2 3)
pin(3 4)
pin(4 9)
pin(5 12)
pin(6 3)
)
circuit(4 INV2PAIR location(8860 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 6)
pin(1 6)
pin(2 3)
pin(3 4)
pin(4 12)
pin(5 11)
pin(6 3)
)
circuit(5 INV2PAIR location(14140 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 5)
pin(1 5)
pin(2 3)
pin(3 4)
pin(4 11)
pin(5 10)
pin(6 3)
@ -1044,16 +1044,16 @@ xref(
)
circuit(INV2PAIR INV2PAIR match
xref(
net(2 2 match)
net(3 3 match)
net(4 4 match)
net(3 2 match)
net(4 3 match)
net(2 4 match)
net(5 5 match)
net(6 6 match)
net(7 7 match)
net(1 1 match)
pin(1 1 match)
pin(2 2 match)
pin(3 3 match)
pin(2 1 match)
pin(3 2 match)
pin(1 3 match)
pin(4 4 match)
pin(5 5 match)
pin(6 6 match)

View File

@ -268,6 +268,24 @@ layout(
# Nets with their geometries
net(1 name(BULK))
net(2
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(3
rect(diff_cont (4230 3290) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
@ -289,7 +307,7 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(3
net(4
rect(diff_cont (4230 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
@ -311,24 +329,6 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(4
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(5)
net(6
rect(diff_cont (3430 890) (220 220))
@ -363,17 +363,17 @@ layout(
circuit(1 INV2 location(1700 800)
pin(0 7)
pin(1 5)
pin(2 4)
pin(3 3)
pin(4 2)
pin(2 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
circuit(2 INV2 location(4340 800)
pin(0 7)
pin(1 4)
pin(1 2)
pin(2 6)
pin(3 3)
pin(4 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
@ -808,45 +808,45 @@ layout(
# Subcircuits and their connections
circuit(1 INV2PAIR location(19420 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 1)
pin(1 1)
pin(2 3)
pin(3 4)
pin(4 10)
pin(5 2)
pin(6 3)
)
circuit(2 INV2PAIR location(-1700 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 8)
pin(1 8)
pin(2 3)
pin(3 4)
pin(4 1)
pin(5 9)
pin(6 3)
)
circuit(3 INV2PAIR location(3580 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 7)
pin(1 7)
pin(2 3)
pin(3 4)
pin(4 9)
pin(5 12)
pin(6 3)
)
circuit(4 INV2PAIR location(8860 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 6)
pin(1 6)
pin(2 3)
pin(3 4)
pin(4 12)
pin(5 11)
pin(6 3)
)
circuit(5 INV2PAIR location(14140 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 5)
pin(1 5)
pin(2 3)
pin(3 4)
pin(4 11)
pin(5 10)
pin(6 3)
@ -918,23 +918,24 @@ reference(
net(2 name('2'))
net(3 name('3'))
net(4 name('4'))
net(5 name('6'))
net(6 name('7'))
net(5 name('5'))
net(6 name('6'))
net(7 name('7'))
# Outgoing pins and their connections to nets
pin(1 name('1'))
pin(2 name('2'))
pin(3 name('3'))
pin(4 name('4'))
pin(name('5'))
pin(5 name('6'))
pin(6 name('7'))
pin(5 name('5'))
pin(6 name('6'))
pin(7 name('7'))
# Subcircuits and their connections
circuit(1 INV2 name($2)
pin(0 6)
pin(0 7)
pin(1 4)
pin(2 5)
pin(2 6)
pin(3 3)
pin(4 2)
pin(5 1)
@ -1017,23 +1018,24 @@ reference(
net(2 name('2'))
net(3 name('3'))
net(4 name('4'))
net(5 name('6'))
net(6 name('7'))
net(5 name('5'))
net(6 name('6'))
net(7 name('7'))
# Outgoing pins and their connections to nets
pin(1 name('1'))
pin(2 name('2'))
pin(3 name('3'))
pin(4 name('4'))
pin(name('5'))
pin(5 name('6'))
pin(6 name('7'))
pin(5 name('5'))
pin(6 name('6'))
pin(7 name('7'))
# Subcircuits and their connections
circuit(1 INV2 name($2)
pin(0 6)
pin(0 7)
pin(1 4)
pin(2 5)
pin(2 6)
pin(3 3)
pin(4 2)
pin(5 1)
@ -1068,28 +1070,57 @@ xref(
)
circuit(INV2PAIR INV2PAIR nomatch
xref(
net(4 () mismatch)
net(2 2 mismatch)
net(3 3 mismatch)
net(3 2 mismatch)
net(4 3 mismatch)
net(5 4 match)
net(6 5 match)
net(7 6 mismatch)
net(2 5 mismatch)
net(6 6 match)
net(7 7 mismatch)
net(1 1 mismatch)
pin(() 4 mismatch)
pin(3 () mismatch)
pin(1 1 match)
pin(2 2 match)
pin(2 1 match)
pin(3 2 match)
pin(4 3 match)
pin(1 4 match)
pin(5 5 match)
pin(6 6 match)
pin(0 0 match)
circuit(() 1 mismatch)
circuit(1 () mismatch)
circuit(2 () mismatch)
circuit(1 1 mismatch)
)
)
circuit(RINGO RINGO skipped
circuit(RINGO RINGO nomatch
xref(
net(() 7 mismatch)
net(() 9 mismatch)
net(() 11 mismatch)
net(() 6 mismatch)
net(() 8 mismatch)
net(5 () mismatch)
net(6 () mismatch)
net(7 () mismatch)
net(9 () mismatch)
net(11 () mismatch)
net(12 () mismatch)
net(10 1 mismatch)
net(8 10 mismatch)
net(1 5 mismatch)
net(2 2 match)
net(3 3 match)
net(4 4 match)
pin(() 0 match)
pin(0 () match)
pin(1 1 match)
pin(2 2 match)
pin(3 3 match)
circuit(() 2 mismatch)
circuit(() 3 mismatch)
circuit(() 4 mismatch)
circuit(() 5 mismatch)
circuit(2 () mismatch)
circuit(3 () mismatch)
circuit(4 () mismatch)
circuit(5 () mismatch)
circuit(1 1 mismatch)
)
)
)

View File

@ -268,6 +268,24 @@ layout(
# Nets with their geometries
net(1 name(BULK))
net(2
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(3
rect(diff_cont (4230 3290) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
@ -289,7 +307,7 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(3
net(4
rect(diff_cont (4230 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
@ -311,24 +329,6 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(4
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(5)
net(6
rect(diff_cont (3430 890) (220 220))
@ -363,17 +363,17 @@ layout(
circuit(1 INV2 location(1700 800)
pin(0 7)
pin(1 5)
pin(2 4)
pin(3 3)
pin(4 2)
pin(2 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
circuit(2 INV2 location(4340 800)
pin(0 7)
pin(1 4)
pin(1 2)
pin(2 6)
pin(3 3)
pin(4 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
@ -808,45 +808,45 @@ layout(
# Subcircuits and their connections
circuit(1 INV2PAIR location(19420 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 1)
pin(1 1)
pin(2 3)
pin(3 4)
pin(4 10)
pin(5 2)
pin(6 3)
)
circuit(2 INV2PAIR location(-1700 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 8)
pin(1 8)
pin(2 3)
pin(3 4)
pin(4 1)
pin(5 9)
pin(6 3)
)
circuit(3 INV2PAIR location(3580 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 7)
pin(1 7)
pin(2 3)
pin(3 4)
pin(4 9)
pin(5 12)
pin(6 3)
)
circuit(4 INV2PAIR location(8860 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 6)
pin(1 6)
pin(2 3)
pin(3 4)
pin(4 12)
pin(5 11)
pin(6 3)
)
circuit(5 INV2PAIR location(14140 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 5)
pin(1 5)
pin(2 3)
pin(3 4)
pin(4 11)
pin(5 10)
pin(6 3)
@ -918,23 +918,24 @@ reference(
net(2 name('2'))
net(3 name('3'))
net(4 name('4'))
net(5 name('6'))
net(6 name('7'))
net(5 name('5'))
net(6 name('6'))
net(7 name('7'))
# Outgoing pins and their connections to nets
pin(1 name('1'))
pin(2 name('2'))
pin(3 name('3'))
pin(4 name('4'))
pin(name('5'))
pin(5 name('6'))
pin(6 name('7'))
pin(5 name('5'))
pin(6 name('6'))
pin(7 name('7'))
# Subcircuits and their connections
circuit(1 INV2 name($2)
pin(0 6)
pin(0 7)
pin(1 4)
pin(2 5)
pin(2 6)
pin(3 3)
pin(4 2)
pin(5 1)
@ -1017,23 +1018,24 @@ reference(
net(2 name('2'))
net(3 name('3'))
net(4 name('4'))
net(5 name('6'))
net(6 name('7'))
net(5 name('5'))
net(6 name('6'))
net(7 name('7'))
# Outgoing pins and their connections to nets
pin(1 name('1'))
pin(2 name('2'))
pin(3 name('3'))
pin(4 name('4'))
pin(name('5'))
pin(5 name('6'))
pin(6 name('7'))
pin(5 name('5'))
pin(6 name('6'))
pin(7 name('7'))
# Subcircuits and their connections
circuit(1 INV2 name($2)
pin(0 6)
pin(0 7)
pin(1 4)
pin(2 5)
pin(2 6)
pin(3 3)
pin(4 2)
pin(5 1)
@ -1068,28 +1070,57 @@ xref(
)
circuit(INV2PAIR INV2PAIR nomatch
xref(
net(4 () mismatch)
net(2 2 mismatch)
net(3 3 mismatch)
net(3 2 mismatch)
net(4 3 mismatch)
net(5 4 match)
net(6 5 match)
net(7 6 mismatch)
net(2 5 mismatch)
net(6 6 match)
net(7 7 mismatch)
net(1 1 mismatch)
pin(() 4 mismatch)
pin(3 () mismatch)
pin(1 1 match)
pin(2 2 match)
pin(2 1 match)
pin(3 2 match)
pin(4 3 match)
pin(1 4 match)
pin(5 5 match)
pin(6 6 match)
pin(0 0 match)
circuit(() 1 mismatch)
circuit(1 () mismatch)
circuit(2 () mismatch)
circuit(1 1 mismatch)
)
)
circuit(RINGO RINGO skipped
circuit(RINGO RINGO nomatch
xref(
net(() 7 mismatch)
net(() 9 mismatch)
net(() 11 mismatch)
net(() 6 mismatch)
net(() 8 mismatch)
net(5 () mismatch)
net(6 () mismatch)
net(7 () mismatch)
net(9 () mismatch)
net(11 () mismatch)
net(12 () mismatch)
net(10 1 mismatch)
net(8 10 mismatch)
net(1 5 mismatch)
net(2 2 match)
net(3 3 match)
net(4 4 match)
pin(() 0 match)
pin(0 () match)
pin(1 1 match)
pin(2 2 match)
pin(3 3 match)
circuit(() 2 mismatch)
circuit(() 3 mismatch)
circuit(() 4 mismatch)
circuit(() 5 mismatch)
circuit(2 () mismatch)
circuit(3 () mismatch)
circuit(4 () mismatch)
circuit(5 () mismatch)
circuit(1 1 mismatch)
)
)
)

View File

@ -268,6 +268,24 @@ layout(
# Nets with their geometries
net(1 name(BULK))
net(2
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(3
rect(diff_cont (4230 3290) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
@ -289,7 +307,7 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(3
net(4
rect(diff_cont (4230 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
@ -311,24 +329,6 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(4
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(5)
net(6
rect(diff_cont (3430 890) (220 220))
@ -363,17 +363,17 @@ layout(
circuit(1 INV2 location(1700 800)
pin(0 7)
pin(1 5)
pin(2 4)
pin(3 3)
pin(4 2)
pin(2 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
circuit(2 INV2 location(4340 800)
pin(0 7)
pin(1 4)
pin(1 2)
pin(2 6)
pin(3 3)
pin(4 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
@ -808,45 +808,45 @@ layout(
# Subcircuits and their connections
circuit(1 INV2PAIR location(19420 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 1)
pin(1 1)
pin(2 3)
pin(3 4)
pin(4 10)
pin(5 2)
pin(6 3)
)
circuit(2 INV2PAIR location(-1700 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 8)
pin(1 8)
pin(2 3)
pin(3 4)
pin(4 1)
pin(5 9)
pin(6 3)
)
circuit(3 INV2PAIR location(3580 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 7)
pin(1 7)
pin(2 3)
pin(3 4)
pin(4 9)
pin(5 12)
pin(6 3)
)
circuit(4 INV2PAIR location(8860 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 6)
pin(1 6)
pin(2 3)
pin(3 4)
pin(4 12)
pin(5 11)
pin(6 3)
)
circuit(5 INV2PAIR location(14140 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 5)
pin(1 5)
pin(2 3)
pin(3 4)
pin(4 11)
pin(5 10)
pin(6 3)
@ -918,23 +918,24 @@ reference(
net(2 name('2'))
net(3 name('3'))
net(4 name('4'))
net(5 name('6'))
net(6 name('7'))
net(5 name('5'))
net(6 name('6'))
net(7 name('7'))
# Outgoing pins and their connections to nets
pin(1 name('1'))
pin(2 name('2'))
pin(3 name('3'))
pin(4 name('4'))
pin(name('5'))
pin(5 name('6'))
pin(6 name('7'))
pin(5 name('5'))
pin(6 name('6'))
pin(7 name('7'))
# Subcircuits and their connections
circuit(1 INV2 name($2)
pin(0 6)
pin(0 7)
pin(1 4)
pin(2 5)
pin(2 6)
pin(3 3)
pin(4 2)
pin(5 1)
@ -1017,23 +1018,24 @@ reference(
net(2 name('2'))
net(3 name('3'))
net(4 name('4'))
net(5 name('6'))
net(6 name('7'))
net(5 name('5'))
net(6 name('6'))
net(7 name('7'))
# Outgoing pins and their connections to nets
pin(1 name('1'))
pin(2 name('2'))
pin(3 name('3'))
pin(4 name('4'))
pin(name('5'))
pin(5 name('6'))
pin(6 name('7'))
pin(5 name('5'))
pin(6 name('6'))
pin(7 name('7'))
# Subcircuits and their connections
circuit(1 INV2 name($2)
pin(0 6)
pin(0 7)
pin(1 4)
pin(2 5)
pin(2 6)
pin(3 3)
pin(4 2)
pin(5 1)
@ -1068,28 +1070,57 @@ xref(
)
circuit(INV2PAIR INV2PAIR nomatch
xref(
net(4 () mismatch)
net(2 2 mismatch)
net(3 3 mismatch)
net(3 2 mismatch)
net(4 3 mismatch)
net(5 4 match)
net(6 5 match)
net(7 6 mismatch)
net(2 5 mismatch)
net(6 6 match)
net(7 7 mismatch)
net(1 1 mismatch)
pin(() 4 mismatch)
pin(3 () mismatch)
pin(1 1 match)
pin(2 2 match)
pin(2 1 match)
pin(3 2 match)
pin(4 3 match)
pin(1 4 match)
pin(5 5 match)
pin(6 6 match)
pin(0 0 match)
circuit(() 1 mismatch)
circuit(1 () mismatch)
circuit(2 () mismatch)
circuit(1 1 mismatch)
)
)
circuit(RINGO RINGO skipped
circuit(RINGO RINGO nomatch
xref(
net(() 7 mismatch)
net(() 9 mismatch)
net(() 11 mismatch)
net(() 6 mismatch)
net(() 8 mismatch)
net(5 () mismatch)
net(6 () mismatch)
net(7 () mismatch)
net(9 () mismatch)
net(11 () mismatch)
net(12 () mismatch)
net(10 1 mismatch)
net(8 10 mismatch)
net(1 5 mismatch)
net(2 2 match)
net(3 3 match)
net(4 4 match)
pin(() 0 match)
pin(0 () match)
pin(1 1 match)
pin(2 2 match)
pin(3 3 match)
circuit(() 2 mismatch)
circuit(() 3 mismatch)
circuit(() 4 mismatch)
circuit(() 5 mismatch)
circuit(2 () mismatch)
circuit(3 () mismatch)
circuit(4 () mismatch)
circuit(5 () mismatch)
circuit(1 1 mismatch)
)
)
)

View File

@ -268,6 +268,24 @@ layout(
# Nets with their geometries
net(1 name(BULK))
net(2
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(3
rect(diff_cont (4230 3290) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
@ -289,7 +307,7 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(3
net(4
rect(diff_cont (4230 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
@ -311,24 +329,6 @@ layout(
rect(metal1 (-3000 -1560) (360 1560))
rect(metal1 (-360 -1560) (360 1560))
)
net(4
rect(diff_cont (790 890) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (1380 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 -3820) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-220 -620) (220 220))
rect(diff_cont (-1820 3380) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
rect(diff_cont (-220 180) (220 220))
)
net(5)
net(6
rect(diff_cont (3430 890) (220 220))
@ -363,17 +363,17 @@ layout(
circuit(1 INV2 location(1700 800)
pin(0 7)
pin(1 5)
pin(2 4)
pin(3 3)
pin(4 2)
pin(2 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
circuit(2 INV2 location(4340 800)
pin(0 7)
pin(1 4)
pin(1 2)
pin(2 6)
pin(3 3)
pin(4 2)
pin(3 4)
pin(4 3)
pin(5 1)
)
@ -808,45 +808,45 @@ layout(
# Subcircuits and their connections
circuit(1 INV2PAIR location(19420 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 1)
pin(1 1)
pin(2 3)
pin(3 4)
pin(4 10)
pin(5 2)
pin(6 3)
)
circuit(2 INV2PAIR location(-1700 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 8)
pin(1 8)
pin(2 3)
pin(3 4)
pin(4 1)
pin(5 9)
pin(6 3)
)
circuit(3 INV2PAIR location(3580 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 7)
pin(1 7)
pin(2 3)
pin(3 4)
pin(4 9)
pin(5 12)
pin(6 3)
)
circuit(4 INV2PAIR location(8860 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 6)
pin(1 6)
pin(2 3)
pin(3 4)
pin(4 12)
pin(5 11)
pin(6 3)
)
circuit(5 INV2PAIR location(14140 -800)
pin(0 4)
pin(1 3)
pin(2 4)
pin(3 5)
pin(1 5)
pin(2 3)
pin(3 4)
pin(4 11)
pin(5 10)
pin(6 3)
@ -918,23 +918,24 @@ reference(
net(2 name('2'))
net(3 name('3'))
net(4 name('4'))
net(5 name('6'))
net(6 name('7'))
net(5 name('5'))
net(6 name('6'))
net(7 name('7'))
# Outgoing pins and their connections to nets
pin(1 name('1'))
pin(2 name('2'))
pin(3 name('3'))
pin(4 name('4'))
pin(name('5'))
pin(5 name('6'))
pin(6 name('7'))
pin(5 name('5'))
pin(6 name('6'))
pin(7 name('7'))
# Subcircuits and their connections
circuit(1 INV2 name($2)
pin(0 6)
pin(0 7)
pin(1 4)
pin(2 5)
pin(2 6)
pin(3 3)
pin(4 2)
pin(5 1)
@ -1017,23 +1018,24 @@ reference(
net(2 name('2'))
net(3 name('3'))
net(4 name('4'))
net(5 name('6'))
net(6 name('7'))
net(5 name('5'))
net(6 name('6'))
net(7 name('7'))
# Outgoing pins and their connections to nets
pin(1 name('1'))
pin(2 name('2'))
pin(3 name('3'))
pin(4 name('4'))
pin(name('5'))
pin(5 name('6'))
pin(6 name('7'))
pin(5 name('5'))
pin(6 name('6'))
pin(7 name('7'))
# Subcircuits and their connections
circuit(1 INV2 name($2)
pin(0 6)
pin(0 7)
pin(1 4)
pin(2 5)
pin(2 6)
pin(3 3)
pin(4 2)
pin(5 1)
@ -1068,28 +1070,57 @@ xref(
)
circuit(INV2PAIR INV2PAIR nomatch
xref(
net(4 () mismatch)
net(2 2 mismatch)
net(3 3 mismatch)
net(3 2 mismatch)
net(4 3 mismatch)
net(5 4 match)
net(6 5 match)
net(7 6 mismatch)
net(2 5 mismatch)
net(6 6 match)
net(7 7 mismatch)
net(1 1 mismatch)
pin(() 4 mismatch)
pin(3 () mismatch)
pin(1 1 match)
pin(2 2 match)
pin(2 1 match)
pin(3 2 match)
pin(4 3 match)
pin(1 4 match)
pin(5 5 match)
pin(6 6 match)
pin(0 0 match)
circuit(() 1 mismatch)
circuit(1 () mismatch)
circuit(2 () mismatch)
circuit(1 1 mismatch)
)
)
circuit(RINGO RINGO skipped
circuit(RINGO RINGO nomatch
xref(
net(() 7 mismatch)
net(() 9 mismatch)
net(() 11 mismatch)
net(() 6 mismatch)
net(() 8 mismatch)
net(5 () mismatch)
net(6 () mismatch)
net(7 () mismatch)
net(9 () mismatch)
net(11 () mismatch)
net(12 () mismatch)
net(10 1 mismatch)
net(8 10 mismatch)
net(1 5 mismatch)
net(2 2 match)
net(3 3 match)
net(4 4 match)
pin(() 0 match)
pin(0 () match)
pin(1 1 match)
pin(2 2 match)
pin(3 3 match)
circuit(() 2 mismatch)
circuit(() 3 mismatch)
circuit(() 4 mismatch)
circuit(() 5 mismatch)
circuit(2 () mismatch)
circuit(3 () mismatch)
circuit(4 () mismatch)
circuit(5 () mismatch)
circuit(1 1 mismatch)
)
)
)

View File

@ -56,6 +56,11 @@ class Buddies_TestClass < TestBase
"strm2txt" => 0x62656769,
}
# Windows CRLF -> LF translation
signature_equiv = {
0x300d0a53 => 0x300a5345
}
%w(strm2cif strm2dxf strm2gds strm2gdstxt strm2oas strm2txt).each do |bin|
puts "Testing #{bin} ..."
@ -74,6 +79,7 @@ class Buddies_TestClass < TestBase
File.open(out_file, "rb") do |file|
sig = file.read(4).unpack('N').first
sig = signature_equiv[sig] || sig
assert_equal(sig, signatures[bin])
end

View File

@ -43,8 +43,8 @@ X$2 3 5 2 6 INVX1
* net 2 VDD
* net 3 IN
* net 4 VSS
* device instance $1 r0 *1 0.85,2.135 NMOS
M$1 4 3 1 4 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
* device instance $2 r0 *1 0.85,5.8 PMOS
M$2 2 3 1 2 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
* device instance $1 r0 *1 0.85,5.8 PMOS
M$1 2 3 1 2 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
* device instance $2 r0 *1 0.85,2.135 NMOS
M$2 4 3 1 4 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
.ENDS INVX1

View File

@ -135,20 +135,7 @@ layout(
pin(4 name(VSS))
# Devices and their connections
device(1 D$NMOS
location(850 2135)
param(L 0.25)
param(W 0.95)
param(AS 0.40375)
param(AD 0.40375)
param(PS 2.75)
param(PD 2.75)
terminal(S 4)
terminal(G 3)
terminal(D 1)
terminal(B 4)
)
device(2 D$PMOS
device(1 D$PMOS
location(850 5800)
param(L 0.25)
param(W 1.5)
@ -161,6 +148,19 @@ layout(
terminal(D 1)
terminal(B 2)
)
device(2 D$NMOS
location(850 2135)
param(L 0.25)
param(W 0.95)
param(AS 0.40375)
param(AD 0.40375)
param(PS 2.75)
param(PD 2.75)
terminal(S 4)
terminal(G 3)
terminal(D 1)
terminal(B 4)
)
)
circuit(DINV
@ -430,8 +430,8 @@ xref(
pin(0 1 match)
pin(1 2 match)
pin(3 3 match)
device(1 1 match)
device(2 2 match)
device(2 1 match)
device(1 2 match)
)
)
circuit(TOP TOP match

30
testdata/lvs/invchain_cheat.cir.1 vendored Normal file
View File

@ -0,0 +1,30 @@
* Extracted by KLayout
.SUBCKT INVCHAIN
X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3
X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2
X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV
.ENDS INVCHAIN
.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2
X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV
X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV
X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV
.ENDS INV3
.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5
+ \$I4 \$I2
X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV
X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV
.ENDS INV2
.SUBCKT INV \$1 \$2 \$3 \$4 \$5 \$9 \$I8 \$I7
M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U
+ PD=1.5U
M$2 \$2 \$I8 \$5 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U
+ PD=1.97U
M$3 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U
+ PD=1.5U
M$4 \$1 \$I7 \$9 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U
+ PD=1.97U
.ENDS INV

30
testdata/lvs/invchain_cheat.cir.2 vendored Normal file
View File

@ -0,0 +1,30 @@
* Extracted by KLayout
.SUBCKT INVCHAIN
X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3
X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2
X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV
.ENDS INVCHAIN
.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2
X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV
X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV
X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV
.ENDS INV3
.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5
+ \$I4 \$I2
X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV
X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV
.ENDS INV2
.SUBCKT INV \$1 \$2 \$3 \$4 \$5 \$8 \$I8 \$I7
M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U
+ PD=1.5U
M$2 \$2 \$I8 \$5 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U
+ PD=1.97U
M$3 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U
+ PD=1.5U
M$4 \$1 \$I7 \$8 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U
+ PD=1.97U
.ENDS INV

30
testdata/lvs/invchain_cheat.cir.3 vendored Normal file
View File

@ -0,0 +1,30 @@
* Extracted by KLayout
.SUBCKT INVCHAIN
X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3
X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2
X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV
.ENDS INVCHAIN
.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2
X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV
X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV
X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV
.ENDS INV3
.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5
+ \$I4 \$I2
X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV
X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV
.ENDS INV2
.SUBCKT INV \$1 \$2 \$3 \$4 \$7 \$10 \$I8 \$I7
M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U
+ PD=1.5U
M$2 \$2 \$I8 \$7 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U
+ PD=1.97U
M$3 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U
+ PD=1.5U
M$4 \$1 \$I7 \$10 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U
+ PD=1.97U
.ENDS INV

73
testdata/lvs/invchain_cheat.lvs vendored Normal file
View File

@ -0,0 +1,73 @@
source($lvs_test_source)
report_lvs($lvs_test_target_lvsdb)
writer = write_spice(true, false)
target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
schematic("invchain_for_cheat.cir")
deep
# Drawing layers
nwell = input(1, 0)
active = input(2, 0)
poly = input(3, 0)
diff_cont = input(4, 0)
poly_cont = input(5, 0)
metal1 = input(6, 0)
via1 = input(7, 0)
metal2 = input(8, 0)
# Bulk layer for terminal provisioning
bulk = polygon_layer
# Computed layers
active_in_nwell = active & nwell
pactive = active_in_nwell
pgate = pactive & poly
psd = pactive - pgate
active_outside_nwell = active - nwell
nactive = active_outside_nwell
ngate = nactive & poly
nsd = nactive - ngate
# Device extraction
cheat("INV") do
# PMOS transistor device extraction
extract_devices(mos3("PMOS"), { "SD" => psd, "G" => pgate,
"tS" => psd, "tD" => psd, "tG" => poly })
# NMOS transistor device extraction
extract_devices(mos3("NMOS"), { "SD" => nsd, "G" => ngate,
"tS" => nsd, "tD" => nsd, "tG" => poly })
end
# Define connectivity for netlist extraction
# Inter-layer
connect(psd, diff_cont)
connect(nsd, diff_cont)
connect(poly, poly_cont)
connect(diff_cont, metal1)
connect(poly_cont, metal1)
connect(metal1, via1)
connect(via1, metal2)
# Global
connect_global(bulk, "SUBSTRATE")
# Compare section
netlist.simplify
compare

757
testdata/lvs/invchain_cheat.lvsdb vendored Normal file
View File

@ -0,0 +1,757 @@
#%lvsdb-klayout
J(
W(INVCHAIN)
U(0.001)
L(l3 '3/0')
L(l6 '4/0')
L(l7 '2/0')
L(l8 '6/0')
L(l9 '7/0')
L(l10 '8/0')
L(l11)
L(l2)
L(l5)
C(l3 l3 l7)
C(l6 l6 l8 l2 l5)
C(l7 l3 l7 l8)
C(l8 l6 l7 l8 l9)
C(l9 l8 l9 l10)
C(l10 l9 l10)
C(l11 l11)
C(l2 l6 l2)
C(l5 l6 l5)
G(l11 SUBSTRATE)
D(D$PMOS PMOS
T(S
R(l2 (-960 -475) (835 950))
)
T(G
R(l3 (-125 -475) (250 950))
)
T(D
R(l2 (125 -475) (550 950))
)
)
D(D$PMOS$1 PMOS
T(S
R(l2 (-675 -475) (550 950))
)
T(G
R(l3 (-125 -475) (250 950))
)
T(D
R(l2 (125 -475) (35 950))
)
)
D(D$NMOS NMOS
T(S
R(l5 (-960 -475) (835 950))
)
T(G
R(l3 (-125 -475) (250 950))
)
T(D
R(l5 (125 -475) (550 950))
)
)
D(D$NMOS$1 NMOS
T(S
R(l5 (-675 -475) (550 950))
)
T(G
R(l3 (-125 -475) (250 950))
)
T(D
R(l5 (125 -475) (35 950))
)
)
X(INV
R((-1500 -800) (3000 4600))
N(1
R(l6 (290 -310) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-290 -690) (360 760))
R(l9 (-305 -705) (250 250))
R(l9 (-250 150) (250 250))
R(l10 (-2025 -775) (3000 900))
R(l5 (-1375 -925) (550 950))
)
N(2
R(l6 (290 2490) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-290 -690) (360 760))
R(l9 (-305 -705) (250 250))
R(l9 (-250 150) (250 250))
R(l10 (-2025 -775) (3000 900))
R(l2 (-1375 -925) (550 950))
)
N(3
R(l3 (-125 -250) (250 2500))
R(l3 (-250 -3050) (250 1600))
R(l3 (-250 1200) (250 1600))
)
N(4
R(l6 (-510 -310) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-290 -3530) (360 2840))
R(l8 (-360 -2800) (360 760))
R(l8 (-360 2040) (360 760))
R(l2 (-740 -855) (835 950))
R(l5 (-835 -3750) (835 950))
)
N(5
R(l2 (925 2325) (35 950))
)
N(6
R(l5 (925 -475) (35 950))
)
N(7)
N(8)
P(1)
P(2)
P(3)
P(4)
P(5)
P(6)
P(7)
P(8)
D(1 D$PMOS
Y(0 2800)
E(L 0.25)
E(W 0.95)
E(AS 0.79325)
E(AD 0.26125)
E(PS 3.57)
E(PD 1.5)
T(S 4)
T(G 3)
T(D 2)
)
D(2 D$PMOS$1
Y(800 2800)
E(L 0.25)
E(W 0.95)
E(AS 0.26125)
E(AD 0.03325)
E(PS 1.5)
E(PD 1.97)
T(S 2)
T(G 7)
T(D 5)
)
D(3 D$NMOS
Y(0 0)
E(L 0.25)
E(W 0.95)
E(AS 0.79325)
E(AD 0.26125)
E(PS 3.57)
E(PD 1.5)
T(S 4)
T(G 3)
T(D 1)
)
D(4 D$NMOS$1
Y(800 0)
E(L 0.25)
E(W 0.95)
E(AS 0.26125)
E(AD 0.03325)
E(PS 1.5)
E(PD 1.97)
T(S 1)
T(G 8)
T(D 6)
)
)
X(INV2
R((0 0) (5500 4600))
N(1)
N(2)
N(3)
N(4)
N(5)
N(6)
N(7)
N(8)
N(9)
N(10)
N(11
R(l6 (1790 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
)
N(12
R(l6 (3490 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
)
N(13
R(l6 (990 3290) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-3590 -690) (360 760))
R(l8 (2940 -760) (360 760))
)
N(14
R(l6 (990 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-3590 -690) (360 760))
R(l8 (2940 -760) (360 760))
)
P(1)
P(2)
P(3)
P(4)
P(5)
P(6)
P(7)
P(8)
P(9)
P(10)
P(11)
P(12)
P(13)
P(14)
X(1 INV M O(180) Y(1500 800)
P(0 14)
P(1 13)
P(2 3)
P(3 11)
P(4 9)
P(5 7)
P(6 1)
P(7 5)
)
X(2 INV Y(4000 800)
P(0 14)
P(1 13)
P(2 4)
P(3 12)
P(4 10)
P(5 8)
P(6 2)
P(7 6)
)
)
X(INV3
R((0 0) (6300 4600))
N(1)
N(2
R(l6 (990 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
)
N(3)
N(4)
N(5)
N(6)
N(7)
N(8)
N(9
R(l6 (2590 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
)
N(10
R(l6 (4290 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
)
N(11
R(l6 (1790 3290) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-3590 -690) (360 760))
R(l8 (-360 -760) (360 760))
R(l8 (2940 -760) (360 760))
)
N(12
R(l6 (1790 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-3590 -690) (360 760))
R(l8 (-360 -760) (360 760))
R(l8 (2940 -760) (360 760))
)
P(1)
P(2)
P(3)
P(4)
P(5)
P(6)
P(7)
P(8)
P(9)
P(10)
P(11)
P(12)
X(1 INV Y(1500 800)
P(0 12)
P(1 11)
P(2 5)
P(3 2)
P(4 9)
P(5 9)
P(6 1)
P(7 1)
)
X(2 INV M O(180) Y(2300 800)
P(0 12)
P(1 11)
P(2 1)
P(3 9)
P(4 2)
P(5 2)
P(6 5)
P(7 5)
)
X(3 INV Y(4800 800)
P(0 12)
P(1 11)
P(2 4)
P(3 10)
P(4 8)
P(5 7)
P(6 3)
P(7 6)
)
)
X(INVCHAIN
R((-1500 -800) (10400 4600))
N(1
R(l6 (490 990) (220 220))
R(l6 (-1220 -1520) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-65 -2185) (1105 350))
)
N(2
R(l6 (3790 990) (220 220))
R(l6 (-1220 -1520) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-65 -2185) (1105 350))
)
N(3
R(l6 (1405 990) (220 220))
R(l6 (-535 -1520) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (20 -2270) (440 520))
)
N(4
R(l6 (7090 990) (220 220))
R(l6 (-1220 -1520) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (-65 -2185) (1105 350))
)
N(5
R(l6 (4705 990) (220 220))
R(l6 (-535 -1520) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (20 -2270) (440 520))
)
N(6
R(l3 (-1295 925) (1235 350))
)
N(7
R(l3 (445 805) (480 550))
)
N(8
R(l3 (1345 925) (1945 350))
)
N(9
R(l3 (3745 805) (480 550))
)
N(10
R(l3 (4645 925) (1945 350))
)
N(11
R(l3 (7045 805) (480 550))
)
N(12
R(l6 (7690 -310) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
)
N(13
R(l6 (6890 2490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-3520 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-6820 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (3010 -690) (360 760))
R(l8 (-3660 -760) (360 760))
R(l8 (2940 -760) (360 760))
R(l8 (-6960 -760) (360 760))
R(l8 (-360 -760) (360 760))
R(l8 (2940 -760) (360 760))
)
N(14
R(l6 (6890 -310) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-3520 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-6820 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
R(l6 (-220 180) (220 220))
R(l8 (3010 -690) (360 760))
R(l8 (-3660 -760) (360 760))
R(l8 (2940 -760) (360 760))
R(l8 (-6960 -760) (360 760))
R(l8 (-360 -760) (360 760))
R(l8 (2940 -760) (360 760))
)
X(1 INV3 Y(-1500 -800)
P(0 7)
P(1 1)
P(2 9)
P(3 8)
P(4 6)
P(5 9)
P(6 5)
P(7 5)
P(8 3)
P(9 2)
P(10 13)
P(11 14)
)
X(2 INV2 Y(2600 -800)
P(0 8)
P(1 11)
P(2 9)
P(3 10)
P(4 8)
P(5 11)
P(6 2)
P(7 12)
P(8 2)
P(9 12)
P(10 5)
P(11 4)
P(12 13)
P(13 14)
)
X(3 INV M O(180) Y(7400 0)
P(0 14)
P(1 13)
P(2 11)
P(3 12)
P(4 4)
P(5 4)
P(6 10)
P(7 10)
)
)
)
H(
X(TRANS
N(1 I('1'))
N(2 I('2'))
N(3 I('3'))
P(1 I('1'))
P(2 I('2'))
P(3 I('3'))
)
X(INV
N(1 I('1'))
N(2 I('2'))
N(3 I('3'))
N(4 I('4'))
N(5 I('5'))
N(6 I('6'))
N(7 I('7'))
N(8 I('8'))
P(1 I('1'))
P(2 I('2'))
P(3 I('3'))
P(4 I('4'))
P(5 I('5'))
P(6 I('6'))
P(7 I('7'))
P(8 I('8'))
D(1 PMOS
I($1)
E(L 0.25)
E(W 0.95)
E(AS 0.79325)
E(AD 0.26125)
E(PS 3.57)
E(PD 1.5)
T(S 4)
T(G 3)
T(D 2)
T(B 4)
)
D(2 PMOS
I($2)
E(L 0.25)
E(W 0.95)
E(AS 0.26125)
E(AD 0.03325)
E(PS 1.5)
E(PD 1.97)
T(S 2)
T(G 7)
T(D 5)
T(B 2)
)
D(3 NMOS
I($3)
E(L 0.25)
E(W 0.95)
E(AS 0.79325)
E(AD 0.26125)
E(PS 3.57)
E(PD 1.5)
T(S 4)
T(G 3)
T(D 1)
T(B 4)
)
D(4 NMOS
I($4)
E(L 0.25)
E(W 0.95)
E(AS 0.26125)
E(AD 0.03325)
E(PS 1.5)
E(PD 1.97)
T(S 1)
T(G 8)
T(D 6)
T(B 1)
)
X(1 TRANS I($1)
P(0 4)
P(1 1)
P(2 3)
)
X(2 TRANS I($2)
P(0 4)
P(1 2)
P(2 3)
)
)
X(INV3
N(1 I('1'))
N(2 I('2'))
N(3 I('3'))
N(4 I('4'))
N(5 I('5'))
N(6 I('6'))
N(7 I('7'))
N(8 I('8'))
N(9 I('9'))
N(10 I('10'))
N(11 I('11'))
N(12 I('12'))
P(1 I('1'))
P(2 I('2'))
P(3 I('3'))
P(4 I('4'))
P(5 I('5'))
P(6 I('6'))
P(7 I('7'))
P(8 I('8'))
P(9 I('9'))
P(10 I('10'))
P(11 I('11'))
P(12 I('12'))
X(1 INV I($1)
P(0 12)
P(1 11)
P(2 3)
P(3 10)
P(4 8)
P(5 6)
P(6 1)
P(7 5)
)
X(2 INV I($2)
P(0 12)
P(1 11)
P(2 4)
P(3 7)
P(4 9)
P(5 9)
P(6 2)
P(7 2)
)
X(3 INV I($3)
P(0 12)
P(1 11)
P(2 2)
P(3 9)
P(4 7)
P(5 7)
P(6 4)
P(7 4)
)
)
X(INV2
N(1 I('1'))
N(2 I('2'))
N(3 I('3'))
N(4 I('4'))
N(5 I('5'))
N(6 I('6'))
N(7 I('7'))
N(8 I('8'))
N(9 I('9'))
N(10 I('10'))
N(11 I('11'))
N(12 I('12'))
N(13 I('13'))
N(14 I('14'))
P(1 I('1'))
P(2 I('2'))
P(3 I('3'))
P(4 I('4'))
P(5 I('5'))
P(6 I('6'))
P(7 I('7'))
P(8 I('8'))
P(9 I('9'))
P(10 I('10'))
P(11 I('11'))
P(12 I('12'))
P(13 I('13'))
P(14 I('14'))
X(1 INV I($1)
P(0 14)
P(1 13)
P(2 3)
P(3 11)
P(4 9)
P(5 7)
P(6 1)
P(7 5)
)
X(2 INV I($2)
P(0 14)
P(1 13)
P(2 4)
P(3 12)
P(4 10)
P(5 8)
P(6 2)
P(7 6)
)
)
X(INVCHAIN
N(1 I('9'))
N(2 I('7'))
N(3 I('8'))
N(4 I('6'))
N(5 I('5'))
N(6 I('1'))
N(7 I('3'))
N(8 I('2'))
N(9 I('13'))
N(10 I('14'))
N(11 I('11'))
N(12 I('10'))
N(13 I('12'))
N(14 I('4'))
X(1 INV3 I($1)
P(0 1)
P(1 2)
P(2 3)
P(3 4)
P(4 1)
P(5 5)
P(6 6)
P(7 5)
P(8 7)
P(9 8)
P(10 9)
P(11 10)
)
X(2 INV2 I($2)
P(0 3)
P(1 11)
P(2 1)
P(3 12)
P(4 3)
P(5 11)
P(6 8)
P(7 13)
P(8 8)
P(9 13)
P(10 5)
P(11 14)
P(12 9)
P(13 10)
)
X(3 INV I($3)
P(0 10)
P(1 9)
P(2 11)
P(3 13)
P(4 14)
P(5 14)
P(6 12)
P(7 12)
)
)
)
Z(
X(() TRANS 0
Z(
)
)
X(INV INV S
Z(
)
)
X(INV2 INV2 S
Z(
)
)
X(INV3 INV3 S
Z(
)
)
X(INVCHAIN INVCHAIN S
Z(
)
)
)

85
testdata/lvs/invchain_for_cheat.cir vendored Normal file
View File

@ -0,0 +1,85 @@
* cell INVCHAIN
.SUBCKT INVCHAIN
* cell instance $1 r0 *1 -1.5,-0.8
X$1 9 7 8 6 9 5 1 5 3 2 13 14 INV3
* cell instance $2 r0 *1 2.6,-0.8
X$2 8 11 9 10 8 11 2 12 2 12 5 4 13 14 INV2
* cell instance $3 m90 *1 7.4,0
X$3 14 13 11 12 4 4 10 10 INV
.ENDS INVCHAIN
* cell INV3
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
.SUBCKT INV3 1 2 3 4 5 6 7 8 9 10 11 12
* cell instance $1 r0 *1 4.8,0.8
X$1 12 11 3 10 8 6 1 5 INV
* cell instance $2 r0 *1 1.5,0.8
X$2 12 11 4 7 9 9 2 2 INV
* cell instance $3 m90 *1 2.3,0.8
X$3 12 11 2 9 7 7 4 4 INV
.ENDS INV3
* cell INV2
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
.SUBCKT INV2 1 2 3 4 5 6 7 8 9 10 11 12 13 14
* cell instance $1 m90 *1 1.5,0.8
X$1 14 13 3 11 9 7 1 5 INV
* cell instance $2 r0 *1 4,0.8
X$2 14 13 4 12 10 8 2 6 INV
.ENDS INV2
* cell INV
* pin
* pin
* pin
* pin
* pin
* pin
* pin
* pin
.SUBCKT INV 1 2 3 4 5 6 7 8
* cell instance $1 r0 *1 0,0
X$1 4 1 3 TRANS
* cell instance $2 r0 *1 0,2.8
X$2 4 2 3 TRANS
* device instance $1 r0 *1 0,2.8 PMOS
M$1 4 3 2 4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U PD=1.5U
* device instance $2 r0 *1 0.8,2.8 PMOS
M$2 2 7 5 2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U PD=1.97U
* device instance $3 r0 *1 0,0 NMOS
M$3 4 3 1 4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U PD=1.5U
* device instance $4 r0 *1 0.8,0 NMOS
M$4 1 8 6 1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U PD=1.97U
.ENDS INV
* cell TRANS
* pin
* pin
* pin
.SUBCKT TRANS 1 2 3
.ENDS TRANS

BIN
testdata/lvs/invchain_for_cheat.gds vendored Normal file

Binary file not shown.

102
testdata/lvs/ringo_layout_var.cir vendored Normal file
View File

@ -0,0 +1,102 @@
* Extracted by KLayout
* cell RINGO
* pin FB
* pin VDD
* pin OUT
* pin ENABLE
* pin VSS
.SUBCKT RINGO 11 12 13 14 15
* net 11 FB
* net 12 VDD
* net 13 OUT
* net 14 ENABLE
* net 15 VSS
* cell instance $1 r0 *1 1.8,0
X$1 12 1 15 12 11 14 15 ND2X1
* cell instance $2 r0 *1 4.2,0
X$2 12 2 15 12 1 15 INVX1B
* cell instance $3 r0 *1 6,0
X$3 12 3 15 12 2 15 INVX1
* cell instance $4 r0 *1 7.8,0
X$4 12 4 15 12 3 15 INVX1B
* cell instance $5 r0 *1 9.6,0
X$5 12 5 15 12 4 15 INVX1
* cell instance $6 r0 *1 11.4,0
X$6 12 6 15 12 5 15 INVX1B
* cell instance $7 r0 *1 13.2,0
X$7 12 7 15 12 6 15 INVX1
* cell instance $8 r0 *1 15,0
X$8 12 8 15 12 7 15 INVX1
* cell instance $9 r0 *1 16.8,0
X$9 12 9 15 12 8 15 INVX1
* cell instance $10 r0 *1 18.6,0
X$10 12 10 15 12 9 15 INVX1
* cell instance $11 r0 *1 20.4,0
X$11 12 11 15 12 10 15 INVX1
* cell instance $12 r0 *1 22.2,0
X$12 12 13 15 12 11 15 INVX1
.ENDS RINGO
* cell INVX1B
* pin VDD
* pin OUT
* pin VSS
* pin
* pin IN
* pin SUBSTRATE
.SUBCKT INVX1B 1 2 3 4 5 6
* net 1 VDD
* net 2 OUT
* net 3 VSS
* net 5 IN
* net 6 SUBSTRATE
* device instance $1 r0 *1 0.85,5.8 PMOS
M$1 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
* device instance $2 r0 *1 0.85,2.135 NMOS
M$2 3 5 2 6 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
.ENDS INVX1B
* cell INVX1
* pin VDD
* pin OUT
* pin VSS
* pin
* pin IN
* pin SUBSTRATE
.SUBCKT INVX1 1 2 3 4 5 6
* net 1 VDD
* net 2 OUT
* net 3 VSS
* net 5 IN
* net 6 SUBSTRATE
* device instance $1 r0 *1 0.85,5.8 PMOS
M$1 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
* device instance $2 r0 *1 0.85,2.135 NMOS
M$2 3 5 2 6 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
.ENDS INVX1
* cell ND2X1
* pin VDD
* pin OUT
* pin VSS
* pin
* pin B
* pin A
* pin SUBSTRATE
.SUBCKT ND2X1 1 2 3 4 5 6 7
* net 1 VDD
* net 2 OUT
* net 3 VSS
* net 5 B
* net 6 A
* net 7 SUBSTRATE
* device instance $1 r0 *1 0.85,5.8 PMOS
M$1 2 6 1 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.3375P PS=3.85U PD=1.95U
* device instance $2 r0 *1 1.55,5.8 PMOS
M$2 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.3375P AD=0.6375P PS=1.95U PD=3.85U
* device instance $3 r0 *1 0.85,2.135 NMOS
M$3 3 6 8 7 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.21375P PS=2.75U PD=1.4U
* device instance $4 r0 *1 1.55,2.135 NMOS
M$4 8 5 2 7 NMOS L=0.25U W=0.95U AS=0.21375P AD=0.40375P PS=1.4U PD=2.75U
.ENDS ND2X1

BIN
testdata/lvs/ringo_layout_var.gds vendored Normal file

Binary file not shown.

78
testdata/lvs/ringo_layout_var.lvs vendored Normal file
View File

@ -0,0 +1,78 @@
source($lvs_test_source, "RINGO")
report_lvs($lvs_test_target_lvsdb, true)
target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
# both INVX1 and INVX1B are the same schematic cell
same_circuits("INVX1", "INVX1")
same_circuits("INVX1B", "INVX1")
schematic("ringo.cir")
deep
# Drawing layers
nwell = input(1, 0)
active = input(2, 0)
pplus = input(3, 0)
nplus = input(4, 0)
poly = input(5, 0)
contact = input(8, 0)
metal1 = input(9, 0)
via1 = input(10, 0)
metal2 = input(11, 0)
# Bulk layer for terminal provisioning
bulk = polygon_layer
# Computed layers
active_in_nwell = active & nwell
pactive = active_in_nwell & pplus
pgate = pactive & poly
psd = pactive - pgate
ntie = active_in_nwell & nplus
active_outside_nwell = active - nwell
nactive = active_outside_nwell & nplus
ngate = nactive & poly
nsd = nactive - ngate
ptie = active_outside_nwell & pplus
# Device extraction
# PMOS transistor device extraction
extract_devices(mos4("PMOS"), { "SD" => psd, "G" => pgate, "W" => nwell,
"tS" => psd, "tD" => psd, "tG" => poly, "tW" => nwell })
# NMOS transistor device extraction
extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk,
"tS" => nsd, "tD" => nsd, "tG" => poly, "tW" => bulk })
# Define connectivity for netlist extraction
# Inter-layer
connect(psd, contact)
connect(nsd, contact)
connect(poly, contact)
connect(ntie, contact)
connect(nwell, ntie)
connect(ptie, contact)
connect(contact, metal1)
connect(metal1, via1)
connect(via1, metal2)
# Global
connect_global(bulk, "SUBSTRATE")
connect_global(ptie, "SUBSTRATE")
# Compare section
netlist.simplify
compare

1076
testdata/lvs/ringo_layout_var.lvsdb.1 vendored Normal file

File diff suppressed because it is too large Load Diff

1076
testdata/lvs/ringo_layout_var.lvsdb.2 vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -57,8 +57,8 @@ M$4 15 1 4 16 NMOS L=0.25U W=0.95U AS=0.21375P AD=0.40375P PS=1.4U PD=2.75U
* net 3 VSS
* net 5 IN
* net 6 SUBSTRATE
* device instance $1 r0 *1 0.85,2.135 NMOS
M$1 3 5 2 6 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
* device instance $2 r0 *1 0.85,5.8 PMOS
M$2 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
* device instance $1 r0 *1 0.85,5.8 PMOS
M$1 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
* device instance $2 r0 *1 0.85,2.135 NMOS
M$2 3 5 2 6 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
.ENDS INVX1

View File

@ -190,20 +190,7 @@ layout(
pin(6 name(SUBSTRATE))
# Devices and their connections
device(1 D$NMOS$2
location(850 2135)
param(L 0.25)
param(W 0.95)
param(AS 0.40375)
param(AD 0.40375)
param(PS 2.75)
param(PD 2.75)
terminal(S 3)
terminal(G 5)
terminal(D 2)
terminal(B 6)
)
device(2 D$PMOS$2
device(1 D$PMOS$2
location(850 5800)
param(L 0.25)
param(W 1.5)
@ -216,6 +203,19 @@ layout(
terminal(D 2)
terminal(B 4)
)
device(2 D$NMOS$2
location(850 2135)
param(L 0.25)
param(W 0.95)
param(AS 0.40375)
param(AD 0.40375)
param(PS 2.75)
param(PD 2.75)
terminal(S 3)
terminal(G 5)
terminal(D 2)
terminal(B 6)
)
)
circuit(RINGO
@ -825,8 +825,8 @@ xref(
pin(5 5 match)
pin(0 0 match)
pin(2 2 match)
device(1 2 match)
device(2 1 match)
device(2 2 match)
device(1 1 match)
)
)
circuit(RINGO RINGO match

View File

@ -163,9 +163,9 @@ layout(
rect(l11 (-1751 1099) (300 1400))
rect(l11 (1100 -1700) (300 300))
rect(l11 (-300 0) (300 1400))
rect(l2 (-375 -1450) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l6 (950 -4890) (425 950))
rect(l2 (-1750 -1450) (425 1500))
rect(l2 (950 -1500) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(3 name(VSS)
rect(l8 (410 1770) (180 180))
@ -371,9 +371,9 @@ layout(
net(2
rect(l8 (4710 3010) (180 180))
rect(l11 (-850 -240) (610 300))
rect(l2 (-1175 1800) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l6 (950 -4890) (425 950))
rect(l2 (-2550 1800) (425 1500))
rect(l2 (950 -1500) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(3
rect(l8 (6510 3010) (180 180))

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,9 @@ target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
schematic("ringo.cir")
# preempt configuration (see below)
same_nets("top", "ENABLE", "RINGO", "ENABLE")
deep
# Drawing layers
@ -71,7 +74,6 @@ connect_global(ptie, "SUBSTRATE")
same_circuits("top", "RINGO")
same_circuits("INV", "INVX1")
same_circuits("DOESNOTEXIST", "DOESNOTEXIST2")
same_nets("top", "ENABLE", "RINGO", "ENABLE")
same_nets("DOESNOTEXIST", "ENABLE", "DOESNOTEXIST2", "ENABLE")
netlist.simplify

View File

@ -7,6 +7,9 @@ target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
schematic("ringo_pin_swapping.cir")
# preempt configuration
equivalent_pins("ND2X1", 4, 5)
deep
# Drawing layers
@ -68,7 +71,6 @@ connect_global(ptie, "SUBSTRATE")
# Compare section
equivalent_pins("ND2X1", 4, 5)
equivalent_pins("DOESNOTEXIST", 4, 5)
netlist.simplify

View File

@ -8,6 +8,9 @@ target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
schematic("ringo.cir")
# preempt configuration
same_device_classes("PM", "PMOS")
deep
# Drawing layers
@ -90,7 +93,6 @@ connect_global(ptie, "SUBSTRATE")
netlist.simplify
same_device_classes("PM", "PMOS")
same_device_classes("NM", "NMOS")
same_device_classes("PMHV", "PMOSHV")
same_device_classes("NMHV", "NMOSHV")

View File

@ -163,9 +163,9 @@ layout(
rect(l11 (-1751 1099) (300 1400))
rect(l11 (1100 -1700) (300 300))
rect(l11 (-300 0) (300 1400))
rect(l2 (-375 -1450) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l6 (950 -4890) (425 950))
rect(l2 (-1750 -1450) (425 1500))
rect(l2 (950 -1500) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(3 name(VSS)
rect(l8 (410 1770) (180 180))
@ -389,8 +389,8 @@ layout(
rect(l11 (1100 -300) (300 300))
rect(l11 (-1101 399) (2 2))
rect(l11 (799 -2101) (300 1400))
rect(l2 (-375 -1450) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l2 (-1750 -1450) (425 1500))
rect(l2 (950 -1500) (425 1500))
)
net(3 name(OUT)
rect(l8 (1110 5160) (180 180))
@ -486,9 +486,9 @@ layout(
net(1
rect(l8 (4710 3010) (180 180))
rect(l11 (-850 -240) (610 300))
rect(l2 (-1175 1800) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l6 (950 -4890) (425 950))
rect(l2 (-2550 1800) (425 1500))
rect(l2 (950 -1500) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(2
rect(l8 (6510 3010) (180 180))
@ -554,9 +554,9 @@ layout(
rect(l2 (1375 -1500) (425 1500))
rect(l2 (1375 -1500) (425 1500))
rect(l2 (1375 -1500) (425 1500))
rect(l2 (4550 -1500) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l2 (-2225 -1500) (425 1500))
rect(l2 (3175 -1500) (425 1500))
rect(l2 (950 -1500) (425 1500))
rect(l2 (-3600 -1500) (425 1500))
rect(l9 (-19575 -450) (500 1500))
rect(l9 (22900 -1500) (500 1500))
)

File diff suppressed because it is too large Load Diff

View File

@ -26,16 +26,16 @@ X$5 6 4 9 6 3 9 INVX1
X$6 6 5 9 6 4 9 INVX1
* cell instance $7 r0 *1 22.2,0
X$7 5 6 7 9 6 9 INVX2
* cell instance $17 r0 *1 7.8,0
X$17 6 12 9 6 10 9 INVX1
* cell instance $18 r0 *1 9.6,0
X$18 6 13 9 6 12 9 INVX1
* cell instance $19 r0 *1 11.4,0
X$19 6 14 9 6 13 9 INVX1
* cell instance $20 r0 *1 13.2,0
X$20 6 15 9 6 14 9 INVX1
* cell instance $21 r0 *1 15,0
X$21 6 11 9 6 15 9 INVX1
* cell instance $13 r0 *1 7.8,0
X$13 6 12 9 6 10 9 INVX1
* cell instance $14 r0 *1 9.6,0
X$14 6 13 9 6 12 9 INVX1
* cell instance $15 r0 *1 11.4,0
X$15 6 14 9 6 13 9 INVX1
* cell instance $16 r0 *1 13.2,0
X$16 6 15 9 6 14 9 INVX1
* cell instance $17 r0 *1 15,0
X$17 6 11 9 6 15 9 INVX1
.ENDS RINGO
* cell INVX2

View File

@ -711,7 +711,7 @@ layout(
pin(4 6)
pin(5 9)
)
circuit(17 INVX1 location(7800 0)
circuit(13 INVX1 location(7800 0)
pin(0 6)
pin(1 12)
pin(2 9)
@ -719,7 +719,7 @@ layout(
pin(4 10)
pin(5 9)
)
circuit(18 INVX1 location(9600 0)
circuit(14 INVX1 location(9600 0)
pin(0 6)
pin(1 13)
pin(2 9)
@ -727,7 +727,7 @@ layout(
pin(4 12)
pin(5 9)
)
circuit(19 INVX1 location(11400 0)
circuit(15 INVX1 location(11400 0)
pin(0 6)
pin(1 14)
pin(2 9)
@ -735,7 +735,7 @@ layout(
pin(4 13)
pin(5 9)
)
circuit(20 INVX1 location(13200 0)
circuit(16 INVX1 location(13200 0)
pin(0 6)
pin(1 15)
pin(2 9)
@ -743,7 +743,7 @@ layout(
pin(4 14)
pin(5 9)
)
circuit(21 INVX1 location(15000 0)
circuit(17 INVX1 location(15000 0)
pin(0 6)
pin(1 11)
pin(2 9)
@ -1147,11 +1147,11 @@ xref(
pin(4 0 match)
circuit(2 2 match)
circuit(3 3 match)
circuit(17 4 match)
circuit(18 5 match)
circuit(19 6 match)
circuit(20 7 match)
circuit(21 8 match)
circuit(13 4 match)
circuit(14 5 match)
circuit(15 6 match)
circuit(16 7 match)
circuit(17 8 match)
circuit(4 9 match)
circuit(5 10 match)
circuit(6 11 match)

View File

@ -163,9 +163,9 @@ layout(
rect(l11 (-1751 1099) (300 1400))
rect(l11 (1100 -1700) (300 300))
rect(l11 (-300 0) (300 1400))
rect(l2 (-375 -1450) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l6 (950 -4890) (425 950))
rect(l2 (-1750 -1450) (425 1500))
rect(l2 (950 -1500) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(3 name(VSS)
rect(l8 (410 1770) (180 180))
@ -389,8 +389,8 @@ layout(
rect(l11 (1100 -300) (300 300))
rect(l11 (-1101 399) (2 2))
rect(l11 (799 -2101) (300 1400))
rect(l2 (-375 -1450) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l2 (-1750 -1450) (425 1500))
rect(l2 (950 -1500) (425 1500))
)
net(3 name(OUT)
rect(l8 (1110 5160) (180 180))
@ -486,9 +486,9 @@ layout(
net(1
rect(l8 (4710 3010) (180 180))
rect(l11 (-850 -240) (610 300))
rect(l2 (-1175 1800) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l6 (950 -4890) (425 950))
rect(l2 (-2550 1800) (425 1500))
rect(l2 (950 -1500) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(2
rect(l8 (6510 3010) (180 180))
@ -554,9 +554,9 @@ layout(
rect(l2 (1375 -1500) (425 1500))
rect(l2 (1375 -1500) (425 1500))
rect(l2 (1375 -1500) (425 1500))
rect(l2 (4550 -1500) (425 1500))
rect(l2 (-1800 -1500) (425 1500))
rect(l2 (-2225 -1500) (425 1500))
rect(l2 (3175 -1500) (425 1500))
rect(l2 (950 -1500) (425 1500))
rect(l2 (-3600 -1500) (425 1500))
rect(l9 (-19575 -450) (500 1500))
rect(l9 (22900 -1500) (500 1500))
)
@ -711,7 +711,7 @@ layout(
pin(4 6)
pin(5 9)
)
circuit(17 INVX1 location(7800 0)
circuit(13 INVX1 location(7800 0)
pin(0 6)
pin(1 12)
pin(2 9)
@ -719,7 +719,7 @@ layout(
pin(4 10)
pin(5 9)
)
circuit(18 INVX1 location(9600 0)
circuit(14 INVX1 location(9600 0)
pin(0 6)
pin(1 13)
pin(2 9)
@ -727,7 +727,7 @@ layout(
pin(4 12)
pin(5 9)
)
circuit(19 INVX1 location(11400 0)
circuit(15 INVX1 location(11400 0)
pin(0 6)
pin(1 14)
pin(2 9)
@ -735,7 +735,7 @@ layout(
pin(4 13)
pin(5 9)
)
circuit(20 INVX1 location(13200 0)
circuit(16 INVX1 location(13200 0)
pin(0 6)
pin(1 15)
pin(2 9)
@ -743,7 +743,7 @@ layout(
pin(4 14)
pin(5 9)
)
circuit(21 INVX1 location(15000 0)
circuit(17 INVX1 location(15000 0)
pin(0 6)
pin(1 11)
pin(2 9)
@ -1147,11 +1147,11 @@ xref(
pin(4 0 match)
circuit(2 2 match)
circuit(3 3 match)
circuit(17 4 match)
circuit(18 5 match)
circuit(19 6 match)
circuit(20 7 match)
circuit(21 8 match)
circuit(13 4 match)
circuit(14 5 match)
circuit(15 6 match)
circuit(16 7 match)
circuit(17 8 match)
circuit(4 9 match)
circuit(5 10 match)
circuit(6 11 match)

File diff suppressed because it is too large Load Diff

View File

@ -191,8 +191,8 @@ circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);
end;
circuit RINGO ();
subcircuit INV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);
subcircuit INV2 $2 (IN=FB,$2=$I38,OUT=$I19,$4=VSS,$5=VDD);
subcircuit INV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$4=VSS,$5=VDD);
subcircuit INV2 $2 (IN=FB,$2=$I38,OUT=$I37,$4=VSS,$5=VDD);
subcircuit INV2 $3 (IN=$I37,$2=$I39,OUT=$I1,$4=VSS,$5=VDD);
subcircuit INV2 $4 (IN=$I1,$2=$I40,OUT=$I2,$4=VSS,$5=VDD);
subcircuit INV2 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD);
subcircuit INV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$4=VSS,$5=VDD);
@ -272,8 +272,8 @@ end;
self.assertEqual(str(l2n.netlist()), """circuit RINGO ();
subcircuit INV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);
subcircuit INV2 $2 (IN=FB,$2=$I38,OUT=$I19,$4=VSS,$5=VDD);
subcircuit INV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$4=VSS,$5=VDD);
subcircuit INV2 $2 (IN=FB,$2=$I38,OUT=$I37,$4=VSS,$5=VDD);
subcircuit INV2 $3 (IN=$I37,$2=$I39,OUT=$I1,$4=VSS,$5=VDD);
subcircuit INV2 $4 (IN=$I1,$2=$I40,OUT=$I2,$4=VSS,$5=VDD);
subcircuit INV2 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD);
subcircuit INV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$4=VSS,$5=VDD);
@ -387,14 +387,14 @@ end;
self.assertEqual(str(l2n.netlist()), """circuit RINGO ();
subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);
subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);
subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);
subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21,$7=VDD);
subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5,$7=VDD);
subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);
subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);
end;
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);
subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2,$7=$I1);
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5,BULK=BULK);
subcircuit INV2 $2 ($1=$I1,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5,BULK=BULK);
end;
circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);
device PMOS $1 (S=$3,G=IN,D=VDD,B=$1) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
@ -416,14 +416,14 @@ end;
self.assertEqual(str(l2n.netlist()), """circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);
subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);
subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);
subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);
subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21,$7=VDD);
subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5,$7=VDD);
subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);
subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);
end;
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);
subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2,$7=$I1);
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5,BULK=BULK);
subcircuit INV2 $2 ($1=$I1,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5,BULK=BULK);
end;
circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);
device PMOS $1 (S=$3,G=IN,D=VDD,B=$1) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);

View File

@ -227,8 +227,8 @@ circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);
end;
circuit RINGO ();
subcircuit INV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);
subcircuit INV2 $2 (IN=FB,$2=$I38,OUT=$I19,$4=VSS,$5=VDD);
subcircuit INV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$4=VSS,$5=VDD);
subcircuit INV2 $2 (IN=FB,$2=$I38,OUT=$I37,$4=VSS,$5=VDD);
subcircuit INV2 $3 (IN=$I37,$2=$I39,OUT=$I1,$4=VSS,$5=VDD);
subcircuit INV2 $4 (IN=$I1,$2=$I40,OUT=$I2,$4=VSS,$5=VDD);
subcircuit INV2 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD);
subcircuit INV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$4=VSS,$5=VDD);
@ -309,8 +309,8 @@ END
assert_equal(l2n.netlist.to_s, <<END)
circuit RINGO ();
subcircuit INV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);
subcircuit INV2 $2 (IN=FB,$2=$I38,OUT=$I19,$4=VSS,$5=VDD);
subcircuit INV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$4=VSS,$5=VDD);
subcircuit INV2 $2 (IN=FB,$2=$I38,OUT=$I37,$4=VSS,$5=VDD);
subcircuit INV2 $3 (IN=$I37,$2=$I39,OUT=$I1,$4=VSS,$5=VDD);
subcircuit INV2 $4 (IN=$I1,$2=$I40,OUT=$I2,$4=VSS,$5=VDD);
subcircuit INV2 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD);
subcircuit INV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$4=VSS,$5=VDD);
@ -425,14 +425,14 @@ END
assert_equal(l2n.netlist.to_s, <<END)
circuit RINGO ();
subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);
subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);
subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);
subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21,$7=VDD);
subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5,$7=VDD);
subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);
subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);
end;
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);
subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2,$7=$I1);
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5,BULK=BULK);
subcircuit INV2 $2 ($1=$I1,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5,BULK=BULK);
end;
circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);
device PMOS $1 (S=$3,G=IN,D=VDD,B=$1) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);
@ -455,14 +455,14 @@ END
assert_equal(l2n.netlist.to_s, <<END)
circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);
subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);
subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);
subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);
subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21,$7=VDD);
subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5,$7=VDD);
subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);
subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);
end;
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);
subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2,$7=$I1);
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5,BULK=BULK);
subcircuit INV2 $2 ($1=$I1,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5,BULK=BULK);
end;
circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);
device PMOS $1 (S=$3,G=IN,D=VDD,B=$1) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);

View File

@ -841,25 +841,36 @@ end;
END
nl3 = nl2.dup
nl2.flatten_circuit(nl2.circuit_by_name("PTRANS"))
nl2.flatten_circuit(nl2.circuit_by_name("NTRANS"))
nl3.flatten_circuit(nl3.circuit_by_name("NTRANS"))
nl3.flatten_circuit(nl3.circuit_by_name("PTRANS"))
assert_equal(nl2.to_s, <<"END")
assert_equal(nl3.to_s, <<"END")
circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);
device PMOS $1 (S=$5,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
device PMOS $2 (S=$5,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
device NMOS $3 (S=$4,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
device NMOS $2 (S=$4,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
device NMOS $3 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
device PMOS $4 (S=$5,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
end;
END
nl3.flatten_circuit("{N,P}TRANS")
assert_equal(nl3.to_s, nl2.to_s)
nl4 = nl2.dup
nl4.flatten_circuit("{P,N}TRANS")
assert_equal(nl4.to_s, nl3.to_s)
nl4 = nl2.dup
nl4.flatten_circuits([ nl4.circuit_by_name("PTRANS"), nl4.circuit_by_name("NTRANS") ])
assert_equal(nl4.to_s, nl3.to_s)
nl2 = nl.dup
nl2.flatten_circuit("*") # smoke test
assert_equal(nl2.to_s, "")
nl2 = nl.dup
cc = []
nl2.each_circuit { |c| cc << c }
nl2.flatten_circuits(cc)
assert_equal(nl2.to_s, "")
end
def test_12_BlankAndPurgeCircuits