mirror of https://github.com/KLayout/klayout.git
commit
a351bc8085
|
|
@ -527,7 +527,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
|
||||||
|
|
||||||
db::BoolAndOrNotLocalOperation op (and_op);
|
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_base_verbosity (base_verbosity ());
|
||||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||||
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
|
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 ()),
|
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&polygons.layout ()),
|
||||||
const_cast<db::Cell *> (&polygons.initial_cell ()),
|
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 ().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_base_verbosity (base_verbosity ());
|
||||||
proc.set_threads (polygons.store ()->threads ());
|
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::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_base_verbosity (base_verbosity ());
|
||||||
proc.set_threads (polygons.store ()->threads ());
|
proc.set_threads (polygons.store ()->threads ());
|
||||||
if (split_after) {
|
if (split_after) {
|
||||||
|
|
@ -1929,7 +1931,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) cons
|
||||||
|
|
||||||
db::InteractingWithEdgeLocalOperation op (inverse);
|
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_base_verbosity (base_verbosity ());
|
||||||
proc.set_threads (polygons.store ()->threads ());
|
proc.set_threads (polygons.store ()->threads ());
|
||||||
if (split_after) {
|
if (split_after) {
|
||||||
|
|
@ -1968,7 +1970,7 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
|
||||||
|
|
||||||
db::PullLocalOperation op (mode, touching);
|
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_base_verbosity (base_verbosity ());
|
||||||
proc.set_threads (polygons.store ()->threads ());
|
proc.set_threads (polygons.store ()->threads ());
|
||||||
if (split_after) {
|
if (split_after) {
|
||||||
|
|
@ -2004,7 +2006,7 @@ DeepRegion::pull_generic (const Edges &other) const
|
||||||
|
|
||||||
db::PullWithEdgeLocalOperation op;
|
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_base_verbosity (base_verbosity ());
|
||||||
proc.set_threads (polygons.store ()->threads ());
|
proc.set_threads (polygons.store ()->threads ());
|
||||||
proc.run (&op, polygons.layer (), other_edges.layer (), dl_out.layer ());
|
proc.run (&op, polygons.layer (), other_edges.layer (), dl_out.layer ());
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,6 @@ DeepLayer &DeepLayer::operator= (const DeepLayer &other)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DeepLayer::~DeepLayer ()
|
DeepLayer::~DeepLayer ()
|
||||||
{
|
{
|
||||||
if (mp_store.get ()) {
|
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
|
void
|
||||||
DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const
|
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;
|
static size_t s_instance_count = 0;
|
||||||
|
|
||||||
DeepShapeStore::DeepShapeStore ()
|
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;
|
++s_instance_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeepShapeStore::DeepShapeStore (const std::string &topcell_name, double dbu)
|
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;
|
++s_instance_count;
|
||||||
|
|
||||||
|
|
@ -292,17 +395,17 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Region ®ion, bool for_n
|
||||||
unsigned int layer = layout ().insert_layer ();
|
unsigned int layer = layout ().insert_layer ();
|
||||||
|
|
||||||
if (max_area_ratio == 0.0) {
|
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) {
|
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::Shapes *shapes = &initial_cell ().shapes (layer);
|
||||||
db::Box world = db::Box::world ();
|
db::Box world = db::Box::world ();
|
||||||
|
|
||||||
// The chain of operators for producing clipped and reduced polygon references
|
// 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::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count);
|
||||||
|
|
||||||
// try to maintain the texts on top level - go through shape iterator
|
// 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)
|
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)
|
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
|
bool DeepShapeStore::is_valid_layout_index (unsigned int n) const
|
||||||
|
|
@ -429,21 +615,6 @@ size_t DeepShapeStore::instance_count ()
|
||||||
return s_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)
|
void DeepShapeStore::add_ref (unsigned int layout, unsigned int layer)
|
||||||
{
|
{
|
||||||
tl::MutexLocker locker (&m_lock);
|
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) {
|
if ((m_layouts[layout]->refs -= 1) <= 0) {
|
||||||
delete m_layouts[layout];
|
delete m_layouts[layout];
|
||||||
m_layouts[layout] = 0;
|
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)
|
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) {
|
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) {
|
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);
|
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);
|
builder.set_target_layer (layer_index);
|
||||||
|
|
||||||
// The chain of operators for producing clipped and reduced polygon references
|
// 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::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count);
|
||||||
db::ClippingHierarchyBuilderShapeReceiver clip (&red);
|
db::ClippingHierarchyBuilderShapeReceiver clip (&red);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
namespace db {
|
namespace db {
|
||||||
|
|
||||||
class DeepShapeStore;
|
class DeepShapeStore;
|
||||||
|
class DeepShapeStoreState;
|
||||||
class Region;
|
class Region;
|
||||||
class Edges;
|
class Edges;
|
||||||
|
|
||||||
|
|
@ -132,6 +133,13 @@ public:
|
||||||
return m_layout;
|
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
|
* @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;
|
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
|
struct DB_PUBLIC RecursiveShapeIteratorCompareForTargetHierarchy
|
||||||
{
|
{
|
||||||
bool operator () (const std::pair<db::RecursiveShapeIterator, db::ICplxTrans> &a, const std::pair<db::RecursiveShapeIterator, db::ICplxTrans> &b) const
|
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
|
* @brief Gets the number of threads
|
||||||
*/
|
*/
|
||||||
int threads () const
|
int threads () const;
|
||||||
{
|
|
||||||
return m_threads;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the maximum vertex count default value
|
* @brief Sets the maximum vertex count default value
|
||||||
|
|
@ -531,10 +582,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Gets the maximum vertex count
|
* @brief Gets the maximum vertex count
|
||||||
*/
|
*/
|
||||||
size_t max_vertex_count () const
|
size_t max_vertex_count () const;
|
||||||
{
|
|
||||||
return m_max_vertex_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the max. area ratio for bounding box vs. polygon area
|
* @brief Sets the max. area ratio for bounding box vs. polygon area
|
||||||
|
|
@ -548,10 +596,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Gets the max. area ratio
|
* @brief Gets the max. area ratio
|
||||||
*/
|
*/
|
||||||
double max_area_ratio () const
|
double max_area_ratio () const;
|
||||||
{
|
|
||||||
return m_max_area_ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the text property name
|
* @brief Sets the text property name
|
||||||
|
|
@ -566,10 +611,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Gets the text property name
|
* @brief Gets the text property name
|
||||||
*/
|
*/
|
||||||
const tl::Variant &text_property_name () const
|
const tl::Variant &text_property_name () const;
|
||||||
{
|
|
||||||
return m_text_property_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the text enlargement value
|
* @brief Sets the text enlargement value
|
||||||
|
|
@ -584,10 +626,45 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Gets the text enlargement value
|
* @brief Gets the text enlargement value
|
||||||
*/
|
*/
|
||||||
int text_enlargement () const
|
int text_enlargement () const;
|
||||||
{
|
|
||||||
return m_text_enlargement;
|
/**
|
||||||
}
|
* @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:
|
private:
|
||||||
friend class DeepLayer;
|
friend class DeepLayer;
|
||||||
|
|
@ -614,11 +691,8 @@ private:
|
||||||
std::map<size_t, std::pair<unsigned int, unsigned int> > m_layers_for_flat;
|
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;
|
std::map<std::pair<unsigned int, unsigned int>, size_t> m_flat_region_id;
|
||||||
layout_map_type m_layout_map;
|
layout_map_type m_layout_map;
|
||||||
int m_threads;
|
DeepShapeStoreState m_state;
|
||||||
double m_max_area_ratio;
|
std::list<DeepShapeStoreState> m_state_stack;
|
||||||
size_t m_max_vertex_count;
|
|
||||||
tl::Variant m_text_property_name;
|
|
||||||
int m_text_enlargement;
|
|
||||||
tl::Mutex m_lock;
|
tl::Mutex m_lock;
|
||||||
|
|
||||||
struct DeliveryMappingCacheKey
|
struct DeliveryMappingCacheKey
|
||||||
|
|
|
||||||
|
|
@ -136,13 +136,13 @@ bool AllDeviceParametersAreEqual::equal (const db::Device &a, const db::Device &
|
||||||
// DeviceClass class implementation
|
// DeviceClass class implementation
|
||||||
|
|
||||||
DeviceClass::DeviceClass ()
|
DeviceClass::DeviceClass ()
|
||||||
: mp_netlist (0), m_strict (false)
|
: m_strict (false), mp_netlist (0)
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceClass::DeviceClass (const DeviceClass &other)
|
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);
|
operator= (other);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,13 @@ template <class Container, class Trans> void insert_transformed (db::Layout & /*
|
||||||
shapes.insert (s.transformed (t));
|
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
|
// Connectivity implementation
|
||||||
|
|
||||||
|
|
@ -1117,11 +1124,11 @@ void hier_clusters<T>::clear ()
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void
|
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 ();
|
clear ();
|
||||||
cell_clusters_box_converter<T> cbc (layout, *this);
|
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
|
namespace
|
||||||
|
|
@ -1159,8 +1166,8 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Constructor
|
* @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)
|
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_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;
|
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*/)
|
void add (const db::Instance *i1, unsigned int /*p1*/, const db::Instance *i2, unsigned int /*p2*/)
|
||||||
{
|
{
|
||||||
|
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;
|
std::vector<ClusterInstElement> p;
|
||||||
db::ICplxTrans t;
|
db::ICplxTrans t;
|
||||||
add_pair (box_type::world (), *i1, p, t, *i2, p, 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,10 +1215,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void finish (const db::Instance *i, unsigned int /*p1*/)
|
void finish (const db::Instance *i, unsigned int /*p1*/)
|
||||||
{
|
{
|
||||||
if (i->size () > 1) {
|
|
||||||
add_single_inst (*i);
|
add_single_inst (*i);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Receiver main event for local-to-instance interactions
|
* @brief Receiver main event for local-to-instance interactions
|
||||||
|
|
@ -1243,16 +1276,45 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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::Layout *mp_layout;
|
||||||
const db::Cell *mp_cell;
|
const db::Cell *mp_cell;
|
||||||
db::connected_clusters<T> *mp_cell_clusters;
|
db::connected_clusters<T> *mp_cell_clusters;
|
||||||
hier_clusters<T> *mp_tree;
|
hier_clusters<T> *mp_tree;
|
||||||
const cell_clusters_box_converter<T> *mp_cbc;
|
const cell_clusters_box_converter<T> *mp_cbc;
|
||||||
const db::Connectivity *mp_conn;
|
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;
|
typedef std::list<std::set<id_type> > join_set_list;
|
||||||
std::map<id_type, typename join_set_list::iterator> m_cm2join_map;
|
std::map<id_type, typename join_set_list::iterator> m_cm2join_map;
|
||||||
join_set_list m_cm2join_sets;
|
join_set_list m_cm2join_sets;
|
||||||
std::list<ClusterInstanceInteraction> m_ci_interactions;
|
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
|
* @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 p2 The instantiation path to the child cell (not including i2)
|
||||||
* @param t2 The accumulated transformation of the path, 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 bb1 = (*mp_cbc) (i1.cell_index ());
|
||||||
box_type b1 = i1.cell_inst ().bbox (*mp_cbc).transformed (t1);
|
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.insert (pp2.end (), p2.begin (), p2.end ());
|
||||||
pp2.push_back (ClusterInstElement (i2.cell_index (), i2.complex_trans (*ii2), i2.prop_id ()));
|
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
|
// dive into cell of ii2
|
||||||
const db::Cell &cell2 = mp_layout->cell (i2.cell_index ());
|
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) {
|
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
|
// dive into cell of ii1
|
||||||
const db::Cell &cell1 = mp_layout->cell (i1.cell_index ());
|
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) {
|
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,
|
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 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);
|
if (is_breakout_cell (mp_breakout_cells, ci1) || is_breakout_cell (mp_breakout_cells, ci2)) {
|
||||||
|
return;
|
||||||
const db::local_clusters<T> &cl1 = mp_tree->clusters_per_cell (ci1);
|
}
|
||||||
const db::local_clusters<T> &cl2 = mp_tree->clusters_per_cell (ci2);
|
|
||||||
|
|
||||||
db::ICplxTrans t1i = t1.inverted ();
|
db::ICplxTrans t1i = t1.inverted ();
|
||||||
db::ICplxTrans t2i = t2.inverted ();
|
db::ICplxTrans t2i = t2.inverted ();
|
||||||
db::ICplxTrans t21 = t1i * t2;
|
db::ICplxTrans t21 = t1i * t2;
|
||||||
|
|
||||||
|
box_type common2 = common.transformed (t2i);
|
||||||
|
|
||||||
// NOTE: make_path may disturb the iteration (because of modification), hence
|
// NOTE: make_path may disturb the iteration (because of modification), hence
|
||||||
// we first collect and then process the interactions.
|
// 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);
|
||||||
|
|
||||||
|
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 ()) {
|
||||||
|
|
||||||
|
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
|
// skip the test, if this cluster doesn't interact with the whole cell2
|
||||||
if (! i->interacts (cell2, t21, *mp_conn)) {
|
if (! i->interacts (cell2, t21, *mp_conn)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
box_type bc1 = common & i->bbox ().transformed (t1);
|
box_type bc2 = (common2 & i->bbox ().transformed (t12));
|
||||||
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (bc1.transformed (t2i)); ! j.at_end (); ++j) {
|
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (bc2); ! j.at_end (); ++j) {
|
||||||
|
|
||||||
if (i->interacts (*j, t21, *mp_conn)) {
|
if (i->interacts (*j, t21, *mp_conn)) {
|
||||||
interactions.push_back (std::make_pair (i->id (), j->id ()));
|
new_interactions.push_back (std::make_pair (i->id (), j->id ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::vector<std::pair<size_t, size_t> >::const_iterator ii = interactions.begin (); ii != interactions.end (); ++ii) {
|
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) {
|
||||||
|
|
||||||
ClusterInstance k1 = make_path (ii->first, p1);
|
ClusterInstance k1 = make_path (ii->first, p1);
|
||||||
ClusterInstance k2 = make_path (ii->second, p2);
|
ClusterInstance k2 = make_path (ii->second, p2);
|
||||||
|
|
||||||
id_type x1 = mp_cell_clusters->find_cluster_with_connection (k1);
|
interacting_clusters.push_back (std::make_pair (k1, k2));
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1427,6 +1488,10 @@ private:
|
||||||
*/
|
*/
|
||||||
void add_single_inst (const db::Instance &i)
|
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 ());
|
box_type bb = (*mp_cbc) (i.cell_index ());
|
||||||
const db::Cell &cell = mp_layout->cell (i.cell_index ());
|
const db::Cell &cell = mp_layout->cell (i.cell_index ());
|
||||||
|
|
||||||
|
|
@ -1456,8 +1521,10 @@ private:
|
||||||
std::vector<ClusterInstElement> pp2;
|
std::vector<ClusterInstElement> pp2;
|
||||||
pp2.push_back (ClusterInstElement (i.cell_index (), i.complex_trans (*ii2), i.prop_id ()));
|
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);
|
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
|
// 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.
|
// 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) {
|
for (db::Cell::touching_iterator jj2 = cell.begin_touching (common.transformed (tt2.inverted ())); ! jj2.at_end (); ++jj2) {
|
||||||
std::vector<ClusterInstElement> p;
|
std::vector<ClusterInstElement> p;
|
||||||
db::ICplxTrans t;
|
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;
|
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)
|
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 b1 = c1.bbox ();
|
||||||
|
|
||||||
box_type bb2 = (*mp_cbc) (i2.cell_index ());
|
box_type bb2 = (*mp_cbc) (i2.cell_index ());
|
||||||
|
|
@ -1519,6 +1592,7 @@ private:
|
||||||
if (b1.touches (ib2) && c1.interacts (cell2, tt2, *mp_conn)) {
|
if (b1.touches (ib2) && c1.interacts (cell2, tt2, *mp_conn)) {
|
||||||
|
|
||||||
pp2.back () = ClusterInstElement (i2.cell_index (), i2.complex_trans (*ii2), i2.prop_id ());
|
pp2.back () = ClusterInstElement (i2.cell_index (), i2.complex_trans (*ii2), i2.prop_id ());
|
||||||
|
|
||||||
add_single_pair (c1, i2.cell_index (), pp2, tt2);
|
add_single_pair (c1, i2.cell_index (), pp2, tt2);
|
||||||
|
|
||||||
// dive into cell of ii2
|
// dive into cell of ii2
|
||||||
|
|
@ -1541,6 +1615,10 @@ private:
|
||||||
void add_single_pair (const local_cluster<T> &c1,
|
void add_single_pair (const local_cluster<T> &c1,
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
if (is_breakout_cell (mp_breakout_cells, ci2)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: make_path may disturb the iteration (because of modification), hence
|
// NOTE: make_path may disturb the iteration (because of modification), hence
|
||||||
// we first collect and then process the interactions.
|
// we first collect and then process the interactions.
|
||||||
|
|
||||||
|
|
@ -1638,6 +1716,58 @@ private:
|
||||||
{
|
{
|
||||||
return mp_tree->make_path (*mp_layout, *mp_cell, id, path);
|
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>
|
template <class T>
|
||||||
|
|
@ -1793,7 +1923,7 @@ hier_clusters<T>::make_path (const db::Layout &layout, const db::Cell &cell, siz
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void
|
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")));
|
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
|
// 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::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);
|
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);
|
todo.push_back (*c);
|
||||||
} else {
|
} else {
|
||||||
tl_assert (! todo.empty ());
|
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 ());
|
done.insert (todo.begin (), todo.end ());
|
||||||
todo.clear ();
|
todo.clear ();
|
||||||
todo.push_back (*c);
|
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>
|
template <class T>
|
||||||
void
|
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) {
|
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;
|
++progress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1952,7 +2084,7 @@ private:
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void
|
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 ()));
|
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) {
|
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
|
// NOTE: this is a receiver for both the child-to-child and
|
||||||
// local to child interactions.
|
// 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);
|
cell_inst_clusters_box_converter<T> cibc (cbc);
|
||||||
|
|
||||||
// The box scanner needs pointers so we have to first store the instances
|
// The box scanner needs pointers so we have to first store the instances
|
||||||
|
|
@ -1992,8 +2124,10 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
|
||||||
db::box_scanner<db::Instance, unsigned int> bs (true, desc);
|
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) {
|
for (std::vector<db::Instance>::const_iterator inst = inst_storage.begin (); inst != inst_storage.end (); ++inst) {
|
||||||
|
if (! is_breakout_cell (breakout_cells, inst->cell_index ())) {
|
||||||
bs.insert (inst.operator-> (), 0);
|
bs.insert (inst.operator-> (), 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bs.process (*rec, 1 /*touching*/, cibc);
|
bs.process (*rec, 1 /*touching*/, cibc);
|
||||||
}
|
}
|
||||||
|
|
@ -2026,8 +2160,10 @@ 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) {
|
for (std::vector<db::Instance>::const_iterator inst = inst_storage.begin (); inst != inst_storage.end (); ++inst) {
|
||||||
|
if (! is_breakout_cell (breakout_cells, inst->cell_index ())) {
|
||||||
bs2.insert2 (inst.operator-> (), 0);
|
bs2.insert2 (inst.operator-> (), 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bs2.process (*rec, 1 /*touching*/, local_cluster_box_convert<T> (), cibc);
|
bs2.process (*rec, 1 /*touching*/, local_cluster_box_convert<T> (), cibc);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@
|
||||||
#include "tlEquivalenceClusters.h"
|
#include "tlEquivalenceClusters.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
|
@ -608,6 +610,14 @@ public:
|
||||||
return m_inst_prop_id;
|
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
|
* @brief Transform with the given transformation
|
||||||
*/
|
*/
|
||||||
|
|
@ -722,6 +732,42 @@ private:
|
||||||
size_t m_id;
|
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 hier_clusters;
|
||||||
template <class T> class connected_clusters;
|
template <class T> class connected_clusters;
|
||||||
|
|
||||||
|
|
@ -895,6 +941,7 @@ class DB_PUBLIC hier_clusters
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename local_cluster<T>::box_type box_type;
|
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
|
* @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
|
* @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
|
* @brief Gets the connected clusters for a given cell
|
||||||
|
|
@ -951,9 +998,9 @@ public:
|
||||||
|
|
||||||
private:
|
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_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 (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, tl::RelativeProgress &progress);
|
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 = 0);
|
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;
|
std::map<db::cell_index_type, connected_clusters<T> > m_per_cell_clusters;
|
||||||
int m_base_verbosity;
|
int m_base_verbosity;
|
||||||
|
|
|
||||||
|
|
@ -1046,15 +1046,21 @@ template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::E
|
||||||
// LocalProcessor implementation
|
// LocalProcessor implementation
|
||||||
|
|
||||||
template <class TS, class TI, class TR>
|
template <class TS, class TI, class TR>
|
||||||
local_processor<TS, TI, TR>::local_processor (db::Layout *layout, db::Cell *top)
|
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), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
|
: 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 ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class TS, class TI, class TR>
|
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)
|
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), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
|
: 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 ..
|
// .. 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) {
|
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
|
||||||
unsigned int iid = ++id;
|
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);
|
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);
|
scanner.insert2 (&i->cell_inst (), iid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1276,14 +1282,14 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
|
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);
|
scanner.insert1 (&i->cell_inst (), ++id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intruder_cell) {
|
if (intruder_cell) {
|
||||||
for (db::Cell::const_iterator i = intruder_cell->begin (); !i.at_end (); ++i) {
|
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);
|
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);
|
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) {
|
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);
|
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) {
|
} else if (intruder_cell) {
|
||||||
// TODO: can we confine this search to the subject's (sized) bounding box?
|
// 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) {
|
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);
|
scanner.insert2 (&i->cell_inst (), ++inst_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -368,8 +368,8 @@ template <class TS, class TI, class TR>
|
||||||
class DB_PUBLIC local_processor
|
class DB_PUBLIC local_processor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
local_processor (db::Layout *layout, db::Cell *top);
|
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);
|
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 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_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;
|
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;
|
const db::Layout *mp_intruder_layout;
|
||||||
db::Cell *mp_subject_top;
|
db::Cell *mp_subject_top;
|
||||||
const db::Cell *mp_intruder_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;
|
std::string m_description;
|
||||||
unsigned int m_nthreads;
|
unsigned int m_nthreads;
|
||||||
size_t m_max_vertex_count;
|
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 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;
|
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;
|
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 ();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ Library::Library()
|
||||||
}
|
}
|
||||||
|
|
||||||
Library::Library(const Library &d)
|
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 ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
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;
|
return (m_subcircuit_pins.size () + m_terminals.size ()) < 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -380,6 +380,30 @@ void Netlist::purge_circuit (Circuit *circuit)
|
||||||
remove_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)
|
void Netlist::flatten_circuit (Circuit *circuit)
|
||||||
{
|
{
|
||||||
tl_assert (circuit != 0);
|
tl_assert (circuit != 0);
|
||||||
|
|
@ -485,8 +509,16 @@ void Netlist::purge ()
|
||||||
|
|
||||||
Circuit *circuit = c.operator-> ();
|
Circuit *circuit = c.operator-> ();
|
||||||
|
|
||||||
|
// purge floating, disconnected nets
|
||||||
circuit->purge_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
|
// No nets left: delete the subcircuits that refer to us and finally delete the circuit
|
||||||
while (circuit->begin_refs () != circuit->end_refs ()) {
|
while (circuit->begin_refs () != circuit->end_refs ()) {
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void flatten_circuit (Circuit *circuit);
|
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
|
* @brief Flattens the netlist
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,18 @@
|
||||||
// (applies to circuits, device classes)
|
// (applies to circuits, device classes)
|
||||||
#define COMPARE_CASE_INSENSITIVE
|
#define COMPARE_CASE_INSENSITIVE
|
||||||
|
|
||||||
|
// A constant indicating a failed match
|
||||||
|
const size_t failed_match = std::numeric_limits<size_t>::max ();
|
||||||
|
|
||||||
|
// A constant indicating an unknown match
|
||||||
|
// const size_t unknown_match = std::numeric_limits<size_t>::max () - 1;
|
||||||
|
|
||||||
|
// A constant indicating an invalid ID
|
||||||
|
const size_t invalid_id = std::numeric_limits<size_t>::max ();
|
||||||
|
|
||||||
|
// A constant indicating an unknown ID
|
||||||
|
const size_t unknown_id = std::numeric_limits<size_t>::max () - 1;
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -320,7 +332,7 @@ public:
|
||||||
} else if (! ca) {
|
} else if (! ca) {
|
||||||
same (cb, ca);
|
same (cb, ca);
|
||||||
} else if (! cb) {
|
} else if (! cb) {
|
||||||
// makeing a object same as null will make this device being ignored
|
// making a object same as null will make this device being ignored
|
||||||
m_cat_by_ptr [ca] = 0;
|
m_cat_by_ptr [ca] = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -489,13 +501,10 @@ public:
|
||||||
void same_circuit (const db::Circuit *ca, const db::Circuit *cb)
|
void same_circuit (const db::Circuit *ca, const db::Circuit *cb)
|
||||||
{
|
{
|
||||||
// no arbitrary cross-pairing
|
// no arbitrary cross-pairing
|
||||||
|
// NOTE: many layout circuits are allowed for one schematic to account for layout alternatives.
|
||||||
if (ca && has_cat_for (ca)) {
|
if (ca && has_cat_for (ca)) {
|
||||||
throw tl::Exception (tl::to_string (tr ("Circuit is already paired with other circuit: ")) + ca->name ());
|
throw tl::Exception (tl::to_string (tr ("Circuit is already paired with other circuit: ")) + ca->name ());
|
||||||
}
|
}
|
||||||
if (cb && has_cat_for (cb)) {
|
|
||||||
throw tl::Exception (tl::to_string (tr ("Circuit is already paired with other circuit: ")) + cb->name ());
|
|
||||||
}
|
|
||||||
|
|
||||||
generic_categorizer<db::Circuit>::same (ca, cb);
|
generic_categorizer<db::Circuit>::same (ca, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -663,12 +672,9 @@ public:
|
||||||
std::string to_string () const
|
std::string to_string () const
|
||||||
{
|
{
|
||||||
if (is_for_subcircuit ()) {
|
if (is_for_subcircuit ()) {
|
||||||
size_t pin_id1 = std::numeric_limits<size_t>::max () - m_id1;
|
|
||||||
size_t pin_id2 = m_id2;
|
|
||||||
const db::SubCircuit *sc = subcircuit_pair ().first;
|
const db::SubCircuit *sc = subcircuit_pair ().first;
|
||||||
const db::Circuit *c = sc->circuit_ref ();
|
const db::Circuit *c = sc->circuit_ref ();
|
||||||
return std::string ("X") + sc->expanded_name () + " " + c->name () + " "
|
return std::string ("X") + sc->expanded_name () + " " + c->name ();
|
||||||
+ "(" + c->pin_by_id (pin_id1)->expanded_name () + ")->(" + c->pin_by_id (pin_id2)->expanded_name () + ")";
|
|
||||||
} else {
|
} else {
|
||||||
size_t term_id1 = m_id1;
|
size_t term_id1 = m_id1;
|
||||||
size_t term_id2 = m_id2;
|
size_t term_id2 = m_id2;
|
||||||
|
|
@ -754,7 +760,17 @@ public:
|
||||||
|
|
||||||
bool has_other () const
|
bool has_other () const
|
||||||
{
|
{
|
||||||
return m_other_net_index != std::numeric_limits<size_t>::max ();
|
return m_other_net_index != invalid_id && m_other_net_index != unknown_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_any_other () const
|
||||||
|
{
|
||||||
|
return m_other_net_index != invalid_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_unknown_other () const
|
||||||
|
{
|
||||||
|
return m_other_net_index == unknown_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t other_net_index () const
|
size_t other_net_index () const
|
||||||
|
|
@ -769,7 +785,7 @@ public:
|
||||||
|
|
||||||
void unset_other_net ()
|
void unset_other_net ()
|
||||||
{
|
{
|
||||||
m_other_net_index = std::numeric_limits<size_t>::max ();
|
m_other_net_index = invalid_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty () const
|
bool empty () const
|
||||||
|
|
@ -857,7 +873,7 @@ std::string indent (size_t depth)
|
||||||
{
|
{
|
||||||
std::string s;
|
std::string s;
|
||||||
for (size_t d = 0; d < depth; ++d) {
|
for (size_t d = 0; d < depth; ++d) {
|
||||||
s += " ";
|
s += "| ";
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -1024,7 +1040,7 @@ private:
|
||||||
// --------------------------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
|
NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
|
||||||
: mp_net (net), m_other_net_index (std::numeric_limits<size_t>::max ())
|
: mp_net (net), m_other_net_index (invalid_id)
|
||||||
{
|
{
|
||||||
if (! net) {
|
if (! net) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1130,7 +1146,7 @@ NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_catego
|
||||||
}
|
}
|
||||||
|
|
||||||
NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
|
NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
|
||||||
: mp_net (0), m_other_net_index (std::numeric_limits<size_t>::max ())
|
: mp_net (0), m_other_net_index (invalid_id)
|
||||||
{
|
{
|
||||||
std::map<const db::Net *, size_t> n2entry;
|
std::map<const db::Net *, size_t> n2entry;
|
||||||
|
|
||||||
|
|
@ -1256,7 +1272,7 @@ NetGraphNode::to_string () const
|
||||||
res += "(null)";
|
res += "(null)";
|
||||||
}
|
}
|
||||||
res += "]";
|
res += "]";
|
||||||
if (m_other_net_index != std::numeric_limits<size_t>::max ()) {
|
if (m_other_net_index != invalid_id) {
|
||||||
res += " (other: #" + tl::to_string (m_other_net_index) + ")";
|
res += " (other: #" + tl::to_string (m_other_net_index) + ")";
|
||||||
}
|
}
|
||||||
res += "\n";
|
res += "\n";
|
||||||
|
|
@ -1406,15 +1422,16 @@ struct NodeRange
|
||||||
class TentativeNodeMapping
|
class TentativeNodeMapping
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TentativeNodeMapping (NetGraph *g1, NetGraph *g2)
|
TentativeNodeMapping ()
|
||||||
: mp_g1 (g1), mp_g2 (g2)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~TentativeNodeMapping ()
|
~TentativeNodeMapping ()
|
||||||
{
|
{
|
||||||
for (std::vector<std::pair<size_t, size_t> >::const_iterator i = m_to_undo.begin (); i != m_to_undo.end (); ++i) {
|
for (std::vector<std::pair<NetGraph *, size_t> >::const_iterator i = m_to_undo.begin (); i != m_to_undo.end (); ++i) {
|
||||||
mp_g1->unidentify (i->first);
|
i->first->unidentify (i->second);
|
||||||
mp_g2->unidentify (i->second);
|
}
|
||||||
|
for (std::vector<std::pair<NetGraph *, size_t> >::const_iterator i = m_to_undo_to_unknown.begin (); i != m_to_undo_to_unknown.end (); ++i) {
|
||||||
|
i->first->identify (i->second, unknown_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1423,17 +1440,40 @@ public:
|
||||||
g1->identify (n1, n2);
|
g1->identify (n1, n2);
|
||||||
g2->identify (n2, n1);
|
g2->identify (n2, n1);
|
||||||
if (nm) {
|
if (nm) {
|
||||||
nm->keep (n1, n2);
|
nm->keep (g1, n1);
|
||||||
|
nm->keep (g2, n2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void map_pair_from_unknown (TentativeNodeMapping *nm, NetGraph *g1, size_t n1, NetGraph *g2, size_t n2)
|
||||||
|
{
|
||||||
|
g1->identify (n1, n2);
|
||||||
|
g2->identify (n2, n1);
|
||||||
|
if (nm) {
|
||||||
|
nm->keep_for_unknown (g1, n1);
|
||||||
|
nm->keep_for_unknown (g2, n2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void map_to_unknown (TentativeNodeMapping *nm, NetGraph *g1, size_t n1)
|
||||||
|
{
|
||||||
|
g1->identify (n1, unknown_id);
|
||||||
|
if (nm) {
|
||||||
|
nm->keep (g1, n1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<size_t, size_t> > m_to_undo;
|
std::vector<std::pair<NetGraph *, size_t> > m_to_undo, m_to_undo_to_unknown;
|
||||||
NetGraph *mp_g1, *mp_g2;
|
|
||||||
|
|
||||||
void keep (size_t n1, size_t n2)
|
void keep (NetGraph *g1, size_t n1)
|
||||||
{
|
{
|
||||||
m_to_undo.push_back (std::make_pair (n1, n2));
|
m_to_undo.push_back (std::make_pair (g1, n1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void keep_for_unknown (NetGraph *g1, size_t n1)
|
||||||
|
{
|
||||||
|
m_to_undo_to_unknown.push_back (std::make_pair (g1, n1));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1564,14 +1604,20 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
||||||
if (tentative) {
|
if (tentative) {
|
||||||
|
|
||||||
if (nodes.size () != other_nodes.size ()) {
|
if (nodes.size () != other_nodes.size ()) {
|
||||||
return std::numeric_limits<size_t>::max ();
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
|
tl::info << indent(depth) << "! rejected branch.";
|
||||||
|
#endif
|
||||||
|
return failed_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1:1 pairing is less strict
|
// 1:1 pairing is less strict
|
||||||
if (nodes.size () > 1 || other_nodes.size () > 1) {
|
if (nodes.size () > 1 || other_nodes.size () > 1) {
|
||||||
for (size_t i = 0; i < nodes.size (); ++i) {
|
for (size_t i = 0; i < nodes.size (); ++i) {
|
||||||
if (! (*nodes[i] == *other_nodes[i])) {
|
if (! (*nodes[i] == *other_nodes[i])) {
|
||||||
return std::numeric_limits<size_t>::max ();
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
|
tl::info << indent(depth) << "! rejected branch.";
|
||||||
|
#endif
|
||||||
|
return failed_match;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1583,8 +1629,11 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
||||||
|
|
||||||
size_t bt_count = derive_node_identities_from_node_set (nodes, other_nodes, depth, n_branch, tentative, with_ambiguous, data);
|
size_t bt_count = derive_node_identities_from_node_set (nodes, other_nodes, depth, n_branch, tentative, with_ambiguous, data);
|
||||||
|
|
||||||
if (bt_count == std::numeric_limits<size_t>::max ()) {
|
if (bt_count == failed_match) {
|
||||||
if (tentative) {
|
if (tentative) {
|
||||||
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
|
tl::info << indent(depth) << "! rejected branch.";
|
||||||
|
#endif
|
||||||
return bt_count;
|
return bt_count;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1593,6 +1642,11 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
|
if (! new_nodes) {
|
||||||
|
tl::info << indent(depth) << "! no updates.";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return new_nodes;
|
return new_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1620,6 +1674,8 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
if (! tentative) {
|
if (! tentative) {
|
||||||
tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||||
|
} else {
|
||||||
|
tl::info << indent(depth) << "tentatively deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -1664,14 +1720,56 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
||||||
++ee_other;
|
++ee_other;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_nodes += derive_node_identities_for_edges (e, ee, e_other, ee_other, net_index, other_net_index, depth, n_branch, tentative, with_ambiguous, data);
|
size_t bt_count = derive_node_identities_for_edges (e, ee, e_other, ee_other, net_index, other_net_index, depth, n_branch, tentative, with_ambiguous, data);
|
||||||
|
if (bt_count == failed_match) {
|
||||||
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
|
tl::info << indent(depth) << "! rejected pair.";
|
||||||
|
#endif
|
||||||
|
return bt_count;
|
||||||
|
} else {
|
||||||
|
new_nodes += bt_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (tentative) {
|
||||||
|
// in tentative mode an exact match is required: no having the same edges for a node disqualifies the node
|
||||||
|
// as matching.
|
||||||
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
|
tl::info << indent(depth) << "! rejected pair for missing edge.";
|
||||||
|
#endif
|
||||||
|
return failed_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = ee;
|
e = ee;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tentative) {
|
||||||
|
|
||||||
|
// in tentative mode, again an exact match is required
|
||||||
|
|
||||||
|
for (NetGraphNode::edge_iterator e_other = n_other->begin (); e_other != n_other->end (); ) {
|
||||||
|
|
||||||
|
NetGraphNode::edge_iterator ee_other = e_other;
|
||||||
|
++ee_other;
|
||||||
|
|
||||||
|
while (ee_other != n_other->end () && ee_other->first == e_other->first) {
|
||||||
|
++ee_other;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetGraphNode::edge_iterator e = n->find_edge (e_other->first);
|
||||||
|
if (e == n->end ()) {
|
||||||
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
|
tl::info << indent(depth) << "! rejected pair for missing edge.";
|
||||||
|
#endif
|
||||||
|
return failed_match;
|
||||||
|
}
|
||||||
|
|
||||||
|
e_other = ee_other;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
if (! tentative && new_nodes > 0) {
|
if (! tentative && new_nodes > 0) {
|
||||||
tl::info << indent(depth) << "finished pair deduction: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name () << " with " << new_nodes << " new pairs";
|
tl::info << indent(depth) << "finished pair deduction: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name () << " with " << new_nodes << " new pairs";
|
||||||
|
|
@ -1689,7 +1787,7 @@ namespace {
|
||||||
bool operator() (const NetGraphNode *a, const NetGraphNode *b) const
|
bool operator() (const NetGraphNode *a, const NetGraphNode *b) const
|
||||||
{
|
{
|
||||||
tl_assert (a->net () && b->net ());
|
tl_assert (a->net () && b->net ());
|
||||||
return a->net ()->name () < b->net ()->name ();
|
return name_compare (a->net ()->name (), b->net ()->name ()) < 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1750,7 +1848,7 @@ static bool net_names_are_different (const db::Net *a, const db::Net *b)
|
||||||
if (! a || ! b || a->name ().empty () || b->name ().empty ()) {
|
if (! a || ! b || a->name ().empty () || b->name ().empty ()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return (a->name () != b->name ());
|
return name_compare (a->name (), b->name ()) != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1758,25 +1856,22 @@ size_t
|
||||||
NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *> &nodes, std::vector<const NetGraphNode *> &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data)
|
NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *> &nodes, std::vector<const NetGraphNode *> &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data)
|
||||||
{
|
{
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
std::string indent;
|
std::string indent_s = indent (depth);
|
||||||
for (size_t d = 0; d < depth; ++d) {
|
indent_s += "*" + tl::to_string (n_branch) + " ";
|
||||||
indent += " ";
|
|
||||||
}
|
|
||||||
indent += "*" + tl::to_string (n_branch) + " ";
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t new_nodes = 0;
|
size_t new_nodes = 0;
|
||||||
|
|
||||||
if (depth > data->max_depth) {
|
if (depth > data->max_depth) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "max. depth exhausted (" << depth + 1 << ">" << data->max_depth << ")";
|
tl::info << indent_s << "max. depth exhausted (" << depth + 1 << ">" << data->max_depth << ")";
|
||||||
#endif
|
#endif
|
||||||
return std::numeric_limits<size_t>::max ();
|
return failed_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodes.size () == 1 && other_nodes.size () == 1) {
|
if (nodes.size () == 1 && other_nodes.size () == 1) {
|
||||||
|
|
||||||
if (! nodes.front ()->has_other () && ! other_nodes.front ()->has_other ()) {
|
if (! nodes.front ()->has_any_other () && ! other_nodes.front ()->has_any_other ()) {
|
||||||
|
|
||||||
// a single candiate: just take this one -> this may render
|
// a single candiate: just take this one -> this may render
|
||||||
// inexact matches, but further propagates net pairing
|
// inexact matches, but further propagates net pairing
|
||||||
|
|
@ -1787,7 +1882,7 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "deduced match (singular): " << nodes.front ()->net ()->expanded_name () << " vs. " << other_nodes.front ()->net ()->expanded_name ();
|
tl::info << indent_s << "deduced match (singular): " << nodes.front ()->net ()->expanded_name () << " vs. " << other_nodes.front ()->net ()->expanded_name ();
|
||||||
#endif
|
#endif
|
||||||
if (data->logger && ! tentative) {
|
if (data->logger && ! tentative) {
|
||||||
if (! (node (ni) == data->other->node (other_ni))) {
|
if (! (node (ni) == data->other->node (other_ni))) {
|
||||||
|
|
@ -1801,7 +1896,7 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
// continue here.
|
// continue here.
|
||||||
size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data);
|
size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data);
|
||||||
|
|
||||||
if (bt_count != std::numeric_limits<size_t>::max ()) {
|
if (bt_count != failed_match) {
|
||||||
new_nodes += bt_count;
|
new_nodes += bt_count;
|
||||||
} else if (tentative) {
|
} else if (tentative) {
|
||||||
return bt_count;
|
return bt_count;
|
||||||
|
|
@ -1809,17 +1904,21 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
|
|
||||||
new_nodes += 1;
|
new_nodes += 1;
|
||||||
|
|
||||||
|
} else if (nodes.front ()->has_unknown_other ()) {
|
||||||
|
|
||||||
|
// accept this solution as the pairing is possible
|
||||||
|
|
||||||
} else if (nodes.front ()->has_other ()) {
|
} else if (nodes.front ()->has_other ()) {
|
||||||
|
|
||||||
// this decision leads to a contradiction
|
// this decision leads to a contradiction
|
||||||
if (data->other->node_index_for_net (other_nodes.front ()->net ()) != nodes.front ()->other_net_index ()) {
|
if (data->other->node_index_for_net (other_nodes.front ()->net ()) != nodes.front ()->other_net_index ()) {
|
||||||
return std::numeric_limits<size_t>::max ();
|
return failed_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// mismatch of assignment state
|
// mismatch of assignment state
|
||||||
return std::numeric_limits<size_t>::max ();
|
return failed_match;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1836,10 +1935,10 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
|
|
||||||
while (n1 != nodes.end () && n2 != other_nodes.end ()) {
|
while (n1 != nodes.end () && n2 != other_nodes.end ()) {
|
||||||
|
|
||||||
if ((*n1)->has_other ()) {
|
if ((*n1)->has_any_other ()) {
|
||||||
++n1;
|
++n1;
|
||||||
continue;
|
continue;
|
||||||
} else if ((*n2)->has_other ()) {
|
} else if ((*n2)->has_any_other ()) {
|
||||||
++n2;
|
++n2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1858,9 +1957,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
++nn1;
|
++nn1;
|
||||||
++nn2;
|
++nn2;
|
||||||
while (nn1 != nodes.end () && nn2 != other_nodes.end ()) {
|
while (nn1 != nodes.end () && nn2 != other_nodes.end ()) {
|
||||||
if ((*nn1)->has_other ()) {
|
if ((*nn1)->has_any_other ()) {
|
||||||
++nn1;
|
++nn1;
|
||||||
} else if ((*nn2)->has_other ()) {
|
} else if ((*nn2)->has_any_other ()) {
|
||||||
++nn2;
|
++nn2;
|
||||||
} else if (! (**nn1 == **n1) || ! (**nn2 == **n2)) {
|
} else if (! (**nn1 == **n1) || ! (**nn2 == **n2)) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -1878,7 +1977,7 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
// in tentative mode ambiguous nodes don't make a match without
|
// in tentative mode ambiguous nodes don't make a match without
|
||||||
// with_ambiguous
|
// with_ambiguous
|
||||||
if (num > 1 && tentative && ! with_ambiguous) {
|
if (num > 1 && tentative && ! with_ambiguous) {
|
||||||
return std::numeric_limits<size_t>::max ();
|
return failed_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
n1 = nn1;
|
n1 = nn1;
|
||||||
|
|
@ -1895,9 +1994,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
// node ranges might have changed - adjust to real count and skip leading pairs assigned already
|
// node ranges might have changed - adjust to real count and skip leading pairs assigned already
|
||||||
|
|
||||||
while (nr->n1 != nr->nn1 && nr->n2 != nr->nn2) {
|
while (nr->n1 != nr->nn1 && nr->n2 != nr->nn2) {
|
||||||
if ((*nr->n1)->has_other ()) {
|
if ((*nr->n1)->has_any_other ()) {
|
||||||
++nr->n1;
|
++nr->n1;
|
||||||
} else if ((*nr->n2)->has_other ()) {
|
} else if ((*nr->n2)->has_any_other ()) {
|
||||||
++nr->n2;
|
++nr->n2;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|
@ -1908,9 +2007,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
std::vector<const NetGraphNode *>::const_iterator i1 = nr->n1, i2 = nr->n2;
|
std::vector<const NetGraphNode *>::const_iterator i1 = nr->n1, i2 = nr->n2;
|
||||||
|
|
||||||
while (i1 != nr->nn1 && i2 != nr->nn2) {
|
while (i1 != nr->nn1 && i2 != nr->nn2) {
|
||||||
if ((*i1)->has_other ()) {
|
if ((*i1)->has_any_other ()) {
|
||||||
++i1;
|
++i1;
|
||||||
} else if ((*i2)->has_other ()) {
|
} else if ((*i2)->has_any_other ()) {
|
||||||
++i2;
|
++i2;
|
||||||
} else {
|
} else {
|
||||||
++nr->num;
|
++nr->num;
|
||||||
|
|
@ -1925,16 +2024,16 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
|
|
||||||
} else if (nr->num == 1) {
|
} else if (nr->num == 1) {
|
||||||
|
|
||||||
if (! (*nr->n1)->has_other () && ! (*nr->n2)->has_other ()) {
|
if (! (*nr->n1)->has_any_other () && ! (*nr->n2)->has_any_other ()) {
|
||||||
|
|
||||||
// in tentative mode, reject this choice if both nets are named and
|
// in tentative mode, reject this choice if both nets are named and
|
||||||
// their names differ -> this favors net matching by name
|
// their names differ -> this favors net matching by name
|
||||||
|
|
||||||
if (tentative && ! data->dont_consider_net_names && net_names_are_different ((*nr->n1)->net (), (*nr->n2)->net ())) {
|
if (tentative && ! data->dont_consider_net_names && net_names_are_different ((*nr->n1)->net (), (*nr->n2)->net ())) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "rejecting pair as names are not identical: " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
tl::info << indent_s << "rejecting pair as names are not identical: " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
||||||
#endif
|
#endif
|
||||||
return std::numeric_limits<size_t>::max ();
|
return failed_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A single candiate: just take this one -> this may render
|
// A single candiate: just take this one -> this may render
|
||||||
|
|
@ -1946,7 +2045,7 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "deduced match (singular): " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
tl::info << indent_s << "deduced match (singular): " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
||||||
#endif
|
#endif
|
||||||
if (data->logger && ! tentative) {
|
if (data->logger && ! tentative) {
|
||||||
if (! (node (ni) == data->other->node (other_ni))) {
|
if (! (node (ni) == data->other->node (other_ni))) {
|
||||||
|
|
@ -1960,41 +2059,45 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
// continue here.
|
// continue here.
|
||||||
size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data);
|
size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data);
|
||||||
|
|
||||||
if (bt_count != std::numeric_limits<size_t>::max ()) {
|
if (bt_count != failed_match) {
|
||||||
new_nodes += bt_count;
|
new_nodes += bt_count;
|
||||||
new_nodes += 1;
|
new_nodes += 1;
|
||||||
} else if (tentative) {
|
} else if (tentative) {
|
||||||
new_nodes = bt_count;
|
new_nodes = bt_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if ((*nr->n1)->has_unknown_other ()) {
|
||||||
|
|
||||||
|
// accept any other net
|
||||||
|
|
||||||
} else if ((*nr->n1)->has_other ()) {
|
} else if ((*nr->n1)->has_other ()) {
|
||||||
|
|
||||||
// this decision leads to a contradiction
|
// this decision leads to a contradiction
|
||||||
if (data->other->node_index_for_net ((*nr->n2)->net ()) != (*nr->n1)->other_net_index ()) {
|
if (data->other->node_index_for_net ((*nr->n2)->net ()) != (*nr->n1)->other_net_index ()) {
|
||||||
return std::numeric_limits<size_t>::max ();
|
return failed_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// mismatch of assignment state
|
// mismatch of assignment state
|
||||||
return std::numeric_limits<size_t>::max ();
|
return failed_match;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (nr->num * n_branch > data->max_n_branch) {
|
} else if (nr->num * n_branch > data->max_n_branch) {
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch.";
|
tl::info << indent_s << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch.";
|
||||||
#endif
|
#endif
|
||||||
return std::numeric_limits<size_t>::max ();
|
return failed_match;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "analyzing ambiguity group with " << nr->num << " members";
|
tl::info << indent_s << "analyzing ambiguity group with " << nr->num << " members";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// sort the ambiguity group such that net names
|
// sort the ambiguity group such that net names match best
|
||||||
|
|
||||||
std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> > pairs;
|
std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> > pairs;
|
||||||
tl::equivalence_clusters<const NetGraphNode *> equivalent_other_nodes;
|
tl::equivalence_clusters<const NetGraphNode *> equivalent_other_nodes;
|
||||||
|
|
@ -2004,20 +2107,39 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
sort_node_range_by_best_match (*nr);
|
sort_node_range_by_best_match (*nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::vector<const NetGraphNode *>::const_iterator i1 = nr->n1; i1 != nr->nn1; ++i1) {
|
{
|
||||||
|
|
||||||
if ((*i1)->has_other ()) {
|
// marks the nodes from the ambiguity group as unknown so we don't revisit them (causing deep recursion)
|
||||||
continue;
|
TentativeNodeMapping tn2unknown;
|
||||||
|
|
||||||
|
// collect and mark the ambiguity combinations to consider
|
||||||
|
std::vector<std::vector<const NetGraphNode *>::const_iterator> iters1, iters2;
|
||||||
|
|
||||||
|
for (std::vector<const NetGraphNode *>::const_iterator i1 = nr->n1; i1 != nr->nn1; ++i1) {
|
||||||
|
if (! (*i1)->has_any_other ()) {
|
||||||
|
iters1.push_back (i1);
|
||||||
|
size_t ni = node_index_for_net ((*i1)->net ());
|
||||||
|
TentativeNodeMapping::map_to_unknown (&tn2unknown, this, ni);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<const NetGraphNode *>::const_iterator i2 = nr->n2; i2 != nr->nn2; ++i2) {
|
||||||
|
if (! (*i2)->has_any_other ()) {
|
||||||
|
iters2.push_back (i2);
|
||||||
|
size_t other_ni = data->other->node_index_for_net ((*i2)->net ());
|
||||||
|
TentativeNodeMapping::map_to_unknown (&tn2unknown, data->other, other_ni);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<std::vector<const NetGraphNode *>::const_iterator>::const_iterator ii1 = iters1.begin (); ii1 != iters1.end (); ++ii1) {
|
||||||
|
|
||||||
|
std::vector<const NetGraphNode *>::const_iterator i1 = *ii1;
|
||||||
|
|
||||||
bool any = false;
|
bool any = false;
|
||||||
|
|
||||||
std::vector<const NetGraphNode *>::const_iterator i2;
|
for (std::vector<std::vector<const NetGraphNode *>::const_iterator>::const_iterator ii2 = iters2.begin (); ii2 != iters2.end (); ++ii2) {
|
||||||
for (i2 = nr->n2; i2 != nr->nn2; ++i2) {
|
|
||||||
|
|
||||||
if ((*i2)->has_other ()) {
|
std::vector<const NetGraphNode *>::const_iterator i2 = *ii2;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (seen.find (*i2) != seen.end ()) {
|
if (seen.find (*i2) != seen.end ()) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2026,19 +2148,19 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
size_t ni = node_index_for_net ((*i1)->net ());
|
size_t ni = node_index_for_net ((*i1)->net ());
|
||||||
size_t other_ni = data->other->node_index_for_net ((*i2)->net ());
|
size_t other_ni = data->other->node_index_for_net ((*i2)->net ());
|
||||||
|
|
||||||
TentativeNodeMapping tn (this, data->other);
|
TentativeNodeMapping tn;
|
||||||
TentativeNodeMapping::map_pair (&tn, this, ni, data->other, other_ni);
|
TentativeNodeMapping::map_pair_from_unknown (&tn, this, ni, data->other, other_ni);
|
||||||
|
|
||||||
// try this candidate in tentative mode
|
// try this candidate in tentative mode
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "trying in tentative mode: " << (*i1)->net ()->expanded_name () << " vs. " << (*i2)->net ()->expanded_name ();
|
tl::info << indent_s << "trying in tentative mode: " << (*i1)->net ()->expanded_name () << " vs. " << (*i2)->net ()->expanded_name ();
|
||||||
#endif
|
#endif
|
||||||
size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, &tn, with_ambiguous, data);
|
size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, &tn, with_ambiguous, data);
|
||||||
|
|
||||||
if (bt_count != std::numeric_limits<size_t>::max ()) {
|
if (bt_count != failed_match) {
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "match found";
|
tl::info << indent_s << "match found";
|
||||||
#endif
|
#endif
|
||||||
// we have a match ...
|
// we have a match ...
|
||||||
|
|
||||||
|
|
@ -2064,10 +2186,12 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
|
|
||||||
if (! any && tentative) {
|
if (! any && tentative) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "mismatch.";
|
tl::info << indent_s << "mismatch.";
|
||||||
#endif
|
#endif
|
||||||
// a mismatch - stop here.
|
// a mismatch - stop here.
|
||||||
return std::numeric_limits<size_t>::max ();
|
return failed_match;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2085,9 +2209,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
if (equivalent_other_nodes.has_attribute (p->second)) {
|
if (equivalent_other_nodes.has_attribute (p->second)) {
|
||||||
tl::info << indent << "deduced ambiguous match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
tl::info << indent_s << "deduced ambiguous match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
||||||
} else {
|
} else {
|
||||||
tl::info << indent << "deduced match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
tl::info << indent_s << "deduced match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (data->logger) {
|
if (data->logger) {
|
||||||
|
|
@ -2108,7 +2232,7 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
size_t ni = node_index_for_net (p->first->net ());
|
size_t ni = node_index_for_net (p->first->net ());
|
||||||
|
|
||||||
size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, tentative, with_ambiguous, data);
|
size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, tentative, with_ambiguous, data);
|
||||||
tl_assert (bt_count != std::numeric_limits<size_t>::max ());
|
tl_assert (bt_count != failed_match);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2126,7 +2250,7 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << indent << "finished analysis of ambiguity group with " << nr->num << " members";
|
tl::info << indent_s << "finished analysis of ambiguity group with " << nr->num << " members";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2150,8 +2274,8 @@ NetlistComparer::NetlistComparer (NetlistCompareLogger *logger)
|
||||||
m_cap_threshold = -1.0; // not set
|
m_cap_threshold = -1.0; // not set
|
||||||
m_res_threshold = -1.0; // not set
|
m_res_threshold = -1.0; // not set
|
||||||
|
|
||||||
m_max_depth = 8;
|
m_max_depth = 50;
|
||||||
m_max_n_branch = 100;
|
m_max_n_branch = 500;
|
||||||
|
|
||||||
m_dont_consider_net_names = false;
|
m_dont_consider_net_names = false;
|
||||||
}
|
}
|
||||||
|
|
@ -2227,39 +2351,39 @@ NetlistComparer::unmatched_circuits (db::Netlist *a, db::Netlist *b, std::vector
|
||||||
// we need to create a copy because this method is supposed to be const.
|
// we need to create a copy because this method is supposed to be const.
|
||||||
db::CircuitCategorizer circuit_categorizer = *mp_circuit_categorizer;
|
db::CircuitCategorizer circuit_categorizer = *mp_circuit_categorizer;
|
||||||
|
|
||||||
std::map<size_t, std::pair<db::Circuit *, db::Circuit *> > cat2circuits;
|
std::map<size_t, std::pair<std::vector<db::Circuit *>, std::vector<db::Circuit *> > > cat2circuits;
|
||||||
|
|
||||||
for (db::Netlist::circuit_iterator i = a->begin_circuits (); i != a->end_circuits (); ++i) {
|
for (db::Netlist::circuit_iterator i = a->begin_circuits (); i != a->end_circuits (); ++i) {
|
||||||
size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ());
|
size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ());
|
||||||
if (cat) {
|
if (cat) {
|
||||||
cat2circuits[cat].first = i.operator-> ();
|
cat2circuits[cat].first.push_back (i.operator-> ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (db::Netlist::circuit_iterator i = b->begin_circuits (); i != b->end_circuits (); ++i) {
|
for (db::Netlist::circuit_iterator i = b->begin_circuits (); i != b->end_circuits (); ++i) {
|
||||||
size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ());
|
size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ());
|
||||||
if (cat) {
|
if (cat) {
|
||||||
cat2circuits[cat].second = i.operator-> ();
|
cat2circuits[cat].second.push_back (i.operator-> ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t na = 0, nb = 0;
|
size_t na = 0, nb = 0;
|
||||||
for (std::map<size_t, std::pair<db::Circuit *, db::Circuit *> >::const_iterator i = cat2circuits.begin (); i != cat2circuits.end (); ++i) {
|
for (std::map<size_t, std::pair<std::vector<db::Circuit *>, std::vector<db::Circuit *> > >::const_iterator i = cat2circuits.begin (); i != cat2circuits.end (); ++i) {
|
||||||
if (! i->second.first) {
|
if (i->second.first.empty ()) {
|
||||||
++nb;
|
nb += i->second.second.size ();
|
||||||
} else if (! i->second.second) {
|
} else if (i->second.second.empty ()) {
|
||||||
++na;
|
na += i->second.first.size ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
in_a.reserve (na);
|
in_a.reserve (na);
|
||||||
in_b.reserve (nb);
|
in_b.reserve (nb);
|
||||||
|
|
||||||
for (std::map<size_t, std::pair<db::Circuit *, db::Circuit *> >::const_iterator i = cat2circuits.begin (); i != cat2circuits.end (); ++i) {
|
for (std::map<size_t, std::pair<std::vector<db::Circuit *>, std::vector<db::Circuit *> > >::const_iterator i = cat2circuits.begin (); i != cat2circuits.end (); ++i) {
|
||||||
if (! i->second.first) {
|
if (i->second.first.empty ()) {
|
||||||
in_b.push_back (i->second.second);
|
in_b.insert (in_b.end (), i->second.second.begin (), i->second.second.end ());
|
||||||
} else if (! i->second.second) {
|
} else if (i->second.second.empty ()) {
|
||||||
in_a.push_back (i->second.first);
|
in_a.insert (in_a.end (), i->second.first.begin (), i->second.first.end ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2274,13 +2398,13 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
||||||
|
|
||||||
bool good = true;
|
bool good = true;
|
||||||
|
|
||||||
std::map<size_t, std::pair<const db::Circuit *, const db::Circuit *> > cat2circuits;
|
std::map<size_t, std::pair<std::vector<const db::Circuit *>, std::vector<const db::Circuit *> > > cat2circuits;
|
||||||
std::set<const db::Circuit *> verified_circuits_a, verified_circuits_b;
|
std::set<const db::Circuit *> verified_circuits_a, verified_circuits_b;
|
||||||
|
|
||||||
for (db::Netlist::const_circuit_iterator i = a->begin_circuits (); i != a->end_circuits (); ++i) {
|
for (db::Netlist::const_circuit_iterator i = a->begin_circuits (); i != a->end_circuits (); ++i) {
|
||||||
size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ());
|
size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ());
|
||||||
if (cat) {
|
if (cat) {
|
||||||
cat2circuits[cat].first = i.operator-> ();
|
cat2circuits[cat].first.push_back (i.operator-> ());
|
||||||
} else {
|
} else {
|
||||||
// skip circuit (but count it as verified)
|
// skip circuit (but count it as verified)
|
||||||
verified_circuits_a.insert (i.operator-> ());
|
verified_circuits_a.insert (i.operator-> ());
|
||||||
|
|
@ -2290,7 +2414,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
||||||
for (db::Netlist::const_circuit_iterator i = b->begin_circuits (); i != b->end_circuits (); ++i) {
|
for (db::Netlist::const_circuit_iterator i = b->begin_circuits (); i != b->end_circuits (); ++i) {
|
||||||
size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ());
|
size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ());
|
||||||
if (cat) {
|
if (cat) {
|
||||||
cat2circuits[cat].second = i.operator-> ();
|
cat2circuits[cat].second.push_back (i.operator-> ());
|
||||||
} else {
|
} else {
|
||||||
// skip circuit (but count it as verified)
|
// skip circuit (but count it as verified)
|
||||||
verified_circuits_b.insert (i.operator-> ());
|
verified_circuits_b.insert (i.operator-> ());
|
||||||
|
|
@ -2342,11 +2466,21 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
||||||
|
|
||||||
// check for circuits that don't match
|
// check for circuits that don't match
|
||||||
|
|
||||||
for (std::map<size_t, std::pair<const db::Circuit *, const db::Circuit *> >::const_iterator i = cat2circuits.begin (); i != cat2circuits.end (); ++i) {
|
for (std::map<size_t, std::pair<std::vector<const db::Circuit *>, std::vector<const db::Circuit *> > >::const_iterator i = cat2circuits.begin (); i != cat2circuits.end (); ++i) {
|
||||||
if (! i->second.first || ! i->second.second) {
|
if (i->second.first.empty ()) {
|
||||||
good = false;
|
good = false;
|
||||||
if (mp_logger) {
|
if (mp_logger) {
|
||||||
mp_logger->circuit_mismatch (i->second.first, i->second.second);
|
for (std::vector<const db::Circuit *>::const_iterator j = i->second.second.begin (); j != i->second.second.end (); ++j) {
|
||||||
|
mp_logger->circuit_mismatch (0, *j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i->second.second.empty ()) {
|
||||||
|
good = false;
|
||||||
|
if (mp_logger) {
|
||||||
|
for (std::vector<const db::Circuit *>::const_iterator j = i->second.first.begin (); j != i->second.first.end (); ++j) {
|
||||||
|
mp_logger->circuit_mismatch (*j, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2355,18 +2489,23 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
||||||
|
|
||||||
for (db::Netlist::const_bottom_up_circuit_iterator c = a->begin_bottom_up (); c != a->end_bottom_up (); ++c) {
|
for (db::Netlist::const_bottom_up_circuit_iterator c = a->begin_bottom_up (); c != a->end_bottom_up (); ++c) {
|
||||||
|
|
||||||
size_t ccat = circuit_categorizer.cat_for_circuit (c.operator-> ());
|
const db::Circuit *ca = c.operator-> ();
|
||||||
|
|
||||||
|
size_t ccat = circuit_categorizer.cat_for_circuit (ca);
|
||||||
if (! ccat) {
|
if (! ccat) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<size_t, std::pair<const db::Circuit *, const db::Circuit *> >::const_iterator i = cat2circuits.find (ccat);
|
std::map<size_t, std::pair<std::vector<const db::Circuit *>, std::vector<const db::Circuit *> > >::const_iterator i = cat2circuits.find (ccat);
|
||||||
tl_assert (i != cat2circuits.end ());
|
tl_assert (i != cat2circuits.end ());
|
||||||
|
tl_assert (! i->second.first.empty ());
|
||||||
|
if (i->second.second.empty ()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (i->second.first && i->second.second) {
|
// NOTE: there can only be one schematic circuit
|
||||||
|
tl_assert (i->second.second.size () == size_t (1));
|
||||||
const db::Circuit *ca = i->second.first;
|
const db::Circuit *cb = i->second.second.front ();
|
||||||
const db::Circuit *cb = i->second.second;
|
|
||||||
|
|
||||||
std::vector<std::pair<const Net *, const Net *> > empty;
|
std::vector<std::pair<const Net *, const Net *> > empty;
|
||||||
const std::vector<std::pair<const Net *, const Net *> > *net_identity = ∅
|
const std::vector<std::pair<const Net *, const Net *> > *net_identity = ∅
|
||||||
|
|
@ -2412,8 +2551,6 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mp_logger) {
|
if (mp_logger) {
|
||||||
mp_logger->end_netlist (a, b);
|
mp_logger->end_netlist (a, b);
|
||||||
}
|
}
|
||||||
|
|
@ -2428,7 +2565,7 @@ std::vector<size_t> collect_pins_with_empty_nets (const db::Circuit *c, CircuitP
|
||||||
|
|
||||||
for (db::Circuit::const_pin_iterator p = c->begin_pins (); p != c->end_pins (); ++p) {
|
for (db::Circuit::const_pin_iterator p = c->begin_pins (); p != c->end_pins (); ++p) {
|
||||||
const db::Net *net = c->net_for_pin (p->id ());
|
const db::Net *net = c->net_for_pin (p->id ());
|
||||||
if ((! net || net->is_floating ()) && ! circuit_pin_mapper->is_mapped (c, p->id ())) {
|
if ((! net || net->is_passive ()) && ! circuit_pin_mapper->is_mapped (c, p->id ())) {
|
||||||
pins.push_back (p->id ());
|
pins.push_back (p->id ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2567,7 +2704,7 @@ struct DeviceConnectionDistance
|
||||||
{
|
{
|
||||||
int d = 0.0;
|
int d = 0.0;
|
||||||
for (std::vector<std::pair<size_t, size_t> >::const_iterator i = a.first.begin (), j = b.first.begin (); i != a.first.end () && j != b.first.end (); ++i, ++j) {
|
for (std::vector<std::pair<size_t, size_t> >::const_iterator i = a.first.begin (), j = b.first.begin (); i != a.first.end () && j != b.first.end (); ++i, ++j) {
|
||||||
if (i->second != j->second || i->second == std::numeric_limits<size_t>::max () || j->second == std::numeric_limits<size_t>::max ()) {
|
if (i->second != j->second || i->second == invalid_id || j->second == invalid_id) {
|
||||||
++d;
|
++d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2645,6 +2782,32 @@ void align (Iter i1, Iter i2, Iter j1, Iter j2, Distance distance)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true, if the given net is passive
|
||||||
|
* A passive net does not have devices nor pins except those which are ignored (not mapped).
|
||||||
|
*/
|
||||||
|
static bool is_passive_net (const db::Net *net, const std::map<const db::Circuit *, CircuitMapper> &circuit_and_pin_mapping)
|
||||||
|
{
|
||||||
|
if (net->terminal_count () != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (net->subcircuit_pin_count () == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (db::Net::const_subcircuit_pin_iterator p = net->begin_subcircuit_pins (); p != net->end_subcircuit_pins (); ++p) {
|
||||||
|
const db::Circuit *c = p->subcircuit ()->circuit_ref ();
|
||||||
|
std::map<const db::Circuit *, CircuitMapper>::const_iterator ic;
|
||||||
|
ic = circuit_and_pin_mapping.find (c);
|
||||||
|
if (ic != circuit_and_pin_mapping.end () && ic->second.has_other_pin_for_this_pin (p->pin_id ())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
||||||
db::DeviceCategorizer &device_categorizer,
|
db::DeviceCategorizer &device_categorizer,
|
||||||
|
|
@ -2715,7 +2878,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
||||||
data.logger = mp_logger;
|
data.logger = mp_logger;
|
||||||
|
|
||||||
size_t ni = g1.derive_node_identities (i1 - g1.begin (), 0, 1, 0 /*not tentative*/, pass > 0 /*with ambiguities*/, &data);
|
size_t ni = g1.derive_node_identities (i1 - g1.begin (), 0, 1, 0 /*not tentative*/, pass > 0 /*with ambiguities*/, &data);
|
||||||
if (ni > 0 && ni != std::numeric_limits<size_t>::max ()) {
|
if (ni > 0 && ni != failed_match) {
|
||||||
new_identities += ni;
|
new_identities += ni;
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << ni << " new identities.";
|
tl::info << ni << " new identities.";
|
||||||
|
|
@ -2749,8 +2912,12 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodes.empty () || other_nodes.empty ()) {
|
if (nodes.empty () || other_nodes.empty ()) {
|
||||||
if (! nodes.empty () || ! other_nodes.empty ()) {
|
// active mismatched nodes give an error
|
||||||
good = false;
|
for (std::vector<const NetGraphNode *>::const_iterator n = nodes.begin (); n != nodes.end () && good; ++n) {
|
||||||
|
good = is_passive_net ((*n)->net (), c12_circuit_and_pin_mapping);
|
||||||
|
}
|
||||||
|
for (std::vector<const NetGraphNode *>::const_iterator n = other_nodes.begin (); n != other_nodes.end () && good; ++n) {
|
||||||
|
good = is_passive_net ((*n)->net (), c22_circuit_and_pin_mapping);
|
||||||
}
|
}
|
||||||
// this assumes that we don't gain anything here. Stop now.
|
// this assumes that we don't gain anything here. Stop now.
|
||||||
break;
|
break;
|
||||||
|
|
@ -2768,7 +2935,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
||||||
data.logger = mp_logger;
|
data.logger = mp_logger;
|
||||||
|
|
||||||
size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, 0, 1, 0 /*not tentative*/, pass > 0 /*with ambiguities*/, &data);
|
size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, 0, 1, 0 /*not tentative*/, pass > 0 /*with ambiguities*/, &data);
|
||||||
if (ni > 0 && ni != std::numeric_limits<size_t>::max ()) {
|
if (ni > 0 && ni != failed_match) {
|
||||||
new_identities += ni;
|
new_identities += ni;
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||||
tl::info << ni << " new identities.";
|
tl::info << ni << " new identities.";
|
||||||
|
|
@ -2808,12 +2975,20 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
||||||
void
|
void
|
||||||
NetlistComparer::handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1, const db::Circuit *c2, const db::Pin *pin2, bool &good, bool &pin_mismatch) const
|
NetlistComparer::handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1, const db::Circuit *c2, const db::Pin *pin2, bool &good, bool &pin_mismatch) const
|
||||||
{
|
{
|
||||||
// Determine whether the pin in question is used - only in this case we will report an error.
|
|
||||||
// Otherwise, the report will be "match" against 0.
|
|
||||||
|
|
||||||
const db::Circuit *c = pin1 ? c1 : c2;
|
const db::Circuit *c = pin1 ? c1 : c2;
|
||||||
const db::Pin *pin = pin1 ? pin1 : pin2;
|
const db::Pin *pin = pin1 ? pin1 : pin2;
|
||||||
|
|
||||||
|
// If the pin isn't connected internally inside the circuit we can ignore it
|
||||||
|
if (c->net_for_pin (pin->id ()) && c->net_for_pin (pin->id ())->is_passive ()) {
|
||||||
|
if (mp_logger) {
|
||||||
|
mp_logger->match_pins (pin1, pin2);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine whether the pin in question is used - only in this case we will report an error.
|
||||||
|
// Otherwise, the report will be "match" against 0.
|
||||||
|
|
||||||
bool is_not_connected = true;
|
bool is_not_connected = true;
|
||||||
for (db::Circuit::const_refs_iterator r = c->begin_refs (); r != c->end_refs () && is_not_connected; ++r) {
|
for (db::Circuit::const_refs_iterator r = c->begin_refs (); r != c->end_refs () && is_not_connected; ++r) {
|
||||||
const db::SubCircuit *sc = r.operator-> ();
|
const db::SubCircuit *sc = r.operator-> ();
|
||||||
|
|
@ -2842,43 +3017,46 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
|
||||||
// Report pin assignment
|
// Report pin assignment
|
||||||
// This step also does the pin identity mapping.
|
// This step also does the pin identity mapping.
|
||||||
|
|
||||||
// try to assign floating pins by name with higher prio
|
// try to assign abstract pins by name with higher prio
|
||||||
std::map<std::string, std::pair<const db::Pin *, const db::Pin *> > floating_pins_by_name;
|
// NOTE: An "abstract" pin is a concept that is used in the context of circuit abstracts where the circuits is
|
||||||
|
// intentionally emptied. An "abstract pin" is not just a floating pin. An abstract does not have a net while
|
||||||
|
// a floating pin has a net, but this net is passive - i.e. not attached to any device.
|
||||||
|
std::map<std::string, std::pair<const db::Pin *, const db::Pin *> > abstract_pins_by_name;
|
||||||
|
|
||||||
for (db::Circuit::const_pin_iterator p = c2->begin_pins (); p != c2->end_pins (); ++p) {
|
for (db::Circuit::const_pin_iterator p = c2->begin_pins (); p != c2->end_pins (); ++p) {
|
||||||
const db::Net *net = c2->net_for_pin (p->id ());
|
const db::Net *net = c2->net_for_pin (p->id ());
|
||||||
if (!net && !p->name ().empty ()) {
|
if (!net && !p->name ().empty ()) {
|
||||||
floating_pins_by_name.insert (std::make_pair (normalize_name (p->name ()), std::make_pair ((const db::Pin *) 0, (const db::Pin *) 0))).first->second.second = p.operator-> ();
|
abstract_pins_by_name.insert (std::make_pair (normalize_name (p->name ()), std::make_pair ((const db::Pin *) 0, (const db::Pin *) 0))).first->second.second = p.operator-> ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (db::Circuit::const_pin_iterator p = c1->begin_pins (); p != c1->end_pins (); ++p) {
|
for (db::Circuit::const_pin_iterator p = c1->begin_pins (); p != c1->end_pins (); ++p) {
|
||||||
const db::Net *net = c1->net_for_pin (p->id ());
|
const db::Net *net = c1->net_for_pin (p->id ());
|
||||||
if (!net && !p->name ().empty ()) {
|
if (!net && !p->name ().empty ()) {
|
||||||
floating_pins_by_name.insert (std::make_pair (normalize_name (p->name ()), std::make_pair ((const db::Pin *) 0, (const db::Pin *) 0))).first->second.first = p.operator-> ();
|
abstract_pins_by_name.insert (std::make_pair (normalize_name (p->name ()), std::make_pair ((const db::Pin *) 0, (const db::Pin *) 0))).first->second.first = p.operator-> ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<const db::Pin *, const db::Pin *> floating_pin_name_mapping;
|
std::map<const db::Pin *, const db::Pin *> abstract_pin_name_mapping;
|
||||||
for (std::map<std::string, std::pair<const db::Pin *, const db::Pin *> >::const_iterator i = floating_pins_by_name.begin (); i != floating_pins_by_name.end (); ++i) {
|
for (std::map<std::string, std::pair<const db::Pin *, const db::Pin *> >::const_iterator i = abstract_pins_by_name.begin (); i != abstract_pins_by_name.end (); ++i) {
|
||||||
if (i->second.first && i->second.second) {
|
if (i->second.first && i->second.second) {
|
||||||
floating_pin_name_mapping [i->second.first] = i->second.second;
|
abstract_pin_name_mapping [i->second.first] = i->second.second;
|
||||||
floating_pin_name_mapping [i->second.second] = i->second.first;
|
abstract_pin_name_mapping [i->second.second] = i->second.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<const db::Pin *> floating_pins;
|
std::vector<const db::Pin *> abstract_pins;
|
||||||
std::multimap<size_t, const db::Pin *> net2pin;
|
std::multimap<size_t, const db::Pin *> net2pin;
|
||||||
for (db::Circuit::const_pin_iterator p = c2->begin_pins (); p != c2->end_pins (); ++p) {
|
for (db::Circuit::const_pin_iterator p = c2->begin_pins (); p != c2->end_pins (); ++p) {
|
||||||
const db::Net *net = c2->net_for_pin (p->id ());
|
const db::Net *net = c2->net_for_pin (p->id ());
|
||||||
if (net) {
|
if (net) {
|
||||||
net2pin.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ()));
|
net2pin.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ()));
|
||||||
} else if (floating_pin_name_mapping.find (p.operator-> ()) == floating_pin_name_mapping.end ()) {
|
} else if (abstract_pin_name_mapping.find (p.operator-> ()) == abstract_pin_name_mapping.end ()) {
|
||||||
floating_pins.push_back (p.operator-> ());
|
abstract_pins.push_back (p.operator-> ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<const db::Pin *>::iterator next_float = floating_pins.begin ();
|
std::vector<const db::Pin *>::iterator next_abstract = abstract_pins.begin ();
|
||||||
|
|
||||||
CircuitMapper &c12_pin_mapping = c12_circuit_and_pin_mapping [c1];
|
CircuitMapper &c12_pin_mapping = c12_circuit_and_pin_mapping [c1];
|
||||||
c12_pin_mapping.set_other (c2);
|
c12_pin_mapping.set_other (c2);
|
||||||
|
|
@ -2892,10 +3070,10 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
|
||||||
const db::Net *net = c1->net_for_pin (p->id ());
|
const db::Net *net = c1->net_for_pin (p->id ());
|
||||||
if (! net) {
|
if (! net) {
|
||||||
|
|
||||||
std::map<const db::Pin *, const db::Pin *>::const_iterator fp = floating_pin_name_mapping.find (p.operator-> ());
|
std::map<const db::Pin *, const db::Pin *>::const_iterator fp = abstract_pin_name_mapping.find (p.operator-> ());
|
||||||
if (fp != floating_pin_name_mapping.end ()) {
|
if (fp != abstract_pin_name_mapping.end ()) {
|
||||||
|
|
||||||
// assign a floating pin - this is a dummy assignment which is mitigated
|
// assign an abstract pin - this is a dummy assignment which is mitigated
|
||||||
// by declaring the pins equivalent in derive_pin_equivalence
|
// by declaring the pins equivalent in derive_pin_equivalence
|
||||||
if (mp_logger) {
|
if (mp_logger) {
|
||||||
mp_logger->match_pins (p.operator-> (), fp->second);
|
mp_logger->match_pins (p.operator-> (), fp->second);
|
||||||
|
|
@ -2903,17 +3081,17 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
|
||||||
c12_pin_mapping.map_pin (p->id (), fp->second->id ());
|
c12_pin_mapping.map_pin (p->id (), fp->second->id ());
|
||||||
c22_pin_mapping.map_pin (fp->second->id (), p->id ());
|
c22_pin_mapping.map_pin (fp->second->id (), p->id ());
|
||||||
|
|
||||||
} else if (next_float != floating_pins.end ()) {
|
} else if (next_abstract != abstract_pins.end ()) {
|
||||||
|
|
||||||
// assign a floating pin - this is a dummy assignment which is mitigated
|
// assign an abstract pin - this is a dummy assignment which is mitigated
|
||||||
// by declaring the pins equivalent in derive_pin_equivalence
|
// by declaring the pins equivalent in derive_pin_equivalence
|
||||||
if (mp_logger) {
|
if (mp_logger) {
|
||||||
mp_logger->match_pins (p.operator-> (), *next_float);
|
mp_logger->match_pins (p.operator-> (), *next_abstract);
|
||||||
}
|
}
|
||||||
c12_pin_mapping.map_pin (p->id (), (*next_float)->id ());
|
c12_pin_mapping.map_pin (p->id (), (*next_abstract)->id ());
|
||||||
c22_pin_mapping.map_pin ((*next_float)->id (), p->id ());
|
c22_pin_mapping.map_pin ((*next_abstract)->id (), p->id ());
|
||||||
|
|
||||||
++next_float;
|
++next_abstract;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -2929,11 +3107,8 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
|
||||||
const db::NetGraphNode &n = *(g1.begin () + g1.node_index_for_net (net));
|
const db::NetGraphNode &n = *(g1.begin () + g1.node_index_for_net (net));
|
||||||
|
|
||||||
if (! n.has_other ()) {
|
if (! n.has_other ()) {
|
||||||
|
|
||||||
handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch);
|
handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::multimap<size_t, const db::Pin *>::iterator np = net2pin.find (n.other_net_index ());
|
std::multimap<size_t, const db::Pin *>::iterator np = net2pin.find (n.other_net_index ());
|
||||||
|
|
@ -2966,9 +3141,10 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
|
||||||
handle_pin_mismatch (c1, 0, c2, np->second, good, pin_mismatch);
|
handle_pin_mismatch (c1, 0, c2, np->second, good, pin_mismatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (next_float != floating_pins.end ()) {
|
// abstract pins must match.
|
||||||
handle_pin_mismatch (c1, 0, c2, *next_float, good, pin_mismatch);
|
while (next_abstract != abstract_pins.end ()) {
|
||||||
++next_float;
|
handle_pin_mismatch (c1, 0, c2, *next_abstract, good, pin_mismatch);
|
||||||
|
++next_abstract;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -3000,7 +3176,7 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph
|
||||||
bool mapped = true;
|
bool mapped = true;
|
||||||
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end (); ++i) {
|
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end (); ++i) {
|
||||||
if (! g1.begin () [i->second].has_other ()) {
|
if (! g1.begin () [i->second].has_other ()) {
|
||||||
i->second = std::numeric_limits<size_t>::max (); // normalization
|
i->second = invalid_id; // normalization
|
||||||
mapped = false;
|
mapped = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3034,7 +3210,7 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph
|
||||||
bool mapped = true;
|
bool mapped = true;
|
||||||
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end (); ++i) {
|
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end (); ++i) {
|
||||||
if (! g2.begin () [i->second].has_other ()) {
|
if (! g2.begin () [i->second].has_other ()) {
|
||||||
i->second = std::numeric_limits<size_t>::max (); // normalization
|
i->second = invalid_id; // normalization
|
||||||
mapped = false;
|
mapped = false;
|
||||||
} else {
|
} else {
|
||||||
i->second = g2.begin () [i->second].other_net_index ();
|
i->second = g2.begin () [i->second].other_net_index ();
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ std::string NetlistDeviceExtractorError::to_string () const
|
||||||
// NetlistDeviceExtractor implementation
|
// NetlistDeviceExtractor implementation
|
||||||
|
|
||||||
NetlistDeviceExtractor::NetlistDeviceExtractor (const std::string &name)
|
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_name = name;
|
||||||
m_terminal_id_propname_id = 0;
|
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);
|
initialize (nl);
|
||||||
extract_without_initialize (layout, cell, clusters, layers, device_scaling);
|
extract_without_initialize (layout, cell, clusters, layers, device_scaling, breakout_cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
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 ());
|
tl_assert (layers.size () == m_layer_definitions.size ());
|
||||||
|
|
||||||
|
|
@ -214,6 +214,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db:
|
||||||
m_layers = layers;
|
m_layers = layers;
|
||||||
mp_clusters = &clusters;
|
mp_clusters = &clusters;
|
||||||
m_device_scaling = device_scaling;
|
m_device_scaling = device_scaling;
|
||||||
|
mp_breakout_cells = breakout_cells;
|
||||||
|
|
||||||
// terminal properties are kept in a property with the terminal_property_name name
|
// 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 ());
|
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::Connectivity device_conn = get_connectivity (layout, layers);
|
||||||
db::hier_clusters<shape_type> device_clusters;
|
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")));
|
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Extracting devices")));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ public:
|
||||||
*
|
*
|
||||||
* NOTE: The extractor expects "PolygonRef" type layers.
|
* 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
|
* @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;
|
db::properties_id_type m_terminal_id_propname_id, m_device_id_propname_id, m_device_class_propname_id;
|
||||||
hier_clusters_type *mp_clusters;
|
hier_clusters_type *mp_clusters;
|
||||||
db::cell_index_type m_cell_index;
|
db::cell_index_type m_cell_index;
|
||||||
|
const std::set<db::cell_index_type> *mp_breakout_cells;
|
||||||
double m_device_scaling;
|
double m_device_scaling;
|
||||||
db::Circuit *mp_circuit;
|
db::Circuit *mp_circuit;
|
||||||
db::DeviceClass *mp_device_class;
|
db::DeviceClass *mp_device_class;
|
||||||
|
|
@ -553,7 +554,7 @@ private:
|
||||||
*/
|
*/
|
||||||
void initialize (db::Netlist *nl);
|
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_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);
|
void push_cached_devices (const tl::vector<Device *> &cached_devices, const db::Vector &disp_cache, const db::Vector &new_disp);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ db::Connectivity NetlistDeviceExtractorMOS3Transistor::get_connectivity (const d
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
tl_assert (layers.size () >= 4);
|
tl_assert (layers.size () >= 4);
|
||||||
|
|
||||||
unsigned int sdiff = layers [0];
|
unsigned int sdiff = layers [0];
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,78 @@
|
||||||
|
|
||||||
#include "gsiDecl.h"
|
#include "gsiDecl.h"
|
||||||
#include "dbDeepShapeStore.h"
|
#include "dbDeepShapeStore.h"
|
||||||
|
#include "tlGlobPattern.h"
|
||||||
|
|
||||||
namespace gsi
|
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",
|
Class<db::DeepShapeStore> decl_dbDeepShapeStore ("db", "DeepShapeStore",
|
||||||
gsi::method ("instance_count", &db::DeepShapeStore::instance_count,
|
gsi::method ("instance_count", &db::DeepShapeStore::instance_count,
|
||||||
"@hide\n"
|
"@hide\n"
|
||||||
|
|
@ -84,6 +152,82 @@ Class<db::DeepShapeStore> decl_dbDeepShapeStore ("db", "DeepShapeStore",
|
||||||
) +
|
) +
|
||||||
gsi::method ("text_enlargement", &db::DeepShapeStore::text_enlargement,
|
gsi::method ("text_enlargement", &db::DeepShapeStore::text_enlargement,
|
||||||
"@brief Gets the text enlargement value.\n"
|
"@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"
|
"@brief An opaque layout heap for the deep region processor\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
|
||||||
|
|
@ -567,7 +567,14 @@ Class<db::Net> decl_dbNet ("db", "Net",
|
||||||
) +
|
) +
|
||||||
gsi::method ("is_floating?", &db::Net::is_floating,
|
gsi::method ("is_floating?", &db::Net::is_floating,
|
||||||
"@brief Returns true, if the net is floating.\n"
|
"@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,
|
gsi::method ("is_internal?", &db::Net::is_internal,
|
||||||
"@brief Returns true, if the net is an internal net.\n"
|
"@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)
|
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);
|
tl::GlobPattern pat (name_pattern);
|
||||||
for (db::Netlist::circuit_iterator c = nl->begin_circuits (); c != nl->end_circuits (); ++c) {
|
for (db::Netlist::circuit_iterator c = nl->begin_circuits (); c != nl->end_circuits (); ++c) {
|
||||||
if (pat.match (c->name ())) {
|
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) {
|
nl->flatten_circuits (circuits_to_flatten);
|
||||||
if (c->get ()) {
|
|
||||||
nl->flatten_circuit (c->get ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blank_circuit_by_name (db::Netlist *nl, const std::string &name_pattern)
|
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"
|
"@brief Flattens all circuits of the netlist\n"
|
||||||
"After calling this method, only the top circuits will remain."
|
"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"),
|
gsi::method ("flatten_circuit", &db::Netlist::flatten_circuit, gsi::arg ("circuit"),
|
||||||
"@brief Flattens a subcircuit\n"
|
"@brief Flattens a subcircuit\n"
|
||||||
"This method will substitute all instances (subcircuits) of the given circuit by it's "
|
"This method will substitute all instances (subcircuits) of the given circuit by it's "
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@
|
||||||
#include "tlGlobPattern.h"
|
#include "tlGlobPattern.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace gsi
|
namespace gsi
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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)
|
TEST(100_Integration)
|
||||||
{
|
{
|
||||||
db::Layout ly;
|
db::Layout ly;
|
||||||
|
|
|
||||||
|
|
@ -208,3 +208,60 @@ TEST(4_FlatAndEmptyInput)
|
||||||
EXPECT_EQ ((dr1 - dr3).to_string (), "(0,0;0,1000;1000,1000;1000,0)");
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 (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 (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:
|
// doesn't do anything here, but we test that this does not destroy anything:
|
||||||
l2n.netlist ()->combine_devices ();
|
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 (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 (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)
|
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 (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 (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:
|
// doesn't do anything here, but we test that this does not destroy anything:
|
||||||
l2n.netlist ()->combine_devices ();
|
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 $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"
|
" subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);\n"
|
||||||
"end;\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 $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 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"
|
" 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 (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 (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)
|
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 (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 (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:
|
// doesn't do anything here, but we test that this does not destroy anything:
|
||||||
l2n.netlist ()->combine_devices ();
|
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 (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 (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)
|
TEST(5_DeviceExtractionWithDeviceCombination)
|
||||||
|
|
|
||||||
|
|
@ -2605,8 +2605,8 @@ TEST(17_InherentlyAmbiguousDecoder)
|
||||||
"match_nets NQ1 NQ1\n"
|
"match_nets NQ1 NQ1\n"
|
||||||
"match_nets NQ2 NQ2\n"
|
"match_nets NQ2 NQ2\n"
|
||||||
"match_nets NQ3 NQ3\n"
|
"match_nets NQ3 NQ3\n"
|
||||||
"match_ambiguous_nets NA NA\n"
|
"match_nets NA NA\n"
|
||||||
"match_ambiguous_nets NB NB\n"
|
"match_nets NB NB\n"
|
||||||
"match_nets B B\n"
|
"match_nets B B\n"
|
||||||
"match_nets A A\n"
|
"match_nets A A\n"
|
||||||
"match_pins $0 $1\n"
|
"match_pins $0 $1\n"
|
||||||
|
|
@ -2796,3 +2796,573 @@ TEST(18_ClockTree)
|
||||||
EXPECT_EQ (good, true);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2108,3 +2108,198 @@ TEST(9_StrictDeviceExtraction)
|
||||||
|
|
||||||
db::compare_layouts (_this, ly, au);
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -752,6 +752,7 @@ TEST(6_Net)
|
||||||
EXPECT_EQ (n.pin_count (), size_t (0));
|
EXPECT_EQ (n.pin_count (), size_t (0));
|
||||||
EXPECT_EQ (n.terminal_count (), size_t (0));
|
EXPECT_EQ (n.terminal_count (), size_t (0));
|
||||||
EXPECT_EQ (n.is_floating (), true);
|
EXPECT_EQ (n.is_floating (), true);
|
||||||
|
EXPECT_EQ (n.is_passive (), true);
|
||||||
EXPECT_EQ (n.is_internal (), false);
|
EXPECT_EQ (n.is_internal (), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -781,6 +782,7 @@ TEST(7_NetTerminalsEditing)
|
||||||
EXPECT_EQ (n1->terminal_count (), size_t (1));
|
EXPECT_EQ (n1->terminal_count (), size_t (1));
|
||||||
EXPECT_EQ (n1->pin_count (), size_t (0));
|
EXPECT_EQ (n1->pin_count (), size_t (0));
|
||||||
EXPECT_EQ (n1->is_floating (), false);
|
EXPECT_EQ (n1->is_floating (), false);
|
||||||
|
EXPECT_EQ (n1->is_passive (), false);
|
||||||
EXPECT_EQ (n1->is_internal (), false);
|
EXPECT_EQ (n1->is_internal (), false);
|
||||||
|
|
||||||
d2->connect_terminal (1, n1);
|
d2->connect_terminal (1, n1);
|
||||||
|
|
@ -789,6 +791,7 @@ TEST(7_NetTerminalsEditing)
|
||||||
EXPECT_EQ (n1->terminal_count (), size_t (2));
|
EXPECT_EQ (n1->terminal_count (), size_t (2));
|
||||||
EXPECT_EQ (n1->pin_count (), size_t (0));
|
EXPECT_EQ (n1->pin_count (), size_t (0));
|
||||||
EXPECT_EQ (n1->is_floating (), false);
|
EXPECT_EQ (n1->is_floating (), false);
|
||||||
|
EXPECT_EQ (n1->is_passive (), false);
|
||||||
EXPECT_EQ (n1->is_internal (), true);
|
EXPECT_EQ (n1->is_internal (), true);
|
||||||
|
|
||||||
EXPECT_EQ (d1->net_for_terminal (0), n1);
|
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->terminal_count (), size_t (0));
|
||||||
EXPECT_EQ (n1->pin_count (), size_t (1));
|
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_EQ (n1->is_internal (), false);
|
||||||
EXPECT_NE (n1->pin_count (), size_t (0));
|
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->pin_count (), size_t (1));
|
||||||
EXPECT_EQ (n1->subcircuit_pin_count (), size_t (1));
|
EXPECT_EQ (n1->subcircuit_pin_count (), size_t (1));
|
||||||
EXPECT_EQ (n1->is_floating (), false);
|
EXPECT_EQ (n1->is_floating (), false);
|
||||||
|
EXPECT_EQ (n1->is_passive (), false);
|
||||||
EXPECT_EQ (n1->is_internal (), false);
|
EXPECT_EQ (n1->is_internal (), false);
|
||||||
|
|
||||||
sc2->connect_pin (1, n1);
|
sc2->connect_pin (1, n1);
|
||||||
|
|
@ -1380,7 +1385,7 @@ TEST(22_BlankCircuit)
|
||||||
nl2.purge ();
|
nl2.purge ();
|
||||||
|
|
||||||
EXPECT_EQ (nl2.to_string (),
|
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_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"
|
" subcircuit INV2 INV2_SC2 (IN=FB,$2=(null),OUT=$I8,$4=VSS,$5=VDD);\n"
|
||||||
"end;\n"
|
"end;\n"
|
||||||
|
|
|
||||||
|
|
@ -1121,6 +1121,108 @@ module DRC
|
||||||
nil
|
nil
|
||||||
end
|
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
|
# make some DRCLayer methods available as functions
|
||||||
# for the engine
|
# for the engine
|
||||||
%w(join and or xor not
|
%w(join and or xor not
|
||||||
|
|
@ -1461,22 +1563,22 @@ CODE
|
||||||
end
|
end
|
||||||
|
|
||||||
# save the netlist if required
|
# 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
|
writer = @target_netlist_format || RBA::NetlistSpiceWriter::new
|
||||||
|
|
||||||
netlist_file = _make_path(@target_netlist_file)
|
netlist_file = _make_path(@target_netlist_file)
|
||||||
info("Writing netlist: #{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
|
end
|
||||||
|
|
||||||
# save the netlist database if requested
|
# 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)
|
l2ndb_file = _make_path(@output_l2ndb_file)
|
||||||
info("Writing netlist database: #{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
|
end
|
||||||
|
|
||||||
|
|
@ -1484,7 +1586,7 @@ CODE
|
||||||
_before_cleanup
|
_before_cleanup
|
||||||
|
|
||||||
# show the data in the browser
|
# 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
|
# NOTE: to prevent the netter destroying the database, we need to take it
|
||||||
l2ndb = _take_data
|
l2ndb = _take_data
|
||||||
|
|
|
||||||
|
|
@ -383,6 +383,10 @@ module DRC
|
||||||
l2ndb
|
l2ndb
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def _l2n_data
|
||||||
|
@netlisted && self.l2n_data
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def cleanup
|
def cleanup
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,98 @@ cell("MACRO")
|
||||||
l1 = input(1, 0)
|
l1 = input(1, 0)
|
||||||
</pre>
|
</pre>
|
||||||
</p>
|
</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 & 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 & 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 & 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
|
||||||
|
</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>
|
<h2>"clear_connections" - Clears all connections stored so far</h2>
|
||||||
<keyword name="clear_connections"/>
|
<keyword name="clear_connections"/>
|
||||||
<a name="clear_connections"/><p>Usage:</p>
|
<a name="clear_connections"/><p>Usage:</p>
|
||||||
|
|
|
||||||
|
|
@ -735,7 +735,7 @@ This method is available for edge layers. The argument must be a polygon layer.
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
This method selects all shapes or regions from self which touch or overlap shapes from the other
|
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.
|
otherwise individual shapes are selected.
|
||||||
It returns a new layer containing the selected shapes. A version which modifies self
|
It returns a new layer containing the selected shapes. A version which modifies self
|
||||||
is <a href="#select_interacting">select_interacting</a>.
|
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>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
This method selects all shapes or regions from self which do not touch or overlap shapes from the other
|
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.
|
otherwise individual shapes are selected.
|
||||||
It returns a new layer containing the selected shapes. A version which modifies self
|
It returns a new layer containing the selected shapes. A version which modifies self
|
||||||
is <a href="#select_not_interacting">select_not_interacting</a>.
|
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>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
This method selects all shapes or regions from self which do not overlap shapes from the other
|
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.
|
otherwise individual shapes are selected.
|
||||||
</p><p>
|
</p><p>
|
||||||
The "not_overlapping" method is equivalent to the <a href="#outside">outside</a> method. It is provided
|
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>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
This method selects all shapes or regions from self which overlap shapes from the other
|
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.
|
otherwise individual shapes are selected.
|
||||||
It returns a new layer containing the selected shapes. A version which modifies self
|
It returns a new layer containing the selected shapes. A version which modifies self
|
||||||
is <a href="#select_overlapping">select_overlapping</a>.
|
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>
|
<ul>
|
||||||
<li><tt>layer.polygons?</tt></li>
|
<li><tt>layer.polygons?</tt></li>
|
||||||
</ul>
|
</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>
|
<h2>"raw" - Marks a layer as raw</h2>
|
||||||
<keyword name="raw"/>
|
<keyword name="raw"/>
|
||||||
<a name="raw"/><p>Usage:</p>
|
<a name="raw"/><p>Usage:</p>
|
||||||
|
|
@ -1562,7 +1616,7 @@ This method is available for polygon layers.
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
This method selects all shapes or regions from self which touch or overlap shapes from the other
|
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.
|
otherwise individual shapes are selected.
|
||||||
It modifies self to contain the selected shapes. A version which does not modify self
|
It modifies self to contain the selected shapes. A version which does not modify self
|
||||||
is <a href="#interacting">interacting</a>.
|
is <a href="#interacting">interacting</a>.
|
||||||
|
|
@ -1595,7 +1649,7 @@ This method is available for polygon layers.
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
This method selects all shapes or regions from self which do not touch or overlap shapes from the other
|
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.
|
otherwise individual shapes are selected.
|
||||||
It modifies self to contain the selected shapes. A version which does not modify self
|
It modifies self to contain the selected shapes. A version which does not modify self
|
||||||
is <a href="#not_interacting">not_interacting</a>.
|
is <a href="#not_interacting">not_interacting</a>.
|
||||||
|
|
@ -1628,7 +1682,7 @@ This method is available for polygon layers.
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
This method selects all shapes or regions from self which do not overlap shapes from the other
|
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.
|
otherwise individual shapes are selected.
|
||||||
It modifies self to contain the selected shapes. A version which does not modify self
|
It modifies self to contain the selected shapes. A version which does not modify self
|
||||||
is <a href="#not_overlapping">not_overlapping</a>.
|
is <a href="#not_overlapping">not_overlapping</a>.
|
||||||
|
|
@ -1661,7 +1715,7 @@ This method is available for polygon layers.
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
This method selects all shapes or regions from self which overlap shapes from the other
|
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.
|
otherwise individual shapes are selected.
|
||||||
It modifies self to contain the selected shapes. A version which does not modify self
|
It modifies self to contain the selected shapes. A version which does not modify self
|
||||||
is <a href="#overlapping">overlapping</a>.
|
is <a href="#overlapping">overlapping</a>.
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,11 @@ module LVS
|
||||||
def _before_cleanup
|
def _before_cleanup
|
||||||
|
|
||||||
# save the netlist database if requested
|
# 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)
|
lvsdb_file = _make_path(@output_lvsdb_file)
|
||||||
info("Writing LVS database: #{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
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ module LVS
|
||||||
|
|
||||||
def initialize(engine)
|
def initialize(engine)
|
||||||
super
|
super
|
||||||
|
@comparer_config = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def _make_data
|
def _make_data
|
||||||
|
|
@ -65,7 +66,6 @@ module LVS
|
||||||
@lvs.generator = @engine._generator
|
@lvs.generator = @engine._generator
|
||||||
|
|
||||||
@l2n = @lvs
|
@l2n = @lvs
|
||||||
@comparer = RBA::NetlistComparer::new
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -94,6 +94,10 @@ module LVS
|
||||||
data
|
data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def _lvs_data
|
||||||
|
_l2n_data && @lvs
|
||||||
|
end
|
||||||
|
|
||||||
# %LVS%
|
# %LVS%
|
||||||
# @name align
|
# @name align
|
||||||
# @brief Aligns the extracted netlist vs. the schematic
|
# @brief Aligns the extracted netlist vs. the schematic
|
||||||
|
|
@ -120,7 +124,9 @@ module LVS
|
||||||
|
|
||||||
nl = _ensure_two_netlists
|
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
|
# check whether we're about to flatten away the internal top cell - that's bad
|
||||||
top_cell = l2n_data.internal_top_cell.name
|
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
|
# flatten layout cells for which there is no corresponding schematic circuit
|
||||||
unmatched_a.each do |c|
|
unmatched_a.each do |c|
|
||||||
@engine.info("Flatten layout cell (no schematic): #{c.name}")
|
@engine.info("Flatten layout cell (no schematic): #{c.name}")
|
||||||
nl[0].flatten_circuit(c)
|
|
||||||
end
|
end
|
||||||
|
nl[0].flatten_circuits(unmatched_a)
|
||||||
|
|
||||||
# flatten schematic circuits for which there is no corresponding layout cell
|
# 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}")
|
@engine.info("Flatten schematic circuit (no layout): #{c.name}")
|
||||||
nl[1].flatten_circuit(c)
|
|
||||||
end
|
end
|
||||||
|
nl[1].flatten_circuits(unmatched_b)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -161,7 +168,20 @@ module LVS
|
||||||
nl = _ensure_two_netlists
|
nl = _ensure_two_netlists
|
||||||
lvs_data.reference = nl[1]
|
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
|
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")
|
n.is_a?(String) || n.is_a?(RBA::Net) || raise("Net arguments of 'same_nets' must be strings or Net objects")
|
||||||
end
|
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
|
( nl_a, nl_b ) = _ensure_two_netlists
|
||||||
|
|
||||||
if ca.is_a?(String)
|
if ca.is_a?(String)
|
||||||
|
|
@ -234,19 +260,19 @@ module LVS
|
||||||
if circuit_a && circuit_b
|
if circuit_a && circuit_b
|
||||||
|
|
||||||
if a.is_a?(String)
|
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
|
else
|
||||||
net_a = a
|
net_a = a
|
||||||
end
|
end
|
||||||
|
|
||||||
if b.is_a?(String)
|
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
|
else
|
||||||
net_b = b
|
net_b = b
|
||||||
end
|
end
|
||||||
|
|
||||||
if net_a && net_b
|
if net_a && net_b
|
||||||
@comparer.same_nets(net_a, net_b)
|
comparer.same_nets(net_a, net_b)
|
||||||
end
|
end
|
||||||
|
|
||||||
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")
|
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
|
( nl_a, nl_b ) = _ensure_two_netlists
|
||||||
|
|
||||||
circuit_a = a && nl_a.circuit_by_name(a)
|
circuit_a = a && nl_a.circuit_by_name(a)
|
||||||
circuit_b = b && nl_b.circuit_by_name(b)
|
circuit_b = b && nl_b.circuit_by_name(b)
|
||||||
|
|
||||||
if circuit_a && circuit_b
|
if circuit_a && circuit_b
|
||||||
@comparer.same_circuits(circuit_a, circuit_b)
|
comparer.same_circuits(circuit_a, circuit_b)
|
||||||
end
|
end
|
||||||
|
|
||||||
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")
|
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
|
( 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)
|
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
|
# NOTE: a device class is allowed to be missing in the reference netlist because the
|
||||||
# device may simply not be used there.
|
# device may simply not be used there.
|
||||||
if dc_b
|
if dc_b
|
||||||
@comparer.same_device_classes(dc_a, dc_b)
|
comparer.same_device_classes(dc_a, dc_b)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
@ -347,6 +385,12 @@ module LVS
|
||||||
raise("All pin arguments of 'equivalent_pins' need to be strings or numbers")
|
raise("All pin arguments of 'equivalent_pins' need to be strings or numbers")
|
||||||
end
|
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
|
( nl_a, nl_b ) = _ensure_two_netlists
|
||||||
|
|
||||||
circuit_b = nl_b.circuit_by_name(circuit)
|
circuit_b = nl_b.circuit_by_name(circuit)
|
||||||
|
|
@ -357,14 +401,14 @@ module LVS
|
||||||
|
|
||||||
pin_ids_b = pins.collect do |p|
|
pin_ids_b = pins.collect do |p|
|
||||||
if p.is_a?(String)
|
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
|
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
|
end
|
||||||
pin.id
|
pin.id
|
||||||
end
|
end
|
||||||
|
|
||||||
@comparer.equivalent_pins(circuit_b, pin_ids_b)
|
comparer.equivalent_pins(circuit_b, pin_ids_b)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -428,8 +472,8 @@ module LVS
|
||||||
# with a capacitance values below the given threshold (in Farad).
|
# with a capacitance values below the given threshold (in Farad).
|
||||||
|
|
||||||
def min_caps(value)
|
def min_caps(value)
|
||||||
lvs_data
|
v = value.to_f
|
||||||
@comparer.min_capacitance = value.to_f
|
@comparer_config << lambda { |comparer| comparer.min_capacitance = v }
|
||||||
end
|
end
|
||||||
|
|
||||||
# %LVS%
|
# %LVS%
|
||||||
|
|
@ -440,8 +484,8 @@ module LVS
|
||||||
# with a resistance value above the given threshold (in Farad).
|
# with a resistance value above the given threshold (in Farad).
|
||||||
|
|
||||||
def max_res(value)
|
def max_res(value)
|
||||||
lvs_data
|
v = value.to_f
|
||||||
@comparer.max_resistance = value.to_f
|
@comparer_config << lambda { |comparer| comparer.max_resistance = v }
|
||||||
end
|
end
|
||||||
|
|
||||||
# %LVS%
|
# %LVS%
|
||||||
|
|
@ -459,8 +503,8 @@ module LVS
|
||||||
# as the seeds for this deduction path. The default value is 8.
|
# as the seeds for this deduction path. The default value is 8.
|
||||||
|
|
||||||
def max_depth(value)
|
def max_depth(value)
|
||||||
lvs_data
|
v = value.to_i
|
||||||
@comparer.max_depth = value.to_i
|
@comparer_config << lambda { |comparer| comparer.max_depth = v }
|
||||||
end
|
end
|
||||||
|
|
||||||
# @name max_branch_complexity
|
# @name max_branch_complexity
|
||||||
|
|
@ -480,8 +524,8 @@ module LVS
|
||||||
# complexity.
|
# complexity.
|
||||||
|
|
||||||
def max_branch_complexity(value)
|
def max_branch_complexity(value)
|
||||||
lvs_data
|
v = value.to_i
|
||||||
@comparer.max_branch_complexity = value.to_i
|
@comparer_config << lambda { |comparer| comparer.max_branch_complexity = v }
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -154,3 +154,14 @@ TEST(16_floating)
|
||||||
{
|
{
|
||||||
run_test (_this, "floating", "floating.gds", false, "TOP");
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,38 @@ private:
|
||||||
GlobPatternString &operator= (const GlobPatternString &);
|
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
|
class GlobPatternPass
|
||||||
: public GlobPatternOp
|
: 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);
|
GlobPatternOp *alt = compile (p, false, cs, false, true);
|
||||||
if (alt) {
|
if (alt) {
|
||||||
alt_op->add_choice (alt);
|
alt_op->add_choice (alt);
|
||||||
|
} else {
|
||||||
|
alt_op->add_choice (new GlobPatternEmpty ());
|
||||||
}
|
}
|
||||||
if (*p == ',') {
|
if (*p == ',') {
|
||||||
++p;
|
++p;
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,7 @@ TEST(6)
|
||||||
|
|
||||||
EXPECT_EQ (a.match ("abcg"), true);
|
EXPECT_EQ (a.match ("abcg"), true);
|
||||||
EXPECT_EQ (a.match ("adg"), true);
|
EXPECT_EQ (a.match ("adg"), true);
|
||||||
|
EXPECT_EQ (a.match ("ad"), false);
|
||||||
EXPECT_EQ (a.match ("ag"), false);
|
EXPECT_EQ (a.match ("ag"), false);
|
||||||
EXPECT_EQ (a.match ("abch"), false);
|
EXPECT_EQ (a.match ("abch"), false);
|
||||||
EXPECT_EQ (a.match ("adh"), false);
|
EXPECT_EQ (a.match ("adh"), false);
|
||||||
|
|
@ -173,11 +174,33 @@ TEST(6)
|
||||||
|
|
||||||
EXPECT_EQ (aa.match ("abcg"), true);
|
EXPECT_EQ (aa.match ("abcg"), true);
|
||||||
EXPECT_EQ (aa.match ("adg"), true);
|
EXPECT_EQ (aa.match ("adg"), true);
|
||||||
|
EXPECT_EQ (aa.match ("ad"), false);
|
||||||
EXPECT_EQ (aa.match ("ag"), false);
|
EXPECT_EQ (aa.match ("ag"), false);
|
||||||
EXPECT_EQ (aa.match ("abch"), false);
|
EXPECT_EQ (aa.match ("abch"), false);
|
||||||
EXPECT_EQ (aa.match ("adh"), false);
|
EXPECT_EQ (aa.match ("adh"), false);
|
||||||
EXPECT_EQ (aa.match ("ah"), 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)
|
TEST(7)
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -270,6 +270,12 @@ circuit(INV2PAIR
|
||||||
rect(diff_cont (-220 180) (220 220))
|
rect(diff_cont (-220 180) (220 220))
|
||||||
)
|
)
|
||||||
net(4
|
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 (4230 3290) (220 220))
|
||||||
rect(diff_cont (-220 180) (220 220))
|
rect(diff_cont (-220 180) (220 220))
|
||||||
rect(diff_cont (-220 -220) (220 220))
|
rect(diff_cont (-220 -220) (220 220))
|
||||||
|
|
@ -283,7 +289,7 @@ circuit(INV2PAIR
|
||||||
rect(metal1 (-3000 -760) (360 760))
|
rect(metal1 (-3000 -760) (360 760))
|
||||||
rect(metal1 (-360 -760) (360 760))
|
rect(metal1 (-360 -760) (360 760))
|
||||||
)
|
)
|
||||||
net(5
|
net(6
|
||||||
rect(diff_cont (4230 490) (220 220))
|
rect(diff_cont (4230 490) (220 220))
|
||||||
rect(diff_cont (-220 180) (220 220))
|
rect(diff_cont (-220 180) (220 220))
|
||||||
rect(diff_cont (-220 -220) (220 220))
|
rect(diff_cont (-220 -220) (220 220))
|
||||||
|
|
@ -297,12 +303,6 @@ circuit(INV2PAIR
|
||||||
rect(metal1 (-3000 -760) (360 760))
|
rect(metal1 (-3000 -760) (360 760))
|
||||||
rect(metal1 (-360 -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(7)
|
||||||
net(8
|
net(8
|
||||||
rect(diff_cont (5030 3690) (220 220))
|
rect(diff_cont (5030 3690) (220 220))
|
||||||
|
|
@ -315,8 +315,8 @@ circuit(INV2PAIR
|
||||||
# Outgoing pins and their connections to nets
|
# Outgoing pins and their connections to nets
|
||||||
pin(1 name(BULK))
|
pin(1 name(BULK))
|
||||||
pin(2)
|
pin(2)
|
||||||
pin(4)
|
|
||||||
pin(5)
|
pin(5)
|
||||||
|
pin(6)
|
||||||
pin(7)
|
pin(7)
|
||||||
pin(8)
|
pin(8)
|
||||||
pin(9)
|
pin(9)
|
||||||
|
|
@ -326,18 +326,18 @@ circuit(INV2PAIR
|
||||||
pin(0 9)
|
pin(0 9)
|
||||||
pin(1 7)
|
pin(1 7)
|
||||||
pin(2 3)
|
pin(2 3)
|
||||||
pin(3 6)
|
pin(3 4)
|
||||||
pin(4 5)
|
pin(4 6)
|
||||||
pin(5 4)
|
pin(5 5)
|
||||||
pin(6 1)
|
pin(6 1)
|
||||||
)
|
)
|
||||||
circuit(2 INV2 location(4340 800)
|
circuit(2 INV2 location(4340 800)
|
||||||
pin(0 9)
|
pin(0 9)
|
||||||
pin(1 6)
|
pin(1 4)
|
||||||
pin(2 2)
|
pin(2 2)
|
||||||
pin(3 8)
|
pin(3 8)
|
||||||
pin(4 5)
|
pin(4 6)
|
||||||
pin(5 4)
|
pin(5 5)
|
||||||
pin(6 1)
|
pin(6 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,12 @@ X(INV2PAIR
|
||||||
R(diff_cont (-220 180) (220 220))
|
R(diff_cont (-220 180) (220 220))
|
||||||
)
|
)
|
||||||
N(4
|
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 (4230 3290) (220 220))
|
||||||
R(diff_cont (-220 180) (220 220))
|
R(diff_cont (-220 180) (220 220))
|
||||||
R(diff_cont (-220 -220) (220 220))
|
R(diff_cont (-220 -220) (220 220))
|
||||||
|
|
@ -251,7 +257,7 @@ X(INV2PAIR
|
||||||
R(metal1 (-3000 -760) (360 760))
|
R(metal1 (-3000 -760) (360 760))
|
||||||
R(metal1 (-360 -760) (360 760))
|
R(metal1 (-360 -760) (360 760))
|
||||||
)
|
)
|
||||||
N(5
|
N(6
|
||||||
R(diff_cont (4230 490) (220 220))
|
R(diff_cont (4230 490) (220 220))
|
||||||
R(diff_cont (-220 180) (220 220))
|
R(diff_cont (-220 180) (220 220))
|
||||||
R(diff_cont (-220 -220) (220 220))
|
R(diff_cont (-220 -220) (220 220))
|
||||||
|
|
@ -265,12 +271,6 @@ X(INV2PAIR
|
||||||
R(metal1 (-3000 -760) (360 760))
|
R(metal1 (-3000 -760) (360 760))
|
||||||
R(metal1 (-360 -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(7)
|
||||||
N(8
|
N(8
|
||||||
R(diff_cont (5030 3690) (220 220))
|
R(diff_cont (5030 3690) (220 220))
|
||||||
|
|
@ -281,8 +281,8 @@ X(INV2PAIR
|
||||||
N(9)
|
N(9)
|
||||||
P(1 I(BULK))
|
P(1 I(BULK))
|
||||||
P(2)
|
P(2)
|
||||||
P(4)
|
|
||||||
P(5)
|
P(5)
|
||||||
|
P(6)
|
||||||
P(7)
|
P(7)
|
||||||
P(8)
|
P(8)
|
||||||
P(9)
|
P(9)
|
||||||
|
|
@ -290,18 +290,18 @@ X(INV2PAIR
|
||||||
P(0 9)
|
P(0 9)
|
||||||
P(1 7)
|
P(1 7)
|
||||||
P(2 3)
|
P(2 3)
|
||||||
P(3 6)
|
P(3 4)
|
||||||
P(4 5)
|
P(4 6)
|
||||||
P(5 4)
|
P(5 5)
|
||||||
P(6 1)
|
P(6 1)
|
||||||
)
|
)
|
||||||
X(2 INV2 Y(4340 800)
|
X(2 INV2 Y(4340 800)
|
||||||
P(0 9)
|
P(0 9)
|
||||||
P(1 6)
|
P(1 4)
|
||||||
P(2 2)
|
P(2 2)
|
||||||
P(3 8)
|
P(3 8)
|
||||||
P(4 5)
|
P(4 6)
|
||||||
P(5 4)
|
P(5 5)
|
||||||
P(6 1)
|
P(6 1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,24 @@ layout(
|
||||||
# Nets with their geometries
|
# Nets with their geometries
|
||||||
net(1 name(BULK))
|
net(1 name(BULK))
|
||||||
net(2
|
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 (4230 3290) (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 180) (220 220))
|
||||||
|
|
@ -289,7 +307,7 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -1560) (360 1560))
|
rect(metal1 (-360 -1560) (360 1560))
|
||||||
)
|
)
|
||||||
net(3
|
net(4
|
||||||
rect(diff_cont (4230 890) (220 220))
|
rect(diff_cont (4230 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 (-220 -620) (220 220))
|
||||||
|
|
@ -311,24 +329,6 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -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(5)
|
||||||
net(6
|
net(6
|
||||||
rect(diff_cont (3430 890) (220 220))
|
rect(diff_cont (3430 890) (220 220))
|
||||||
|
|
@ -363,17 +363,17 @@ layout(
|
||||||
circuit(1 INV2 location(1700 800)
|
circuit(1 INV2 location(1700 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 5)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 2)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
circuit(2 INV2 location(4340 800)
|
circuit(2 INV2 location(4340 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 2)
|
||||||
pin(2 6)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -808,45 +808,45 @@ layout(
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2PAIR location(19420 -800)
|
circuit(1 INV2PAIR location(19420 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 1)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 1)
|
pin(3 4)
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 2)
|
pin(5 2)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(2 INV2PAIR location(-1700 -800)
|
circuit(2 INV2PAIR location(-1700 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 8)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 8)
|
pin(3 4)
|
||||||
pin(4 1)
|
pin(4 1)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(3 INV2PAIR location(3580 -800)
|
circuit(3 INV2PAIR location(3580 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 7)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 7)
|
pin(3 4)
|
||||||
pin(4 9)
|
pin(4 9)
|
||||||
pin(5 12)
|
pin(5 12)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(4 INV2PAIR location(8860 -800)
|
circuit(4 INV2PAIR location(8860 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 6)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 6)
|
pin(3 4)
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 11)
|
pin(5 11)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(5 INV2PAIR location(14140 -800)
|
circuit(5 INV2PAIR location(14140 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 5)
|
pin(3 4)
|
||||||
pin(4 11)
|
pin(4 11)
|
||||||
pin(5 10)
|
pin(5 10)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
|
|
@ -1044,16 +1044,16 @@ xref(
|
||||||
)
|
)
|
||||||
circuit(INV2PAIR INV2PAIR match
|
circuit(INV2PAIR INV2PAIR match
|
||||||
xref(
|
xref(
|
||||||
net(2 2 match)
|
net(3 2 match)
|
||||||
net(3 3 match)
|
net(4 3 match)
|
||||||
net(4 4 match)
|
net(2 4 match)
|
||||||
net(5 5 match)
|
net(5 5 match)
|
||||||
net(6 6 match)
|
net(6 6 match)
|
||||||
net(7 7 match)
|
net(7 7 match)
|
||||||
net(1 1 match)
|
net(1 1 match)
|
||||||
pin(1 1 match)
|
pin(2 1 match)
|
||||||
pin(2 2 match)
|
pin(3 2 match)
|
||||||
pin(3 3 match)
|
pin(1 3 match)
|
||||||
pin(4 4 match)
|
pin(4 4 match)
|
||||||
pin(5 5 match)
|
pin(5 5 match)
|
||||||
pin(6 6 match)
|
pin(6 6 match)
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,24 @@ layout(
|
||||||
# Nets with their geometries
|
# Nets with their geometries
|
||||||
net(1 name(BULK))
|
net(1 name(BULK))
|
||||||
net(2
|
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 (4230 3290) (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 180) (220 220))
|
||||||
|
|
@ -289,7 +307,7 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -1560) (360 1560))
|
rect(metal1 (-360 -1560) (360 1560))
|
||||||
)
|
)
|
||||||
net(3
|
net(4
|
||||||
rect(diff_cont (4230 890) (220 220))
|
rect(diff_cont (4230 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 (-220 -620) (220 220))
|
||||||
|
|
@ -311,24 +329,6 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -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(5)
|
||||||
net(6
|
net(6
|
||||||
rect(diff_cont (3430 890) (220 220))
|
rect(diff_cont (3430 890) (220 220))
|
||||||
|
|
@ -363,17 +363,17 @@ layout(
|
||||||
circuit(1 INV2 location(1700 800)
|
circuit(1 INV2 location(1700 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 5)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 2)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
circuit(2 INV2 location(4340 800)
|
circuit(2 INV2 location(4340 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 2)
|
||||||
pin(2 6)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -808,45 +808,45 @@ layout(
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2PAIR location(19420 -800)
|
circuit(1 INV2PAIR location(19420 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 1)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 1)
|
pin(3 4)
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 2)
|
pin(5 2)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(2 INV2PAIR location(-1700 -800)
|
circuit(2 INV2PAIR location(-1700 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 8)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 8)
|
pin(3 4)
|
||||||
pin(4 1)
|
pin(4 1)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(3 INV2PAIR location(3580 -800)
|
circuit(3 INV2PAIR location(3580 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 7)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 7)
|
pin(3 4)
|
||||||
pin(4 9)
|
pin(4 9)
|
||||||
pin(5 12)
|
pin(5 12)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(4 INV2PAIR location(8860 -800)
|
circuit(4 INV2PAIR location(8860 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 6)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 6)
|
pin(3 4)
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 11)
|
pin(5 11)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(5 INV2PAIR location(14140 -800)
|
circuit(5 INV2PAIR location(14140 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 5)
|
pin(3 4)
|
||||||
pin(4 11)
|
pin(4 11)
|
||||||
pin(5 10)
|
pin(5 10)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
|
|
@ -1044,16 +1044,16 @@ xref(
|
||||||
)
|
)
|
||||||
circuit(INV2PAIR INV2PAIR match
|
circuit(INV2PAIR INV2PAIR match
|
||||||
xref(
|
xref(
|
||||||
net(2 2 match)
|
net(3 2 match)
|
||||||
net(3 3 match)
|
net(4 3 match)
|
||||||
net(4 4 match)
|
net(2 4 match)
|
||||||
net(5 5 match)
|
net(5 5 match)
|
||||||
net(6 6 match)
|
net(6 6 match)
|
||||||
net(7 7 match)
|
net(7 7 match)
|
||||||
net(1 1 match)
|
net(1 1 match)
|
||||||
pin(1 1 match)
|
pin(2 1 match)
|
||||||
pin(2 2 match)
|
pin(3 2 match)
|
||||||
pin(3 3 match)
|
pin(1 3 match)
|
||||||
pin(4 4 match)
|
pin(4 4 match)
|
||||||
pin(5 5 match)
|
pin(5 5 match)
|
||||||
pin(6 6 match)
|
pin(6 6 match)
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,24 @@ layout(
|
||||||
# Nets with their geometries
|
# Nets with their geometries
|
||||||
net(1 name(BULK))
|
net(1 name(BULK))
|
||||||
net(2
|
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 (4230 3290) (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 180) (220 220))
|
||||||
|
|
@ -289,7 +307,7 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -1560) (360 1560))
|
rect(metal1 (-360 -1560) (360 1560))
|
||||||
)
|
)
|
||||||
net(3
|
net(4
|
||||||
rect(diff_cont (4230 890) (220 220))
|
rect(diff_cont (4230 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 (-220 -620) (220 220))
|
||||||
|
|
@ -311,24 +329,6 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -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(5)
|
||||||
net(6
|
net(6
|
||||||
rect(diff_cont (3430 890) (220 220))
|
rect(diff_cont (3430 890) (220 220))
|
||||||
|
|
@ -363,17 +363,17 @@ layout(
|
||||||
circuit(1 INV2 location(1700 800)
|
circuit(1 INV2 location(1700 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 5)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 2)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
circuit(2 INV2 location(4340 800)
|
circuit(2 INV2 location(4340 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 2)
|
||||||
pin(2 6)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -808,45 +808,45 @@ layout(
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2PAIR location(19420 -800)
|
circuit(1 INV2PAIR location(19420 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 1)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 1)
|
pin(3 4)
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 2)
|
pin(5 2)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(2 INV2PAIR location(-1700 -800)
|
circuit(2 INV2PAIR location(-1700 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 8)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 8)
|
pin(3 4)
|
||||||
pin(4 1)
|
pin(4 1)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(3 INV2PAIR location(3580 -800)
|
circuit(3 INV2PAIR location(3580 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 7)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 7)
|
pin(3 4)
|
||||||
pin(4 9)
|
pin(4 9)
|
||||||
pin(5 12)
|
pin(5 12)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(4 INV2PAIR location(8860 -800)
|
circuit(4 INV2PAIR location(8860 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 6)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 6)
|
pin(3 4)
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 11)
|
pin(5 11)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(5 INV2PAIR location(14140 -800)
|
circuit(5 INV2PAIR location(14140 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 5)
|
pin(3 4)
|
||||||
pin(4 11)
|
pin(4 11)
|
||||||
pin(5 10)
|
pin(5 10)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
|
|
@ -1044,16 +1044,16 @@ xref(
|
||||||
)
|
)
|
||||||
circuit(INV2PAIR INV2PAIR match
|
circuit(INV2PAIR INV2PAIR match
|
||||||
xref(
|
xref(
|
||||||
net(2 2 match)
|
net(3 2 match)
|
||||||
net(3 3 match)
|
net(4 3 match)
|
||||||
net(4 4 match)
|
net(2 4 match)
|
||||||
net(5 5 match)
|
net(5 5 match)
|
||||||
net(6 6 match)
|
net(6 6 match)
|
||||||
net(7 7 match)
|
net(7 7 match)
|
||||||
net(1 1 match)
|
net(1 1 match)
|
||||||
pin(1 1 match)
|
pin(2 1 match)
|
||||||
pin(2 2 match)
|
pin(3 2 match)
|
||||||
pin(3 3 match)
|
pin(1 3 match)
|
||||||
pin(4 4 match)
|
pin(4 4 match)
|
||||||
pin(5 5 match)
|
pin(5 5 match)
|
||||||
pin(6 6 match)
|
pin(6 6 match)
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,24 @@ layout(
|
||||||
# Nets with their geometries
|
# Nets with their geometries
|
||||||
net(1 name(BULK))
|
net(1 name(BULK))
|
||||||
net(2
|
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 (4230 3290) (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 180) (220 220))
|
||||||
|
|
@ -289,7 +307,7 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -1560) (360 1560))
|
rect(metal1 (-360 -1560) (360 1560))
|
||||||
)
|
)
|
||||||
net(3
|
net(4
|
||||||
rect(diff_cont (4230 890) (220 220))
|
rect(diff_cont (4230 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 (-220 -620) (220 220))
|
||||||
|
|
@ -311,24 +329,6 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -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(5)
|
||||||
net(6
|
net(6
|
||||||
rect(diff_cont (3430 890) (220 220))
|
rect(diff_cont (3430 890) (220 220))
|
||||||
|
|
@ -363,17 +363,17 @@ layout(
|
||||||
circuit(1 INV2 location(1700 800)
|
circuit(1 INV2 location(1700 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 5)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 2)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
circuit(2 INV2 location(4340 800)
|
circuit(2 INV2 location(4340 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 2)
|
||||||
pin(2 6)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -808,45 +808,45 @@ layout(
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2PAIR location(19420 -800)
|
circuit(1 INV2PAIR location(19420 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 1)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 1)
|
pin(3 4)
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 2)
|
pin(5 2)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(2 INV2PAIR location(-1700 -800)
|
circuit(2 INV2PAIR location(-1700 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 8)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 8)
|
pin(3 4)
|
||||||
pin(4 1)
|
pin(4 1)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(3 INV2PAIR location(3580 -800)
|
circuit(3 INV2PAIR location(3580 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 7)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 7)
|
pin(3 4)
|
||||||
pin(4 9)
|
pin(4 9)
|
||||||
pin(5 12)
|
pin(5 12)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(4 INV2PAIR location(8860 -800)
|
circuit(4 INV2PAIR location(8860 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 6)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 6)
|
pin(3 4)
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 11)
|
pin(5 11)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(5 INV2PAIR location(14140 -800)
|
circuit(5 INV2PAIR location(14140 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 5)
|
pin(3 4)
|
||||||
pin(4 11)
|
pin(4 11)
|
||||||
pin(5 10)
|
pin(5 10)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
|
|
@ -1044,16 +1044,16 @@ xref(
|
||||||
)
|
)
|
||||||
circuit(INV2PAIR INV2PAIR match
|
circuit(INV2PAIR INV2PAIR match
|
||||||
xref(
|
xref(
|
||||||
net(2 2 match)
|
net(3 2 match)
|
||||||
net(3 3 match)
|
net(4 3 match)
|
||||||
net(4 4 match)
|
net(2 4 match)
|
||||||
net(5 5 match)
|
net(5 5 match)
|
||||||
net(6 6 match)
|
net(6 6 match)
|
||||||
net(7 7 match)
|
net(7 7 match)
|
||||||
net(1 1 match)
|
net(1 1 match)
|
||||||
pin(1 1 match)
|
pin(2 1 match)
|
||||||
pin(2 2 match)
|
pin(3 2 match)
|
||||||
pin(3 3 match)
|
pin(1 3 match)
|
||||||
pin(4 4 match)
|
pin(4 4 match)
|
||||||
pin(5 5 match)
|
pin(5 5 match)
|
||||||
pin(6 6 match)
|
pin(6 6 match)
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,24 @@ layout(
|
||||||
# Nets with their geometries
|
# Nets with their geometries
|
||||||
net(1 name(BULK))
|
net(1 name(BULK))
|
||||||
net(2
|
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 (4230 3290) (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 180) (220 220))
|
||||||
|
|
@ -289,7 +307,7 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -1560) (360 1560))
|
rect(metal1 (-360 -1560) (360 1560))
|
||||||
)
|
)
|
||||||
net(3
|
net(4
|
||||||
rect(diff_cont (4230 890) (220 220))
|
rect(diff_cont (4230 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 (-220 -620) (220 220))
|
||||||
|
|
@ -311,24 +329,6 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -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(5)
|
||||||
net(6
|
net(6
|
||||||
rect(diff_cont (3430 890) (220 220))
|
rect(diff_cont (3430 890) (220 220))
|
||||||
|
|
@ -363,17 +363,17 @@ layout(
|
||||||
circuit(1 INV2 location(1700 800)
|
circuit(1 INV2 location(1700 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 5)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 2)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
circuit(2 INV2 location(4340 800)
|
circuit(2 INV2 location(4340 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 2)
|
||||||
pin(2 6)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -808,45 +808,45 @@ layout(
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2PAIR location(19420 -800)
|
circuit(1 INV2PAIR location(19420 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 1)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 1)
|
pin(3 4)
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 2)
|
pin(5 2)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(2 INV2PAIR location(-1700 -800)
|
circuit(2 INV2PAIR location(-1700 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 8)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 8)
|
pin(3 4)
|
||||||
pin(4 1)
|
pin(4 1)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(3 INV2PAIR location(3580 -800)
|
circuit(3 INV2PAIR location(3580 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 7)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 7)
|
pin(3 4)
|
||||||
pin(4 9)
|
pin(4 9)
|
||||||
pin(5 12)
|
pin(5 12)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(4 INV2PAIR location(8860 -800)
|
circuit(4 INV2PAIR location(8860 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 6)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 6)
|
pin(3 4)
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 11)
|
pin(5 11)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(5 INV2PAIR location(14140 -800)
|
circuit(5 INV2PAIR location(14140 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 5)
|
pin(3 4)
|
||||||
pin(4 11)
|
pin(4 11)
|
||||||
pin(5 10)
|
pin(5 10)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
|
|
@ -918,23 +918,24 @@ reference(
|
||||||
net(2 name('2'))
|
net(2 name('2'))
|
||||||
net(3 name('3'))
|
net(3 name('3'))
|
||||||
net(4 name('4'))
|
net(4 name('4'))
|
||||||
net(5 name('6'))
|
net(5 name('5'))
|
||||||
net(6 name('7'))
|
net(6 name('6'))
|
||||||
|
net(7 name('7'))
|
||||||
|
|
||||||
# Outgoing pins and their connections to nets
|
# Outgoing pins and their connections to nets
|
||||||
pin(1 name('1'))
|
pin(1 name('1'))
|
||||||
pin(2 name('2'))
|
pin(2 name('2'))
|
||||||
pin(3 name('3'))
|
pin(3 name('3'))
|
||||||
pin(4 name('4'))
|
pin(4 name('4'))
|
||||||
pin(name('5'))
|
pin(5 name('5'))
|
||||||
pin(5 name('6'))
|
pin(6 name('6'))
|
||||||
pin(6 name('7'))
|
pin(7 name('7'))
|
||||||
|
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2 name($2)
|
circuit(1 INV2 name($2)
|
||||||
pin(0 6)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 4)
|
||||||
pin(2 5)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 3)
|
||||||
pin(4 2)
|
pin(4 2)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
|
|
@ -1017,23 +1018,24 @@ reference(
|
||||||
net(2 name('2'))
|
net(2 name('2'))
|
||||||
net(3 name('3'))
|
net(3 name('3'))
|
||||||
net(4 name('4'))
|
net(4 name('4'))
|
||||||
net(5 name('6'))
|
net(5 name('5'))
|
||||||
net(6 name('7'))
|
net(6 name('6'))
|
||||||
|
net(7 name('7'))
|
||||||
|
|
||||||
# Outgoing pins and their connections to nets
|
# Outgoing pins and their connections to nets
|
||||||
pin(1 name('1'))
|
pin(1 name('1'))
|
||||||
pin(2 name('2'))
|
pin(2 name('2'))
|
||||||
pin(3 name('3'))
|
pin(3 name('3'))
|
||||||
pin(4 name('4'))
|
pin(4 name('4'))
|
||||||
pin(name('5'))
|
pin(5 name('5'))
|
||||||
pin(5 name('6'))
|
pin(6 name('6'))
|
||||||
pin(6 name('7'))
|
pin(7 name('7'))
|
||||||
|
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2 name($2)
|
circuit(1 INV2 name($2)
|
||||||
pin(0 6)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 4)
|
||||||
pin(2 5)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 3)
|
||||||
pin(4 2)
|
pin(4 2)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
|
|
@ -1068,28 +1070,57 @@ xref(
|
||||||
)
|
)
|
||||||
circuit(INV2PAIR INV2PAIR nomatch
|
circuit(INV2PAIR INV2PAIR nomatch
|
||||||
xref(
|
xref(
|
||||||
net(4 () mismatch)
|
net(3 2 mismatch)
|
||||||
net(2 2 mismatch)
|
net(4 3 mismatch)
|
||||||
net(3 3 mismatch)
|
|
||||||
net(5 4 match)
|
net(5 4 match)
|
||||||
net(6 5 match)
|
net(2 5 mismatch)
|
||||||
net(7 6 mismatch)
|
net(6 6 match)
|
||||||
|
net(7 7 mismatch)
|
||||||
net(1 1 mismatch)
|
net(1 1 mismatch)
|
||||||
pin(() 4 mismatch)
|
pin(2 1 match)
|
||||||
pin(3 () mismatch)
|
pin(3 2 match)
|
||||||
pin(1 1 match)
|
|
||||||
pin(2 2 match)
|
|
||||||
pin(4 3 match)
|
pin(4 3 match)
|
||||||
|
pin(1 4 match)
|
||||||
pin(5 5 match)
|
pin(5 5 match)
|
||||||
pin(6 6 match)
|
pin(6 6 match)
|
||||||
pin(0 0 match)
|
pin(0 0 match)
|
||||||
circuit(() 1 mismatch)
|
|
||||||
circuit(1 () mismatch)
|
|
||||||
circuit(2 () mismatch)
|
circuit(2 () mismatch)
|
||||||
|
circuit(1 1 mismatch)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
circuit(RINGO RINGO skipped
|
circuit(RINGO RINGO nomatch
|
||||||
xref(
|
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)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,24 @@ layout(
|
||||||
# Nets with their geometries
|
# Nets with their geometries
|
||||||
net(1 name(BULK))
|
net(1 name(BULK))
|
||||||
net(2
|
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 (4230 3290) (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 180) (220 220))
|
||||||
|
|
@ -289,7 +307,7 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -1560) (360 1560))
|
rect(metal1 (-360 -1560) (360 1560))
|
||||||
)
|
)
|
||||||
net(3
|
net(4
|
||||||
rect(diff_cont (4230 890) (220 220))
|
rect(diff_cont (4230 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 (-220 -620) (220 220))
|
||||||
|
|
@ -311,24 +329,6 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -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(5)
|
||||||
net(6
|
net(6
|
||||||
rect(diff_cont (3430 890) (220 220))
|
rect(diff_cont (3430 890) (220 220))
|
||||||
|
|
@ -363,17 +363,17 @@ layout(
|
||||||
circuit(1 INV2 location(1700 800)
|
circuit(1 INV2 location(1700 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 5)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 2)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
circuit(2 INV2 location(4340 800)
|
circuit(2 INV2 location(4340 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 2)
|
||||||
pin(2 6)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -808,45 +808,45 @@ layout(
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2PAIR location(19420 -800)
|
circuit(1 INV2PAIR location(19420 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 1)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 1)
|
pin(3 4)
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 2)
|
pin(5 2)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(2 INV2PAIR location(-1700 -800)
|
circuit(2 INV2PAIR location(-1700 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 8)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 8)
|
pin(3 4)
|
||||||
pin(4 1)
|
pin(4 1)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(3 INV2PAIR location(3580 -800)
|
circuit(3 INV2PAIR location(3580 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 7)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 7)
|
pin(3 4)
|
||||||
pin(4 9)
|
pin(4 9)
|
||||||
pin(5 12)
|
pin(5 12)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(4 INV2PAIR location(8860 -800)
|
circuit(4 INV2PAIR location(8860 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 6)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 6)
|
pin(3 4)
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 11)
|
pin(5 11)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(5 INV2PAIR location(14140 -800)
|
circuit(5 INV2PAIR location(14140 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 5)
|
pin(3 4)
|
||||||
pin(4 11)
|
pin(4 11)
|
||||||
pin(5 10)
|
pin(5 10)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
|
|
@ -918,23 +918,24 @@ reference(
|
||||||
net(2 name('2'))
|
net(2 name('2'))
|
||||||
net(3 name('3'))
|
net(3 name('3'))
|
||||||
net(4 name('4'))
|
net(4 name('4'))
|
||||||
net(5 name('6'))
|
net(5 name('5'))
|
||||||
net(6 name('7'))
|
net(6 name('6'))
|
||||||
|
net(7 name('7'))
|
||||||
|
|
||||||
# Outgoing pins and their connections to nets
|
# Outgoing pins and their connections to nets
|
||||||
pin(1 name('1'))
|
pin(1 name('1'))
|
||||||
pin(2 name('2'))
|
pin(2 name('2'))
|
||||||
pin(3 name('3'))
|
pin(3 name('3'))
|
||||||
pin(4 name('4'))
|
pin(4 name('4'))
|
||||||
pin(name('5'))
|
pin(5 name('5'))
|
||||||
pin(5 name('6'))
|
pin(6 name('6'))
|
||||||
pin(6 name('7'))
|
pin(7 name('7'))
|
||||||
|
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2 name($2)
|
circuit(1 INV2 name($2)
|
||||||
pin(0 6)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 4)
|
||||||
pin(2 5)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 3)
|
||||||
pin(4 2)
|
pin(4 2)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
|
|
@ -1017,23 +1018,24 @@ reference(
|
||||||
net(2 name('2'))
|
net(2 name('2'))
|
||||||
net(3 name('3'))
|
net(3 name('3'))
|
||||||
net(4 name('4'))
|
net(4 name('4'))
|
||||||
net(5 name('6'))
|
net(5 name('5'))
|
||||||
net(6 name('7'))
|
net(6 name('6'))
|
||||||
|
net(7 name('7'))
|
||||||
|
|
||||||
# Outgoing pins and their connections to nets
|
# Outgoing pins and their connections to nets
|
||||||
pin(1 name('1'))
|
pin(1 name('1'))
|
||||||
pin(2 name('2'))
|
pin(2 name('2'))
|
||||||
pin(3 name('3'))
|
pin(3 name('3'))
|
||||||
pin(4 name('4'))
|
pin(4 name('4'))
|
||||||
pin(name('5'))
|
pin(5 name('5'))
|
||||||
pin(5 name('6'))
|
pin(6 name('6'))
|
||||||
pin(6 name('7'))
|
pin(7 name('7'))
|
||||||
|
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2 name($2)
|
circuit(1 INV2 name($2)
|
||||||
pin(0 6)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 4)
|
||||||
pin(2 5)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 3)
|
||||||
pin(4 2)
|
pin(4 2)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
|
|
@ -1068,28 +1070,57 @@ xref(
|
||||||
)
|
)
|
||||||
circuit(INV2PAIR INV2PAIR nomatch
|
circuit(INV2PAIR INV2PAIR nomatch
|
||||||
xref(
|
xref(
|
||||||
net(4 () mismatch)
|
net(3 2 mismatch)
|
||||||
net(2 2 mismatch)
|
net(4 3 mismatch)
|
||||||
net(3 3 mismatch)
|
|
||||||
net(5 4 match)
|
net(5 4 match)
|
||||||
net(6 5 match)
|
net(2 5 mismatch)
|
||||||
net(7 6 mismatch)
|
net(6 6 match)
|
||||||
|
net(7 7 mismatch)
|
||||||
net(1 1 mismatch)
|
net(1 1 mismatch)
|
||||||
pin(() 4 mismatch)
|
pin(2 1 match)
|
||||||
pin(3 () mismatch)
|
pin(3 2 match)
|
||||||
pin(1 1 match)
|
|
||||||
pin(2 2 match)
|
|
||||||
pin(4 3 match)
|
pin(4 3 match)
|
||||||
|
pin(1 4 match)
|
||||||
pin(5 5 match)
|
pin(5 5 match)
|
||||||
pin(6 6 match)
|
pin(6 6 match)
|
||||||
pin(0 0 match)
|
pin(0 0 match)
|
||||||
circuit(() 1 mismatch)
|
|
||||||
circuit(1 () mismatch)
|
|
||||||
circuit(2 () mismatch)
|
circuit(2 () mismatch)
|
||||||
|
circuit(1 1 mismatch)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
circuit(RINGO RINGO skipped
|
circuit(RINGO RINGO nomatch
|
||||||
xref(
|
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)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,24 @@ layout(
|
||||||
# Nets with their geometries
|
# Nets with their geometries
|
||||||
net(1 name(BULK))
|
net(1 name(BULK))
|
||||||
net(2
|
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 (4230 3290) (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 180) (220 220))
|
||||||
|
|
@ -289,7 +307,7 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -1560) (360 1560))
|
rect(metal1 (-360 -1560) (360 1560))
|
||||||
)
|
)
|
||||||
net(3
|
net(4
|
||||||
rect(diff_cont (4230 890) (220 220))
|
rect(diff_cont (4230 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 (-220 -620) (220 220))
|
||||||
|
|
@ -311,24 +329,6 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -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(5)
|
||||||
net(6
|
net(6
|
||||||
rect(diff_cont (3430 890) (220 220))
|
rect(diff_cont (3430 890) (220 220))
|
||||||
|
|
@ -363,17 +363,17 @@ layout(
|
||||||
circuit(1 INV2 location(1700 800)
|
circuit(1 INV2 location(1700 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 5)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 2)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
circuit(2 INV2 location(4340 800)
|
circuit(2 INV2 location(4340 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 2)
|
||||||
pin(2 6)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -808,45 +808,45 @@ layout(
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2PAIR location(19420 -800)
|
circuit(1 INV2PAIR location(19420 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 1)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 1)
|
pin(3 4)
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 2)
|
pin(5 2)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(2 INV2PAIR location(-1700 -800)
|
circuit(2 INV2PAIR location(-1700 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 8)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 8)
|
pin(3 4)
|
||||||
pin(4 1)
|
pin(4 1)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(3 INV2PAIR location(3580 -800)
|
circuit(3 INV2PAIR location(3580 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 7)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 7)
|
pin(3 4)
|
||||||
pin(4 9)
|
pin(4 9)
|
||||||
pin(5 12)
|
pin(5 12)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(4 INV2PAIR location(8860 -800)
|
circuit(4 INV2PAIR location(8860 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 6)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 6)
|
pin(3 4)
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 11)
|
pin(5 11)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(5 INV2PAIR location(14140 -800)
|
circuit(5 INV2PAIR location(14140 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 5)
|
pin(3 4)
|
||||||
pin(4 11)
|
pin(4 11)
|
||||||
pin(5 10)
|
pin(5 10)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
|
|
@ -918,23 +918,24 @@ reference(
|
||||||
net(2 name('2'))
|
net(2 name('2'))
|
||||||
net(3 name('3'))
|
net(3 name('3'))
|
||||||
net(4 name('4'))
|
net(4 name('4'))
|
||||||
net(5 name('6'))
|
net(5 name('5'))
|
||||||
net(6 name('7'))
|
net(6 name('6'))
|
||||||
|
net(7 name('7'))
|
||||||
|
|
||||||
# Outgoing pins and their connections to nets
|
# Outgoing pins and their connections to nets
|
||||||
pin(1 name('1'))
|
pin(1 name('1'))
|
||||||
pin(2 name('2'))
|
pin(2 name('2'))
|
||||||
pin(3 name('3'))
|
pin(3 name('3'))
|
||||||
pin(4 name('4'))
|
pin(4 name('4'))
|
||||||
pin(name('5'))
|
pin(5 name('5'))
|
||||||
pin(5 name('6'))
|
pin(6 name('6'))
|
||||||
pin(6 name('7'))
|
pin(7 name('7'))
|
||||||
|
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2 name($2)
|
circuit(1 INV2 name($2)
|
||||||
pin(0 6)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 4)
|
||||||
pin(2 5)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 3)
|
||||||
pin(4 2)
|
pin(4 2)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
|
|
@ -1017,23 +1018,24 @@ reference(
|
||||||
net(2 name('2'))
|
net(2 name('2'))
|
||||||
net(3 name('3'))
|
net(3 name('3'))
|
||||||
net(4 name('4'))
|
net(4 name('4'))
|
||||||
net(5 name('6'))
|
net(5 name('5'))
|
||||||
net(6 name('7'))
|
net(6 name('6'))
|
||||||
|
net(7 name('7'))
|
||||||
|
|
||||||
# Outgoing pins and their connections to nets
|
# Outgoing pins and their connections to nets
|
||||||
pin(1 name('1'))
|
pin(1 name('1'))
|
||||||
pin(2 name('2'))
|
pin(2 name('2'))
|
||||||
pin(3 name('3'))
|
pin(3 name('3'))
|
||||||
pin(4 name('4'))
|
pin(4 name('4'))
|
||||||
pin(name('5'))
|
pin(5 name('5'))
|
||||||
pin(5 name('6'))
|
pin(6 name('6'))
|
||||||
pin(6 name('7'))
|
pin(7 name('7'))
|
||||||
|
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2 name($2)
|
circuit(1 INV2 name($2)
|
||||||
pin(0 6)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 4)
|
||||||
pin(2 5)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 3)
|
||||||
pin(4 2)
|
pin(4 2)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
|
|
@ -1068,28 +1070,57 @@ xref(
|
||||||
)
|
)
|
||||||
circuit(INV2PAIR INV2PAIR nomatch
|
circuit(INV2PAIR INV2PAIR nomatch
|
||||||
xref(
|
xref(
|
||||||
net(4 () mismatch)
|
net(3 2 mismatch)
|
||||||
net(2 2 mismatch)
|
net(4 3 mismatch)
|
||||||
net(3 3 mismatch)
|
|
||||||
net(5 4 match)
|
net(5 4 match)
|
||||||
net(6 5 match)
|
net(2 5 mismatch)
|
||||||
net(7 6 mismatch)
|
net(6 6 match)
|
||||||
|
net(7 7 mismatch)
|
||||||
net(1 1 mismatch)
|
net(1 1 mismatch)
|
||||||
pin(() 4 mismatch)
|
pin(2 1 match)
|
||||||
pin(3 () mismatch)
|
pin(3 2 match)
|
||||||
pin(1 1 match)
|
|
||||||
pin(2 2 match)
|
|
||||||
pin(4 3 match)
|
pin(4 3 match)
|
||||||
|
pin(1 4 match)
|
||||||
pin(5 5 match)
|
pin(5 5 match)
|
||||||
pin(6 6 match)
|
pin(6 6 match)
|
||||||
pin(0 0 match)
|
pin(0 0 match)
|
||||||
circuit(() 1 mismatch)
|
|
||||||
circuit(1 () mismatch)
|
|
||||||
circuit(2 () mismatch)
|
circuit(2 () mismatch)
|
||||||
|
circuit(1 1 mismatch)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
circuit(RINGO RINGO skipped
|
circuit(RINGO RINGO nomatch
|
||||||
xref(
|
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)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,24 @@ layout(
|
||||||
# Nets with their geometries
|
# Nets with their geometries
|
||||||
net(1 name(BULK))
|
net(1 name(BULK))
|
||||||
net(2
|
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 (4230 3290) (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 180) (220 220))
|
||||||
|
|
@ -289,7 +307,7 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -1560) (360 1560))
|
rect(metal1 (-360 -1560) (360 1560))
|
||||||
)
|
)
|
||||||
net(3
|
net(4
|
||||||
rect(diff_cont (4230 890) (220 220))
|
rect(diff_cont (4230 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 (-220 -620) (220 220))
|
||||||
|
|
@ -311,24 +329,6 @@ layout(
|
||||||
rect(metal1 (-3000 -1560) (360 1560))
|
rect(metal1 (-3000 -1560) (360 1560))
|
||||||
rect(metal1 (-360 -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(5)
|
||||||
net(6
|
net(6
|
||||||
rect(diff_cont (3430 890) (220 220))
|
rect(diff_cont (3430 890) (220 220))
|
||||||
|
|
@ -363,17 +363,17 @@ layout(
|
||||||
circuit(1 INV2 location(1700 800)
|
circuit(1 INV2 location(1700 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 5)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 2)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
circuit(2 INV2 location(4340 800)
|
circuit(2 INV2 location(4340 800)
|
||||||
pin(0 7)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 2)
|
||||||
pin(2 6)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 4)
|
||||||
pin(4 2)
|
pin(4 3)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -808,45 +808,45 @@ layout(
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2PAIR location(19420 -800)
|
circuit(1 INV2PAIR location(19420 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 1)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 1)
|
pin(3 4)
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 2)
|
pin(5 2)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(2 INV2PAIR location(-1700 -800)
|
circuit(2 INV2PAIR location(-1700 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 8)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 8)
|
pin(3 4)
|
||||||
pin(4 1)
|
pin(4 1)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(3 INV2PAIR location(3580 -800)
|
circuit(3 INV2PAIR location(3580 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 7)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 7)
|
pin(3 4)
|
||||||
pin(4 9)
|
pin(4 9)
|
||||||
pin(5 12)
|
pin(5 12)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(4 INV2PAIR location(8860 -800)
|
circuit(4 INV2PAIR location(8860 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 6)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 6)
|
pin(3 4)
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 11)
|
pin(5 11)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
)
|
)
|
||||||
circuit(5 INV2PAIR location(14140 -800)
|
circuit(5 INV2PAIR location(14140 -800)
|
||||||
pin(0 4)
|
pin(0 4)
|
||||||
pin(1 3)
|
pin(1 5)
|
||||||
pin(2 4)
|
pin(2 3)
|
||||||
pin(3 5)
|
pin(3 4)
|
||||||
pin(4 11)
|
pin(4 11)
|
||||||
pin(5 10)
|
pin(5 10)
|
||||||
pin(6 3)
|
pin(6 3)
|
||||||
|
|
@ -918,23 +918,24 @@ reference(
|
||||||
net(2 name('2'))
|
net(2 name('2'))
|
||||||
net(3 name('3'))
|
net(3 name('3'))
|
||||||
net(4 name('4'))
|
net(4 name('4'))
|
||||||
net(5 name('6'))
|
net(5 name('5'))
|
||||||
net(6 name('7'))
|
net(6 name('6'))
|
||||||
|
net(7 name('7'))
|
||||||
|
|
||||||
# Outgoing pins and their connections to nets
|
# Outgoing pins and their connections to nets
|
||||||
pin(1 name('1'))
|
pin(1 name('1'))
|
||||||
pin(2 name('2'))
|
pin(2 name('2'))
|
||||||
pin(3 name('3'))
|
pin(3 name('3'))
|
||||||
pin(4 name('4'))
|
pin(4 name('4'))
|
||||||
pin(name('5'))
|
pin(5 name('5'))
|
||||||
pin(5 name('6'))
|
pin(6 name('6'))
|
||||||
pin(6 name('7'))
|
pin(7 name('7'))
|
||||||
|
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2 name($2)
|
circuit(1 INV2 name($2)
|
||||||
pin(0 6)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 4)
|
||||||
pin(2 5)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 3)
|
||||||
pin(4 2)
|
pin(4 2)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
|
|
@ -1017,23 +1018,24 @@ reference(
|
||||||
net(2 name('2'))
|
net(2 name('2'))
|
||||||
net(3 name('3'))
|
net(3 name('3'))
|
||||||
net(4 name('4'))
|
net(4 name('4'))
|
||||||
net(5 name('6'))
|
net(5 name('5'))
|
||||||
net(6 name('7'))
|
net(6 name('6'))
|
||||||
|
net(7 name('7'))
|
||||||
|
|
||||||
# Outgoing pins and their connections to nets
|
# Outgoing pins and their connections to nets
|
||||||
pin(1 name('1'))
|
pin(1 name('1'))
|
||||||
pin(2 name('2'))
|
pin(2 name('2'))
|
||||||
pin(3 name('3'))
|
pin(3 name('3'))
|
||||||
pin(4 name('4'))
|
pin(4 name('4'))
|
||||||
pin(name('5'))
|
pin(5 name('5'))
|
||||||
pin(5 name('6'))
|
pin(6 name('6'))
|
||||||
pin(6 name('7'))
|
pin(7 name('7'))
|
||||||
|
|
||||||
# Subcircuits and their connections
|
# Subcircuits and their connections
|
||||||
circuit(1 INV2 name($2)
|
circuit(1 INV2 name($2)
|
||||||
pin(0 6)
|
pin(0 7)
|
||||||
pin(1 4)
|
pin(1 4)
|
||||||
pin(2 5)
|
pin(2 6)
|
||||||
pin(3 3)
|
pin(3 3)
|
||||||
pin(4 2)
|
pin(4 2)
|
||||||
pin(5 1)
|
pin(5 1)
|
||||||
|
|
@ -1068,28 +1070,57 @@ xref(
|
||||||
)
|
)
|
||||||
circuit(INV2PAIR INV2PAIR nomatch
|
circuit(INV2PAIR INV2PAIR nomatch
|
||||||
xref(
|
xref(
|
||||||
net(4 () mismatch)
|
net(3 2 mismatch)
|
||||||
net(2 2 mismatch)
|
net(4 3 mismatch)
|
||||||
net(3 3 mismatch)
|
|
||||||
net(5 4 match)
|
net(5 4 match)
|
||||||
net(6 5 match)
|
net(2 5 mismatch)
|
||||||
net(7 6 mismatch)
|
net(6 6 match)
|
||||||
|
net(7 7 mismatch)
|
||||||
net(1 1 mismatch)
|
net(1 1 mismatch)
|
||||||
pin(() 4 mismatch)
|
pin(2 1 match)
|
||||||
pin(3 () mismatch)
|
pin(3 2 match)
|
||||||
pin(1 1 match)
|
|
||||||
pin(2 2 match)
|
|
||||||
pin(4 3 match)
|
pin(4 3 match)
|
||||||
|
pin(1 4 match)
|
||||||
pin(5 5 match)
|
pin(5 5 match)
|
||||||
pin(6 6 match)
|
pin(6 6 match)
|
||||||
pin(0 0 match)
|
pin(0 0 match)
|
||||||
circuit(() 1 mismatch)
|
|
||||||
circuit(1 () mismatch)
|
|
||||||
circuit(2 () mismatch)
|
circuit(2 () mismatch)
|
||||||
|
circuit(1 1 mismatch)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
circuit(RINGO RINGO skipped
|
circuit(RINGO RINGO nomatch
|
||||||
xref(
|
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)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,11 @@ class Buddies_TestClass < TestBase
|
||||||
"strm2txt" => 0x62656769,
|
"strm2txt" => 0x62656769,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Windows CRLF -> LF translation
|
||||||
|
signature_equiv = {
|
||||||
|
0x300d0a53 => 0x300a5345
|
||||||
|
}
|
||||||
|
|
||||||
%w(strm2cif strm2dxf strm2gds strm2gdstxt strm2oas strm2txt).each do |bin|
|
%w(strm2cif strm2dxf strm2gds strm2gdstxt strm2oas strm2txt).each do |bin|
|
||||||
|
|
||||||
puts "Testing #{bin} ..."
|
puts "Testing #{bin} ..."
|
||||||
|
|
@ -74,6 +79,7 @@ class Buddies_TestClass < TestBase
|
||||||
|
|
||||||
File.open(out_file, "rb") do |file|
|
File.open(out_file, "rb") do |file|
|
||||||
sig = file.read(4).unpack('N').first
|
sig = file.read(4).unpack('N').first
|
||||||
|
sig = signature_equiv[sig] || sig
|
||||||
assert_equal(sig, signatures[bin])
|
assert_equal(sig, signatures[bin])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ X$2 3 5 2 6 INVX1
|
||||||
* net 2 VDD
|
* net 2 VDD
|
||||||
* net 3 IN
|
* net 3 IN
|
||||||
* net 4 VSS
|
* net 4 VSS
|
||||||
* device instance $1 r0 *1 0.85,2.135 NMOS
|
* device instance $1 r0 *1 0.85,5.8 PMOS
|
||||||
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
|
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,5.8 PMOS
|
* device instance $2 r0 *1 0.85,2.135 NMOS
|
||||||
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
|
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
|
.ENDS INVX1
|
||||||
|
|
|
||||||
|
|
@ -135,20 +135,7 @@ layout(
|
||||||
pin(4 name(VSS))
|
pin(4 name(VSS))
|
||||||
|
|
||||||
# Devices and their connections
|
# Devices and their connections
|
||||||
device(1 D$NMOS
|
device(1 D$PMOS
|
||||||
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
|
|
||||||
location(850 5800)
|
location(850 5800)
|
||||||
param(L 0.25)
|
param(L 0.25)
|
||||||
param(W 1.5)
|
param(W 1.5)
|
||||||
|
|
@ -161,6 +148,19 @@ layout(
|
||||||
terminal(D 1)
|
terminal(D 1)
|
||||||
terminal(B 2)
|
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
|
circuit(DINV
|
||||||
|
|
@ -430,8 +430,8 @@ xref(
|
||||||
pin(0 1 match)
|
pin(0 1 match)
|
||||||
pin(1 2 match)
|
pin(1 2 match)
|
||||||
pin(3 3 match)
|
pin(3 3 match)
|
||||||
device(1 1 match)
|
device(2 1 match)
|
||||||
device(2 2 match)
|
device(1 2 match)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
circuit(TOP TOP match
|
circuit(TOP TOP match
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
@ -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(
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
@ -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
|
||||||
Binary file not shown.
|
|
@ -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
|
||||||
Binary file not shown.
|
|
@ -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
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -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 3 VSS
|
||||||
* net 5 IN
|
* net 5 IN
|
||||||
* net 6 SUBSTRATE
|
* net 6 SUBSTRATE
|
||||||
* device instance $1 r0 *1 0.85,2.135 NMOS
|
* device instance $1 r0 *1 0.85,5.8 PMOS
|
||||||
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
|
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,5.8 PMOS
|
* device instance $2 r0 *1 0.85,2.135 NMOS
|
||||||
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
|
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
|
.ENDS INVX1
|
||||||
|
|
|
||||||
|
|
@ -190,20 +190,7 @@ layout(
|
||||||
pin(6 name(SUBSTRATE))
|
pin(6 name(SUBSTRATE))
|
||||||
|
|
||||||
# Devices and their connections
|
# Devices and their connections
|
||||||
device(1 D$NMOS$2
|
device(1 D$PMOS$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
|
|
||||||
location(850 5800)
|
location(850 5800)
|
||||||
param(L 0.25)
|
param(L 0.25)
|
||||||
param(W 1.5)
|
param(W 1.5)
|
||||||
|
|
@ -216,6 +203,19 @@ layout(
|
||||||
terminal(D 2)
|
terminal(D 2)
|
||||||
terminal(B 4)
|
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
|
circuit(RINGO
|
||||||
|
|
@ -825,8 +825,8 @@ xref(
|
||||||
pin(5 5 match)
|
pin(5 5 match)
|
||||||
pin(0 0 match)
|
pin(0 0 match)
|
||||||
pin(2 2 match)
|
pin(2 2 match)
|
||||||
device(1 2 match)
|
device(2 2 match)
|
||||||
device(2 1 match)
|
device(1 1 match)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
circuit(RINGO RINGO match
|
circuit(RINGO RINGO match
|
||||||
|
|
|
||||||
|
|
@ -163,9 +163,9 @@ layout(
|
||||||
rect(l11 (-1751 1099) (300 1400))
|
rect(l11 (-1751 1099) (300 1400))
|
||||||
rect(l11 (1100 -1700) (300 300))
|
rect(l11 (1100 -1700) (300 300))
|
||||||
rect(l11 (-300 0) (300 1400))
|
rect(l11 (-300 0) (300 1400))
|
||||||
rect(l2 (-375 -1450) (425 1500))
|
rect(l2 (-1750 -1450) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
rect(l6 (950 -4890) (425 950))
|
rect(l6 (-425 -4890) (425 950))
|
||||||
)
|
)
|
||||||
net(3 name(VSS)
|
net(3 name(VSS)
|
||||||
rect(l8 (410 1770) (180 180))
|
rect(l8 (410 1770) (180 180))
|
||||||
|
|
@ -371,9 +371,9 @@ layout(
|
||||||
net(2
|
net(2
|
||||||
rect(l8 (4710 3010) (180 180))
|
rect(l8 (4710 3010) (180 180))
|
||||||
rect(l11 (-850 -240) (610 300))
|
rect(l11 (-850 -240) (610 300))
|
||||||
rect(l2 (-1175 1800) (425 1500))
|
rect(l2 (-2550 1800) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
rect(l6 (950 -4890) (425 950))
|
rect(l6 (-425 -4890) (425 950))
|
||||||
)
|
)
|
||||||
net(3
|
net(3
|
||||||
rect(l8 (6510 3010) (180 180))
|
rect(l8 (6510 3010) (180 180))
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,6 +7,9 @@ target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
|
||||||
|
|
||||||
schematic("ringo.cir")
|
schematic("ringo.cir")
|
||||||
|
|
||||||
|
# preempt configuration (see below)
|
||||||
|
same_nets("top", "ENABLE", "RINGO", "ENABLE")
|
||||||
|
|
||||||
deep
|
deep
|
||||||
|
|
||||||
# Drawing layers
|
# Drawing layers
|
||||||
|
|
@ -71,7 +74,6 @@ connect_global(ptie, "SUBSTRATE")
|
||||||
same_circuits("top", "RINGO")
|
same_circuits("top", "RINGO")
|
||||||
same_circuits("INV", "INVX1")
|
same_circuits("INV", "INVX1")
|
||||||
same_circuits("DOESNOTEXIST", "DOESNOTEXIST2")
|
same_circuits("DOESNOTEXIST", "DOESNOTEXIST2")
|
||||||
same_nets("top", "ENABLE", "RINGO", "ENABLE")
|
|
||||||
same_nets("DOESNOTEXIST", "ENABLE", "DOESNOTEXIST2", "ENABLE")
|
same_nets("DOESNOTEXIST", "ENABLE", "DOESNOTEXIST2", "ENABLE")
|
||||||
|
|
||||||
netlist.simplify
|
netlist.simplify
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
|
||||||
|
|
||||||
schematic("ringo_pin_swapping.cir")
|
schematic("ringo_pin_swapping.cir")
|
||||||
|
|
||||||
|
# preempt configuration
|
||||||
|
equivalent_pins("ND2X1", 4, 5)
|
||||||
|
|
||||||
deep
|
deep
|
||||||
|
|
||||||
# Drawing layers
|
# Drawing layers
|
||||||
|
|
@ -68,7 +71,6 @@ connect_global(ptie, "SUBSTRATE")
|
||||||
|
|
||||||
# Compare section
|
# Compare section
|
||||||
|
|
||||||
equivalent_pins("ND2X1", 4, 5)
|
|
||||||
equivalent_pins("DOESNOTEXIST", 4, 5)
|
equivalent_pins("DOESNOTEXIST", 4, 5)
|
||||||
|
|
||||||
netlist.simplify
|
netlist.simplify
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
|
||||||
|
|
||||||
schematic("ringo.cir")
|
schematic("ringo.cir")
|
||||||
|
|
||||||
|
# preempt configuration
|
||||||
|
same_device_classes("PM", "PMOS")
|
||||||
|
|
||||||
deep
|
deep
|
||||||
|
|
||||||
# Drawing layers
|
# Drawing layers
|
||||||
|
|
@ -90,7 +93,6 @@ connect_global(ptie, "SUBSTRATE")
|
||||||
|
|
||||||
netlist.simplify
|
netlist.simplify
|
||||||
|
|
||||||
same_device_classes("PM", "PMOS")
|
|
||||||
same_device_classes("NM", "NMOS")
|
same_device_classes("NM", "NMOS")
|
||||||
same_device_classes("PMHV", "PMOSHV")
|
same_device_classes("PMHV", "PMOSHV")
|
||||||
same_device_classes("NMHV", "NMOSHV")
|
same_device_classes("NMHV", "NMOSHV")
|
||||||
|
|
|
||||||
|
|
@ -163,9 +163,9 @@ layout(
|
||||||
rect(l11 (-1751 1099) (300 1400))
|
rect(l11 (-1751 1099) (300 1400))
|
||||||
rect(l11 (1100 -1700) (300 300))
|
rect(l11 (1100 -1700) (300 300))
|
||||||
rect(l11 (-300 0) (300 1400))
|
rect(l11 (-300 0) (300 1400))
|
||||||
rect(l2 (-375 -1450) (425 1500))
|
rect(l2 (-1750 -1450) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
rect(l6 (950 -4890) (425 950))
|
rect(l6 (-425 -4890) (425 950))
|
||||||
)
|
)
|
||||||
net(3 name(VSS)
|
net(3 name(VSS)
|
||||||
rect(l8 (410 1770) (180 180))
|
rect(l8 (410 1770) (180 180))
|
||||||
|
|
@ -389,8 +389,8 @@ layout(
|
||||||
rect(l11 (1100 -300) (300 300))
|
rect(l11 (1100 -300) (300 300))
|
||||||
rect(l11 (-1101 399) (2 2))
|
rect(l11 (-1101 399) (2 2))
|
||||||
rect(l11 (799 -2101) (300 1400))
|
rect(l11 (799 -2101) (300 1400))
|
||||||
rect(l2 (-375 -1450) (425 1500))
|
rect(l2 (-1750 -1450) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
)
|
)
|
||||||
net(3 name(OUT)
|
net(3 name(OUT)
|
||||||
rect(l8 (1110 5160) (180 180))
|
rect(l8 (1110 5160) (180 180))
|
||||||
|
|
@ -486,9 +486,9 @@ layout(
|
||||||
net(1
|
net(1
|
||||||
rect(l8 (4710 3010) (180 180))
|
rect(l8 (4710 3010) (180 180))
|
||||||
rect(l11 (-850 -240) (610 300))
|
rect(l11 (-850 -240) (610 300))
|
||||||
rect(l2 (-1175 1800) (425 1500))
|
rect(l2 (-2550 1800) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
rect(l6 (950 -4890) (425 950))
|
rect(l6 (-425 -4890) (425 950))
|
||||||
)
|
)
|
||||||
net(2
|
net(2
|
||||||
rect(l8 (6510 3010) (180 180))
|
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 (1375 -1500) (425 1500))
|
||||||
rect(l2 (1375 -1500) (425 1500))
|
rect(l2 (1375 -1500) (425 1500))
|
||||||
rect(l2 (4550 -1500) (425 1500))
|
rect(l2 (3175 -1500) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
rect(l2 (-2225 -1500) (425 1500))
|
rect(l2 (-3600 -1500) (425 1500))
|
||||||
rect(l9 (-19575 -450) (500 1500))
|
rect(l9 (-19575 -450) (500 1500))
|
||||||
rect(l9 (22900 -1500) (500 1500))
|
rect(l9 (22900 -1500) (500 1500))
|
||||||
)
|
)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -26,16 +26,16 @@ X$5 6 4 9 6 3 9 INVX1
|
||||||
X$6 6 5 9 6 4 9 INVX1
|
X$6 6 5 9 6 4 9 INVX1
|
||||||
* cell instance $7 r0 *1 22.2,0
|
* cell instance $7 r0 *1 22.2,0
|
||||||
X$7 5 6 7 9 6 9 INVX2
|
X$7 5 6 7 9 6 9 INVX2
|
||||||
* cell instance $17 r0 *1 7.8,0
|
* cell instance $13 r0 *1 7.8,0
|
||||||
X$17 6 12 9 6 10 9 INVX1
|
X$13 6 12 9 6 10 9 INVX1
|
||||||
* cell instance $18 r0 *1 9.6,0
|
* cell instance $14 r0 *1 9.6,0
|
||||||
X$18 6 13 9 6 12 9 INVX1
|
X$14 6 13 9 6 12 9 INVX1
|
||||||
* cell instance $19 r0 *1 11.4,0
|
* cell instance $15 r0 *1 11.4,0
|
||||||
X$19 6 14 9 6 13 9 INVX1
|
X$15 6 14 9 6 13 9 INVX1
|
||||||
* cell instance $20 r0 *1 13.2,0
|
* cell instance $16 r0 *1 13.2,0
|
||||||
X$20 6 15 9 6 14 9 INVX1
|
X$16 6 15 9 6 14 9 INVX1
|
||||||
* cell instance $21 r0 *1 15,0
|
* cell instance $17 r0 *1 15,0
|
||||||
X$21 6 11 9 6 15 9 INVX1
|
X$17 6 11 9 6 15 9 INVX1
|
||||||
.ENDS RINGO
|
.ENDS RINGO
|
||||||
|
|
||||||
* cell INVX2
|
* cell INVX2
|
||||||
|
|
|
||||||
|
|
@ -711,7 +711,7 @@ layout(
|
||||||
pin(4 6)
|
pin(4 6)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(17 INVX1 location(7800 0)
|
circuit(13 INVX1 location(7800 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 12)
|
pin(1 12)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -719,7 +719,7 @@ layout(
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(18 INVX1 location(9600 0)
|
circuit(14 INVX1 location(9600 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 13)
|
pin(1 13)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -727,7 +727,7 @@ layout(
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(19 INVX1 location(11400 0)
|
circuit(15 INVX1 location(11400 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 14)
|
pin(1 14)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -735,7 +735,7 @@ layout(
|
||||||
pin(4 13)
|
pin(4 13)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(20 INVX1 location(13200 0)
|
circuit(16 INVX1 location(13200 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 15)
|
pin(1 15)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -743,7 +743,7 @@ layout(
|
||||||
pin(4 14)
|
pin(4 14)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(21 INVX1 location(15000 0)
|
circuit(17 INVX1 location(15000 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 11)
|
pin(1 11)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -1147,11 +1147,11 @@ xref(
|
||||||
pin(4 0 match)
|
pin(4 0 match)
|
||||||
circuit(2 2 match)
|
circuit(2 2 match)
|
||||||
circuit(3 3 match)
|
circuit(3 3 match)
|
||||||
circuit(17 4 match)
|
circuit(13 4 match)
|
||||||
circuit(18 5 match)
|
circuit(14 5 match)
|
||||||
circuit(19 6 match)
|
circuit(15 6 match)
|
||||||
circuit(20 7 match)
|
circuit(16 7 match)
|
||||||
circuit(21 8 match)
|
circuit(17 8 match)
|
||||||
circuit(4 9 match)
|
circuit(4 9 match)
|
||||||
circuit(5 10 match)
|
circuit(5 10 match)
|
||||||
circuit(6 11 match)
|
circuit(6 11 match)
|
||||||
|
|
|
||||||
|
|
@ -163,9 +163,9 @@ layout(
|
||||||
rect(l11 (-1751 1099) (300 1400))
|
rect(l11 (-1751 1099) (300 1400))
|
||||||
rect(l11 (1100 -1700) (300 300))
|
rect(l11 (1100 -1700) (300 300))
|
||||||
rect(l11 (-300 0) (300 1400))
|
rect(l11 (-300 0) (300 1400))
|
||||||
rect(l2 (-375 -1450) (425 1500))
|
rect(l2 (-1750 -1450) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
rect(l6 (950 -4890) (425 950))
|
rect(l6 (-425 -4890) (425 950))
|
||||||
)
|
)
|
||||||
net(3 name(VSS)
|
net(3 name(VSS)
|
||||||
rect(l8 (410 1770) (180 180))
|
rect(l8 (410 1770) (180 180))
|
||||||
|
|
@ -389,8 +389,8 @@ layout(
|
||||||
rect(l11 (1100 -300) (300 300))
|
rect(l11 (1100 -300) (300 300))
|
||||||
rect(l11 (-1101 399) (2 2))
|
rect(l11 (-1101 399) (2 2))
|
||||||
rect(l11 (799 -2101) (300 1400))
|
rect(l11 (799 -2101) (300 1400))
|
||||||
rect(l2 (-375 -1450) (425 1500))
|
rect(l2 (-1750 -1450) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
)
|
)
|
||||||
net(3 name(OUT)
|
net(3 name(OUT)
|
||||||
rect(l8 (1110 5160) (180 180))
|
rect(l8 (1110 5160) (180 180))
|
||||||
|
|
@ -486,9 +486,9 @@ layout(
|
||||||
net(1
|
net(1
|
||||||
rect(l8 (4710 3010) (180 180))
|
rect(l8 (4710 3010) (180 180))
|
||||||
rect(l11 (-850 -240) (610 300))
|
rect(l11 (-850 -240) (610 300))
|
||||||
rect(l2 (-1175 1800) (425 1500))
|
rect(l2 (-2550 1800) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
rect(l6 (950 -4890) (425 950))
|
rect(l6 (-425 -4890) (425 950))
|
||||||
)
|
)
|
||||||
net(2
|
net(2
|
||||||
rect(l8 (6510 3010) (180 180))
|
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 (1375 -1500) (425 1500))
|
||||||
rect(l2 (1375 -1500) (425 1500))
|
rect(l2 (1375 -1500) (425 1500))
|
||||||
rect(l2 (4550 -1500) (425 1500))
|
rect(l2 (3175 -1500) (425 1500))
|
||||||
rect(l2 (-1800 -1500) (425 1500))
|
rect(l2 (950 -1500) (425 1500))
|
||||||
rect(l2 (-2225 -1500) (425 1500))
|
rect(l2 (-3600 -1500) (425 1500))
|
||||||
rect(l9 (-19575 -450) (500 1500))
|
rect(l9 (-19575 -450) (500 1500))
|
||||||
rect(l9 (22900 -1500) (500 1500))
|
rect(l9 (22900 -1500) (500 1500))
|
||||||
)
|
)
|
||||||
|
|
@ -711,7 +711,7 @@ layout(
|
||||||
pin(4 6)
|
pin(4 6)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(17 INVX1 location(7800 0)
|
circuit(13 INVX1 location(7800 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 12)
|
pin(1 12)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -719,7 +719,7 @@ layout(
|
||||||
pin(4 10)
|
pin(4 10)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(18 INVX1 location(9600 0)
|
circuit(14 INVX1 location(9600 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 13)
|
pin(1 13)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -727,7 +727,7 @@ layout(
|
||||||
pin(4 12)
|
pin(4 12)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(19 INVX1 location(11400 0)
|
circuit(15 INVX1 location(11400 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 14)
|
pin(1 14)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -735,7 +735,7 @@ layout(
|
||||||
pin(4 13)
|
pin(4 13)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(20 INVX1 location(13200 0)
|
circuit(16 INVX1 location(13200 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 15)
|
pin(1 15)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -743,7 +743,7 @@ layout(
|
||||||
pin(4 14)
|
pin(4 14)
|
||||||
pin(5 9)
|
pin(5 9)
|
||||||
)
|
)
|
||||||
circuit(21 INVX1 location(15000 0)
|
circuit(17 INVX1 location(15000 0)
|
||||||
pin(0 6)
|
pin(0 6)
|
||||||
pin(1 11)
|
pin(1 11)
|
||||||
pin(2 9)
|
pin(2 9)
|
||||||
|
|
@ -1147,11 +1147,11 @@ xref(
|
||||||
pin(4 0 match)
|
pin(4 0 match)
|
||||||
circuit(2 2 match)
|
circuit(2 2 match)
|
||||||
circuit(3 3 match)
|
circuit(3 3 match)
|
||||||
circuit(17 4 match)
|
circuit(13 4 match)
|
||||||
circuit(18 5 match)
|
circuit(14 5 match)
|
||||||
circuit(19 6 match)
|
circuit(15 6 match)
|
||||||
circuit(20 7 match)
|
circuit(16 7 match)
|
||||||
circuit(21 8 match)
|
circuit(17 8 match)
|
||||||
circuit(4 9 match)
|
circuit(4 9 match)
|
||||||
circuit(5 10 match)
|
circuit(5 10 match)
|
||||||
circuit(6 11 match)
|
circuit(6 11 match)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -191,8 +191,8 @@ circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);
|
||||||
end;
|
end;
|
||||||
circuit RINGO ();
|
circuit RINGO ();
|
||||||
subcircuit INV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);
|
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 $2 (IN=FB,$2=$I38,OUT=$I37,$4=VSS,$5=VDD);
|
||||||
subcircuit INV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$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 $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 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD);
|
||||||
subcircuit INV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$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 ();
|
self.assertEqual(str(l2n.netlist()), """circuit RINGO ();
|
||||||
subcircuit INV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);
|
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 $2 (IN=FB,$2=$I38,OUT=$I37,$4=VSS,$5=VDD);
|
||||||
subcircuit INV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$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 $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 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD);
|
||||||
subcircuit INV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$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 ();
|
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 $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 $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=$I13,$6=$I5,$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 $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);
|
subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);
|
||||||
end;
|
end;
|
||||||
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);
|
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=$I4,VSS=$I5,VDD=$I6,BULK=BULK);
|
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5,BULK=BULK);
|
||||||
subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);
|
subcircuit INV2 $2 ($1=$I1,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5,BULK=BULK);
|
||||||
end;
|
end;
|
||||||
circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);
|
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);
|
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);
|
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 $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 $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=$I13,$6=$I5,$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 $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);
|
subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);
|
||||||
end;
|
end;
|
||||||
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);
|
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=$I4,VSS=$I5,VDD=$I6,BULK=BULK);
|
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5,BULK=BULK);
|
||||||
subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);
|
subcircuit INV2 $2 ($1=$I1,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5,BULK=BULK);
|
||||||
end;
|
end;
|
||||||
circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);
|
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);
|
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);
|
||||||
|
|
|
||||||
|
|
@ -227,8 +227,8 @@ circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);
|
||||||
end;
|
end;
|
||||||
circuit RINGO ();
|
circuit RINGO ();
|
||||||
subcircuit INV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);
|
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 $2 (IN=FB,$2=$I38,OUT=$I37,$4=VSS,$5=VDD);
|
||||||
subcircuit INV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$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 $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 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD);
|
||||||
subcircuit INV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$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)
|
assert_equal(l2n.netlist.to_s, <<END)
|
||||||
circuit RINGO ();
|
circuit RINGO ();
|
||||||
subcircuit INV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);
|
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 $2 (IN=FB,$2=$I38,OUT=$I37,$4=VSS,$5=VDD);
|
||||||
subcircuit INV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$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 $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 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD);
|
||||||
subcircuit INV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$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)
|
assert_equal(l2n.netlist.to_s, <<END)
|
||||||
circuit RINGO ();
|
circuit RINGO ();
|
||||||
subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);
|
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 $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=$I13,$6=$I5,$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 $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);
|
subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);
|
||||||
end;
|
end;
|
||||||
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);
|
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=$I4,VSS=$I5,VDD=$I6,BULK=BULK);
|
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5,BULK=BULK);
|
||||||
subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);
|
subcircuit INV2 $2 ($1=$I1,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5,BULK=BULK);
|
||||||
end;
|
end;
|
||||||
circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);
|
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);
|
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)
|
assert_equal(l2n.netlist.to_s, <<END)
|
||||||
circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);
|
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 $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 $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=$I13,$6=$I5,$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 $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);
|
subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);
|
||||||
end;
|
end;
|
||||||
circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);
|
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=$I4,VSS=$I5,VDD=$I6,BULK=BULK);
|
subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5,BULK=BULK);
|
||||||
subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);
|
subcircuit INV2 $2 ($1=$I1,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5,BULK=BULK);
|
||||||
end;
|
end;
|
||||||
circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);
|
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);
|
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);
|
||||||
|
|
|
||||||
|
|
@ -841,25 +841,36 @@ end;
|
||||||
END
|
END
|
||||||
|
|
||||||
nl3 = nl2.dup
|
nl3 = nl2.dup
|
||||||
nl2.flatten_circuit(nl2.circuit_by_name("PTRANS"))
|
nl3.flatten_circuit(nl3.circuit_by_name("NTRANS"))
|
||||||
nl2.flatten_circuit(nl2.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);
|
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 $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 $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=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 NMOS $4 (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;
|
||||||
END
|
END
|
||||||
|
|
||||||
nl3.flatten_circuit("{N,P}TRANS")
|
nl4 = nl2.dup
|
||||||
assert_equal(nl3.to_s, nl2.to_s)
|
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 = nl.dup
|
||||||
nl2.flatten_circuit("*") # smoke test
|
nl2.flatten_circuit("*") # smoke test
|
||||||
assert_equal(nl2.to_s, "")
|
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
|
end
|
||||||
|
|
||||||
def test_12_BlankAndPurgeCircuits
|
def test_12_BlankAndPurgeCircuits
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue