Merge pull request #432 from KLayout/issue-425

Issue 425
This commit is contained in:
Matthias Köfferlein 2019-12-02 21:13:14 +01:00 committed by GitHub
commit 8f8c393309
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 1110 additions and 702 deletions

View File

@ -105,6 +105,14 @@ Circuit &Circuit::operator= (const Circuit &other)
m_cell_index = other.m_cell_index;
m_pins = other.m_pins;
m_pin_by_id.clear ();
for (pin_list::iterator p = m_pins.begin (); p != m_pins.end (); ++p) {
if (m_pin_by_id.size () <= p->id ()) {
m_pin_by_id.resize (p->id () + 1, pin_list::iterator ());
}
m_pin_by_id [p->id ()] = p;
}
std::map<const Device *, Device *> device_table;
for (const_device_iterator i = other.begin_devices (); i != other.end_devices (); ++i) {
Device *d = new Device (*i);
@ -157,17 +165,22 @@ void Circuit::set_netlist (Netlist *netlist)
const Pin *Circuit::pin_by_id (size_t id) const
{
if (id >= m_pins.size ()) {
if (id >= m_pin_by_id.size ()) {
return 0;
} else {
return &m_pins [id];
pin_list::iterator pi = m_pin_by_id [id];
if (pi == pin_list::iterator ()) {
return 0;
} else {
return pi.operator-> ();
}
}
}
void Circuit::rename_pin (size_t id, const std::string &name)
{
if (id < m_pins.size ()) {
m_pins [id].set_name (name);
if (id < m_pin_by_id.size () && m_pin_by_id [id] != pin_list::iterator ()) {
m_pin_by_id [id]->set_name (name);
}
}
@ -207,6 +220,7 @@ void Circuit::clear ()
{
m_name.clear ();
m_pins.clear ();
m_pin_by_id.clear ();
m_devices.clear ();
m_nets.clear ();
m_subcircuits.clear ();
@ -290,22 +304,33 @@ Circuit::const_child_circuit_iterator Circuit::end_parents () const
void Circuit::clear_pins ()
{
m_pins.clear ();
m_pin_by_id.clear ();
}
const Pin &Circuit::add_pin (const Pin &pin)
{
m_pins.push_back (pin);
m_pins.back ().set_id (m_pins.size () - 1);
m_pins.back ().set_id (m_pin_by_id.size ());
m_pin_by_id.push_back (--m_pins.end ());
return m_pins.back ();
}
const Pin &Circuit::add_pin (const std::string &name)
{
m_pins.push_back (Pin (name));
m_pins.back ().set_id (m_pins.size () - 1);
m_pins.back ().set_id (m_pin_by_id.size ());
m_pin_by_id.push_back (--m_pins.end ());
return m_pins.back ();
}
void Circuit::remove_pin (size_t id)
{
if (id < m_pin_by_id.size () && m_pin_by_id [id] != pin_list::iterator ()) {
m_pins.erase (m_pin_by_id [id]);
m_pin_by_id [id] = pin_list::iterator ();
}
}
void Circuit::add_net (Net *net)
{
m_nets.push_back (net);
@ -550,17 +575,58 @@ void Circuit::connect_pin (size_t pin_id, Net *net)
}
}
void Circuit::purge_nets_keep_pins ()
{
do_purge_nets (true);
}
void Circuit::purge_nets ()
{
do_purge_nets (false);
}
void Circuit::do_purge_nets (bool keep_pins)
{
std::vector<db::Net *> nets_to_be_purged;
for (net_iterator n = begin_nets (); n != end_nets (); ++n) {
if (n->is_floating ()) {
if (n->is_passive ()) {
nets_to_be_purged.push_back (n.operator-> ());
}
}
std::set<size_t> pins_to_delete;
for (std::vector<db::Net *>::const_iterator n = nets_to_be_purged.begin (); n != nets_to_be_purged.end (); ++n) {
if (! keep_pins) {
for (db::Net::pin_iterator p = (*n)->begin_pins (); p != (*n)->end_pins (); ++p) {
pins_to_delete.insert (p->pin_id ());
}
}
delete *n;
}
if (! pins_to_delete.empty ()) {
// remove the pin references of the pins we're going to delete
for (refs_iterator r = begin_refs (); r != end_refs (); ++r) {
db::SubCircuit *subcircuit = r.operator-> ();
for (std::set<size_t>::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) {
db::Net *net = subcircuit->net_for_pin (*p);
for (db::Net::subcircuit_pin_iterator sp = net->begin_subcircuit_pins (); sp != net->end_subcircuit_pins (); ++sp) {
if (sp->pin_id () == *p && sp->subcircuit () == subcircuit) {
net->erase_subcircuit_pin (sp);
break;
}
}
}
}
// and actually remove those pins
for (std::set<size_t>::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) {
remove_pin (*p);
}
}
}
/**

View File

@ -89,7 +89,7 @@ class DB_PUBLIC Circuit
: public db::NetlistObject, public gsi::ObjectBase
{
public:
typedef tl::vector<Pin> pin_list;
typedef std::list<Pin> pin_list;
typedef pin_list::const_iterator const_pin_iterator;
typedef pin_list::iterator pin_iterator;
typedef tl::shared_collection<Device> device_list;
@ -330,6 +330,11 @@ public:
*/
const Pin &add_pin (const Pin &pin);
/**
* @brief Removes the pin with the given ID
*/
void remove_pin (size_t id);
/**
* @brief Begin iterator for the pins of the circuit (non-const version)
*/
@ -708,10 +713,19 @@ public:
/**
* @brief Purge unused nets
*
* This method will purge all nets which return "floating".
* This method will purge all nets which return "is_passive".
* Pins on these nets will also be removed.
*/
void purge_nets ();
/**
* @brief Purge unused nets but
*
* This method will purge all nets which return "is_passive".
* Pins on these nets will be kept but their net will be 0.
*/
void purge_nets_keep_pins ();
/**
* @brief Combine devices
*
@ -751,6 +765,7 @@ private:
db::cell_index_type m_cell_index;
net_list m_nets;
pin_list m_pins;
std::vector<pin_list::iterator> m_pin_by_id;
device_list m_devices;
subcircuit_list m_subcircuits;
Netlist *mp_netlist;
@ -780,6 +795,7 @@ private:
void set_netlist (Netlist *netlist);
bool combine_parallel_devices (const db::DeviceClass &cls);
bool combine_serial_devices (const db::DeviceClass &cls);
void do_purge_nets (bool keep_pins);
void devices_changed ();
void subcircuits_changed ();

View File

@ -472,7 +472,7 @@ void Netlist::remove_device_abstract (DeviceAbstract *device_abstract)
void Netlist::purge_nets ()
{
for (circuit_iterator c = begin_circuits (); c != end_circuits (); ++c) {
for (bottom_up_circuit_iterator c = begin_bottom_up (); c != end_bottom_up (); ++c) {
c->purge_nets ();
}
}

View File

@ -2951,14 +2951,34 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
// Report missing net assignment
for (db::NetGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) {
if (! i->has_other () && mp_logger) {
mp_logger->net_mismatch (i->net (), 0);
if (! i->has_other ()) {
if (mp_logger) {
if (good) {
mp_logger->match_nets (i->net (), 0);
} else {
mp_logger->net_mismatch (i->net (), 0);
}
}
if (good) {
// in the "good" case, match the nets against 0
g1.identify (g1.node_index_for_net (i->net ()), 0);
}
}
}
for (db::NetGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) {
if (! i->has_other () && mp_logger) {
mp_logger->net_mismatch (0, i->net ());
if (! i->has_other ()) {
if (mp_logger) {
if (good) {
mp_logger->match_nets (0, i->net ());
} else {
mp_logger->net_mismatch (0, i->net ());
}
}
if (good) {
// in the "good" case, match the nets against 0
g2.identify (g2.node_index_for_net (i->net ()), 0);
}
}
}
@ -2969,22 +2989,34 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
return good;
}
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
bool
NetlistComparer::handle_pin_mismatch (const db::NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const db::NetGraph &g2, const db::Circuit *c2, const db::Pin *pin2) const
{
const db::Circuit *c = pin1 ? c1 : c2;
const db::Pin *pin = pin1 ? pin1 : pin2;
const db::NetGraph *graph = pin1 ? &g1 : &g2;
const db::Net *net = c->net_for_pin (pin->id ());
// 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);
// Nets which are paired with "null" are "safely to be ignored" and
// pin matching against "null" is valid.
if (net) {
const db::NetGraphNode &n = graph->node (graph->node_index_for_net (net));
if (n.has_other () && n.other_net_index () == 0) {
if (mp_logger) {
mp_logger->match_pins (pin1, pin2);
}
return true;
}
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.
// "used" follows a heuristic criterion derived from the subcircuits which make use of this circuit:
// if one of these connects the pin to a net with either connections upwards, other subcircuits or
// devices, the pin is regarded "used".
// TODO: it would be better probably to have a global concept of "used pins" which considers all
// devices and propagates their presence as "used" property upwards, then downwards to the subcircuit
// pins.
bool is_not_connected = true;
for (db::Circuit::const_refs_iterator r = c->begin_refs (); r != c->end_refs () && is_not_connected; ++r) {
@ -2999,12 +3031,12 @@ NetlistComparer::handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1
if (mp_logger) {
mp_logger->match_pins (pin1, pin2);
}
return true;
} else {
if (mp_logger) {
mp_logger->pin_mismatch (pin1, pin2);
}
good = false;
pin_mismatch = true;
return false;
}
}
@ -3042,18 +3074,21 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
}
}
std::vector<const db::Pin *> abstract_pins;
std::multimap<size_t, const db::Pin *> net2pin;
std::vector<const db::Pin *> abstract_pins2;
std::multimap<size_t, const db::Pin *> net2pin2;
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 ());
if (net) {
net2pin.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ()));
net2pin2.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ()));
} else if (abstract_pin_name_mapping.find (p.operator-> ()) == abstract_pin_name_mapping.end ()) {
abstract_pins.push_back (p.operator-> ());
abstract_pins2.push_back (p.operator-> ());
}
}
std::vector<const db::Pin *>::iterator next_abstract = abstract_pins.begin ();
// collect missing assignment for circuit 1
std::multimap<size_t, const db::Pin *> net2pin1;
std::vector<const db::Pin *>::iterator next_abstract = abstract_pins2.begin ();
CircuitMapper &c12_pin_mapping = c12_circuit_and_pin_mapping [c1];
c12_pin_mapping.set_other (c2);
@ -3078,7 +3113,7 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
c12_pin_mapping.map_pin (p->id (), fp->second->id ());
c22_pin_mapping.map_pin (fp->second->id (), p->id ());
} else if (next_abstract != abstract_pins.end ()) {
} else if (next_abstract != abstract_pins2.end ()) {
// assign an abstract pin - this is a dummy assignment which is mitigated
// by declaring the pins equivalent in derive_pin_equivalence
@ -3093,7 +3128,10 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
} else {
// otherwise this is an error for subcircuits or worth a report for top-level circuits
handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch);
if (! handle_pin_mismatch (g1, c1, p.operator-> (), g2, c2, 0)) {
good = false;
pin_mismatch = true;
}
}
@ -3104,14 +3142,15 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
const db::NetGraphNode &n = *(g1.begin () + g1.node_index_for_net (net));
if (! n.has_other ()) {
handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch);
// remember and handle later when we know which pins are not mapped
net2pin1.insert (std::make_pair (g1.node_index_for_net (net), p.operator-> ()));
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 = net2pin2.find (n.other_net_index ());
for (db::Net::const_pin_iterator pi = net->begin_pins (); pi != net->end_pins (); ++pi) {
if (np != net2pin.end () && np->first == n.other_net_index ()) {
if (np != net2pin2.end () && np->first == n.other_net_index ()) {
if (mp_logger) {
mp_logger->match_pins (pi->pin (), np->second);
@ -3122,11 +3161,12 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
std::multimap<size_t, const db::Pin *>::iterator np_delete = np;
++np;
net2pin.erase (np_delete);
net2pin2.erase (np_delete);
} else {
handle_pin_mismatch (c1, pi->pin (), c2, 0, good, pin_mismatch);
// remember and handle later when we know which pins are not mapped
net2pin1.insert (std::make_pair (g1.node_index_for_net (net), p.operator-> ()));
}
@ -3134,16 +3174,28 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g
}
for (std::multimap<size_t, const db::Pin *>::iterator np = net2pin.begin (); np != net2pin.end (); ++np) {
handle_pin_mismatch (c1, 0, c2, np->second, good, pin_mismatch);
for (std::multimap<size_t, const db::Pin *>::iterator np = net2pin1.begin (); np != net2pin1.end (); ++np) {
if (! handle_pin_mismatch (g1, c1, np->second, g2, c2, 0)) {
good = false;
pin_mismatch = true;
}
}
for (std::multimap<size_t, const db::Pin *>::iterator np = net2pin2.begin (); np != net2pin2.end (); ++np) {
if (! handle_pin_mismatch (g1, c1, 0, g2, c2, np->second)) {
good = false;
pin_mismatch = true;
}
}
// abstract pins must match.
while (next_abstract != abstract_pins.end ()) {
handle_pin_mismatch (c1, 0, c2, *next_abstract, good, pin_mismatch);
while (next_abstract != abstract_pins2.end ()) {
if (! handle_pin_mismatch (g1, c1, 0, g2, c2, *next_abstract)) {
good = false;
pin_mismatch = true;
}
++next_abstract;
}
}
void
@ -3384,7 +3436,7 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG
bool mapped = true;
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 (! g2.begin () [i->second].has_other ()) {
mapped = false;
} else {
i->second = g2.begin () [i->second].other_net_index ();

View File

@ -314,7 +314,7 @@ protected:
void do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping, bool &pin_mismatch, bool &good) const;
void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, bool &good) const;
void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinMapper &circuit_pin_mapper, std::map<const db::Circuit *, CircuitMapper> &c12_circuit_and_pin_mapping, std::map<const db::Circuit *, CircuitMapper> &c22_circuit_and_pin_mapping, bool &good) const;
void handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1, const db::Circuit *c2, const db::Pin *p2, bool &good, bool &pin_mismatch) const;
bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const;
mutable NetlistCompareLogger *mp_logger;
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<const Net *, const Net *> > > m_same_nets;

View File

@ -508,8 +508,7 @@ NetlistCrossReference::build_pin_refs (const std::pair<const db::Net *, const db
std::map<const db::Pin *, const db::Pin *>::const_iterator ipb = m_other_pin.find (pa);
if (ipb != m_other_pin.end () && ipb->second) {
const db::Pin *pb = ipb->second;
std::map<const Pin *, const db::NetPinRef *>::iterator b = p2r_b.find (pb);
std::map<const Pin *, const db::NetPinRef *>::iterator b = p2r_b.find (ipb->second);
if (b != p2r_b.end ()) {
prb = b->second;
// remove the entry so we won't find it again
@ -558,7 +557,7 @@ NetlistCrossReference::build_subcircuit_pin_refs (const std::pair<const db::Net
const db::Pin *pa = sa->circuit_ref ()->pin_by_id (a->first.second);
std::map<const db::Pin *, const db::Pin *>::const_iterator ipb = m_other_pin.find (pa);
if (ipb != m_other_pin.end ()) {
if (ipb != m_other_pin.end () && ipb->second) {
std::map<std::pair<const db::SubCircuit *, size_t>, const db::NetSubcircuitPinRef *>::iterator b = s2t_b.find (std::make_pair (sb, ipb->second->id ()));
if (b != s2t_b.end ()) {

View File

@ -288,11 +288,6 @@ void NetlistSpiceReader::finish ()
pop_stream ();
}
// purge nets with single connections (this way unconnected pins can be realized)
if (mp_netlist) {
mp_netlist->purge_nets ();
}
mp_stream.reset (0);
mp_netlist = 0;
mp_circuit = 0;

View File

@ -1131,6 +1131,11 @@ Class<db::Circuit> decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit",
"to the outside through such a pin. The pin is added after all existing "
"pins. For more details see the \\Pin class."
) +
gsi::method ("remove_pin", &db::Circuit::remove_pin, gsi::arg ("id"),
"@brief Removes the pin with the given ID from the circuit\n"
"\n"
"This method has been introduced in version 0.26.2.\n"
) +
gsi::iterator ("each_child", (db::Circuit::child_circuit_iterator (db::Circuit::*) ()) &db::Circuit::begin_children, (db::Circuit::child_circuit_iterator (db::Circuit::*) ()) &db::Circuit::end_children,
"@brief Iterates over the child circuits of this circuit\n"
"Child circuits are the ones that are referenced from this circuit via subcircuits."
@ -1311,8 +1316,16 @@ Class<db::Circuit> decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit",
) +
gsi::method ("purge_nets", &db::Circuit::purge_nets,
"@brief Purges floating nets.\n"
"Floating nets can be created as effect of reconnections of devices or pins. "
"This method will eliminate all nets that make less than two connections."
"Floating nets are nets with no device or subcircuit attached to. Such floating "
"nets are removed in this step. If these nets are connected outward to a circuit pin, this "
"circuit pin is also removed."
) +
gsi::method ("purge_nets_keep_pins", &db::Circuit::purge_nets_keep_pins,
"@brief Purges floating nets but keep pins.\n"
"This method will remove floating nets like \\purge_nets, but if these nets are attached "
"to a pin, the pin will be left disconnected from any net.\n"
"\n"
"This method has been introduced in version 0.26.2.\n"
),
"@brief Circuits are the basic building blocks of the netlist\n"
"A circuit has pins by which it can connect to the outside. Pins are "

View File

@ -2055,11 +2055,11 @@ TEST(14_Subcircuit2NandMismatchNoSwap)
"net_mismatch INT IN1\n"
"net_mismatch IN1 INT\n"
"net_mismatch IN2 IN2\n"
"match_pins $0 (null)\n"
"match_pins $1 $1\n"
"match_pins $2 $2\n"
"match_pins $3 $3\n"
"match_pins $4 $4\n"
"match_pins $0 (null)\n"
"match_pins (null) $0\n"
"match_subcircuits $2 $1\n"
"subcircuit_mismatch $1 $2\n"
@ -3366,3 +3366,340 @@ TEST(21_BusLikeAmbiguousConnections)
EXPECT_EQ (good, true);
}
TEST(22_NodesRemoved)
{
const char *nls1 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n"
" subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n"
" subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n"
" subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n"
" subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n"
"end;\n"
"circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n"
" subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n"
" subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n"
"end;\n"
"circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n";
const char *nls2 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n"
" subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n"
" subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n"
" subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n"
" subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n"
"end;\n"
"circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\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"
"end;\n"
"circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\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 INV2 INV2\n"
"match_nets VDD VDD\n"
"match_nets OUT OUT\n"
"match_nets $3 $3\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets (null) $1\n"
"match_nets (null) BULK\n"
"match_pins IN IN\n"
"match_pins $1 $2\n"
"match_pins OUT OUT\n"
"match_pins VSS VSS\n"
"match_pins VDD VDD\n"
"match_pins (null) $0\n"
"match_pins (null) BULK\n"
"match_devices $1 $1\n"
"match_devices $2 $2\n"
"match_devices $3 $3\n"
"match_devices $4 $4\n"
"end_circuit INV2 INV2 MATCH\n"
"begin_circuit INV2PAIR INV2PAIR\n"
"match_nets $I2 $I2\n"
"match_nets $I5 $I6\n"
"match_nets $I4 $I5\n"
"match_nets $I6 $I4\n"
"match_nets $I3 $I3\n"
"match_nets $I7 $I7\n"
"match_nets $I8 $I8\n"
"match_nets (null) BULK\n"
"match_nets (null) $I1\n"
"match_pins $0 $1\n"
"match_pins $1 $2\n"
"match_pins $2 $3\n"
"match_pins $3 $4\n"
"match_pins $4 $5\n"
"match_pins (null) BULK\n"
"match_pins (null) $6\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"end_circuit INV2PAIR INV2PAIR MATCH\n"
"begin_circuit RINGO RINGO\n"
"match_nets OSC OSC\n"
"match_nets $I7 $I7\n"
"match_nets $I6 $I6\n"
"match_nets $I5 $I5\n"
"match_nets $I21 $I13\n"
"match_nets FB FB\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets $I22 $I22\n"
"match_nets $I23 $I23\n"
"match_nets $I24 $I24\n"
"match_nets $I25 $I25\n"
"match_pins FB FB\n"
"match_pins OSC OSC\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"match_subcircuits $3 $3\n"
"match_subcircuits $4 $4\n"
"match_subcircuits $5 $5\n"
"end_circuit RINGO RINGO MATCH"
);
EXPECT_EQ (good, true);
}
TEST(23_NodesRemovedWithError)
{
const char *nls1 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n"
" subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n"
" subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n"
" subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n"
" subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n"
"end;\n"
"circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n"
// NOTE: $1 pin should not be connected to different nets, although it's not functional
" subcircuit INV2 $1 ($1=$3,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n"
" subcircuit INV2 $2 ($1=$6,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n"
"end;\n"
"circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n";
const char *nls2 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n"
" subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n"
" subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n"
" subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n"
" subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n"
"end;\n"
"circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\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"
"end;\n"
"circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\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 INV2 INV2\n"
"match_nets $1 $1\n"
"match_nets VDD VDD\n"
"match_nets OUT OUT\n"
"match_nets $3 $3\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets (null) BULK\n"
"match_pins $0 $0\n"
"match_pins IN IN\n"
"match_pins $2 $2\n"
"match_pins OUT OUT\n"
"match_pins VSS VSS\n"
"match_pins VDD VDD\n"
"match_pins (null) BULK\n"
"match_devices $1 $1\n"
"match_devices $2 $2\n"
"match_devices $3 $3\n"
"match_devices $4 $4\n"
"end_circuit INV2 INV2 MATCH\n"
"begin_circuit INV2PAIR INV2PAIR\n"
"match_nets $I2 $I2\n"
"match_nets $I5 $I6\n"
"match_nets $I4 $I5\n"
"match_nets $I6 $I4\n"
"match_nets $I3 $I3\n"
"match_nets $I7 $I7\n"
"net_mismatch $3 $I1\n"
"match_nets $I8 $I8\n"
"net_mismatch $6 BULK\n"
"match_pins $0 $1\n"
"match_pins $1 $2\n"
"match_pins $2 $3\n"
"match_pins $3 $4\n"
"match_pins $4 $5\n"
"pin_mismatch (null) BULK\n"
"pin_mismatch (null) $6\n"
"match_subcircuits $1 $1\n"
"subcircuit_mismatch $2 $2\n"
"end_circuit INV2PAIR INV2PAIR NOMATCH\n"
"circuit_skipped RINGO RINGO"
);
EXPECT_EQ (good, false);
}
TEST(24_NodesRemovedButConnectedInOther)
{
const char *nls1 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n"
" subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n"
" subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n"
" subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n"
" subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n"
"end;\n"
"circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n"
" subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n"
" subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n"
"end;\n"
"circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n";
const char *nls2 =
"circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n"
" subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n"
" subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n"
" subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n"
" subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n"
" subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n"
"end;\n"
// rewired here: BULK->VSS (pin $4), $1->$I3/$I4 (both rewired pins are deleted in the first netlist)
// This proves that we can basically do everything with the dropped pins.
"circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n"
" subcircuit INV2 $1 ($1=$I3,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=$I5);\n"
" subcircuit INV2 $2 ($1=$I4,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=$I5);\n"
"end;\n"
"circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n"
" device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\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 INV2 INV2\n"
"match_nets VDD VDD\n"
"match_nets OUT OUT\n"
"match_nets $3 $3\n"
"match_nets IN IN\n"
"match_nets VSS VSS\n"
"match_nets (null) $1\n"
"match_nets (null) BULK\n"
"match_pins IN IN\n"
"match_pins $1 $2\n"
"match_pins OUT OUT\n"
"match_pins VSS VSS\n"
"match_pins VDD VDD\n"
"match_pins (null) $0\n"
"match_pins (null) BULK\n"
"match_devices $1 $1\n"
"match_devices $2 $2\n"
"match_devices $3 $3\n"
"match_devices $4 $4\n"
"end_circuit INV2 INV2 MATCH\n"
"begin_circuit INV2PAIR INV2PAIR\n"
"match_nets $I2 $I2\n"
"match_nets $I5 $I6\n"
"match_nets $I4 $I5\n"
"match_nets $I6 $I4\n"
"match_nets $I3 $I3\n"
"match_nets $I7 $I7\n"
"match_nets $I8 $I8\n"
"match_nets (null) BULK\n"
"match_nets (null) $I1\n"
"match_pins $0 $1\n"
"match_pins $1 $2\n"
"match_pins $2 $3\n"
"match_pins $3 $4\n"
"match_pins $4 $5\n"
"match_pins (null) BULK\n"
"match_pins (null) $6\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"end_circuit INV2PAIR INV2PAIR MATCH\n"
"begin_circuit RINGO RINGO\n"
"match_nets OSC OSC\n"
"match_nets $I7 $I7\n"
"match_nets $I6 $I6\n"
"match_nets $I5 $I5\n"
"match_nets $I21 $I13\n"
"match_nets FB FB\n"
"match_nets VSS VSS\n"
"match_nets VDD VDD\n"
"match_nets $I22 $I22\n"
"match_nets $I23 $I23\n"
"match_nets $I24 $I24\n"
"match_nets $I25 $I25\n"
"match_pins FB FB\n"
"match_pins OSC OSC\n"
"match_pins VDD VDD\n"
"match_pins VSS VSS\n"
"match_subcircuits $1 $1\n"
"match_subcircuits $2 $2\n"
"match_subcircuits $3 $3\n"
"match_subcircuits $4 $4\n"
"match_subcircuits $5 $5\n"
"end_circuit RINGO RINGO MATCH"
);
EXPECT_EQ (good, true);
}

View File

@ -2573,3 +2573,134 @@ TEST(12_FloatingSubcircuitExtraction)
);
}
TEST(13_RemoveDummyPins)
{
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, "issue-425.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;
// 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;
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);
// perform the net extraction
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
db::NetlistExtractor net_ex;
net_ex.set_include_floating_subcircuits (true);
net_ex.extract_nets (dss, 0, conn, nl, cl);
nl.simplify ();
// compare netlist as string
CHECKPOINT ();
db::compare_netlist (_this, nl,
"circuit RINGO (FB=FB,VSS=VSS,VDD=VDD);\n"
" subcircuit INV2 $1 (IN=FB,OUT=$I25,$3=VSS,$4=VDD);\n"
" subcircuit INV2 $2 (IN=$I25,OUT=$I1,$3=VSS,$4=VDD);\n"
" subcircuit INV2 $3 (IN=$I1,OUT=$I2,$3=VSS,$4=VDD);\n"
" subcircuit INV2 $4 (IN=$I2,OUT=$I3,$3=VSS,$4=VDD);\n"
"end;\n"
"circuit INV2 (IN=IN,OUT=OUT,$3=$4,$4=$5);\n"
" device PMOS $1 (S=$2,G=IN,D=$5) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=$5,G=$2,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=$2,G=IN,D=$4) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
"end;\n"
);
}

View File

@ -360,6 +360,17 @@ TEST(3_CircuitBasic)
EXPECT_EQ (c2.pin_by_id (0)->name (), "p1");
EXPECT_EQ (c2.pin_by_id (1)->name (), "p2");
EXPECT_EQ (c2.pin_by_id (2), 0);
c2.remove_pin (1);
EXPECT_EQ (c2.pin_by_id (0)->name (), "p1");
EXPECT_EQ (c2.pin_by_id (1), 0);
EXPECT_EQ (c2.pin_by_id (2), 0);
db::Pin p3 = c2.add_pin ("p3");
EXPECT_EQ (c2.pin_by_id (0)->name (), "p1");
EXPECT_EQ (c2.pin_by_id (1), 0);
EXPECT_EQ (c2.pin_by_id (2)->name (), "p3");
EXPECT_EQ (c2.pin_by_id (3), 0);
}
TEST(4_CircuitDevices)
@ -1393,7 +1404,7 @@ TEST(22_BlankCircuit)
nl2.purge ();
EXPECT_EQ (nl2.to_string (),
"circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=VDD);\n"
"circuit RINGO (OSC=OSC,VSS=VSS,VDD=VDD);\n"
" subcircuit INV2 INV2_SC1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);\n"
" subcircuit INV2 INV2_SC2 (IN=FB,$2=(null),OUT=$I8,$4=VSS,$5=VDD);\n"
"end;\n"

View File

@ -30,22 +30,14 @@
#include "lymMacro.h"
#include "tlFileUtils.h"
void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string &suffix, const std::string &layout)
void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string &au_netlist, const std::string &layout, bool priv = false)
{
std::string rs = tl::testsrc ();
rs += "/testdata/lvs/" + lvs_rs;
std::string testsrc = priv ? tl::testsrc_private () : tl::testsrc ();
testsrc = tl::combine_path (tl::combine_path (testsrc, "testdata"), "lvs");
std::string src = tl::testsrc ();
src += "/testdata/lvs/" + layout;
std::string au_lvsdb = tl::testsrc ();
au_lvsdb += "/testdata/lvs/" + suffix + ".lvsdb.gz";
std::string au_cir = tl::testsrc ();
au_cir += "/testdata/lvs/" + suffix + ".cir.gz";
std::string au_l2n = tl::testsrc ();
au_l2n += "/testdata/lvs/" + suffix + ".l2n.gz";
std::string rs = tl::combine_path (testsrc, lvs_rs);
std::string ly = tl::combine_path (testsrc, layout);
std::string au_cir = tl::combine_path (testsrc, au_netlist);
std::string output_lvsdb = _this->tmp_file ("tmp.lvsdb");
std::string output_cir = _this->tmp_file ("tmp.cir");
@ -59,7 +51,7 @@ void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string
"$lvs_test_target_lvsdb = '%s'\n"
"$lvs_test_target_cir = '%s'\n"
"$lvs_test_target_l2n = '%s'\n"
, src, output_lvsdb, output_cir, output_l2n)
, ly, output_lvsdb, output_cir, output_l2n)
);
config.set_interpreter (lym::Macro::Ruby);
EXPECT_EQ (config.run (), 0);
@ -101,11 +93,53 @@ void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string
TEST(1_full)
{
test_is_long_runner ();
run_test (_this, "vexriscv.lvs", "vexriscv", "vexriscv.oas.gz");
run_test (_this, "vexriscv.lvs", "vexriscv.cir.gz", "vexriscv.oas.gz");
}
TEST(2_fullWithAlign)
{
test_is_long_runner ();
run_test (_this, "vexriscv_align.lvs", "vexriscv", "vexriscv.oas.gz");
run_test (_this, "vexriscv_align.lvs", "vexriscv.cir.gz", "vexriscv.oas.gz");
}
TEST(10_private)
{
// test_is_long_runner ();
run_test (_this, "test_10.lvs", "test_10.cir.gz", "test_10.gds.gz", true);
}
TEST(11_private)
{
// test_is_long_runner ();
run_test (_this, "test_11.lvs", "test_11.cir.gz", "test_11.gds.gz", true);
}
TEST(12_private)
{
// test_is_long_runner ();
run_test (_this, "test_12.lvs", "test_12.cir.gz", "test_12.gds.gz", true);
}
TEST(13_private)
{
// test_is_long_runner ();
run_test (_this, "test_13.lvs", "test_13.cir.gz", "test_13.gds.gz", true);
}
TEST(14_private)
{
test_is_long_runner ();
run_test (_this, "test_14.lvs", "test_14.cir.gz", "test_14.gds.gz", true);
}
TEST(15_private)
{
// test_is_long_runner ();
run_test (_this, "test_15.lvs", "test_15.cir.gz", "test_15.gds.gz", true);
}
TEST(16_private)
{
// test_is_long_runner ();
run_test (_this, "test_16.lvs", "test_16.cir.gz", "test_16.gds.gz", true);
}

BIN
testdata/algo/issue-425.gds vendored Normal file

Binary file not shown.

View File

@ -1120,7 +1120,7 @@ xref(
circuit(3 () mismatch)
circuit(4 () mismatch)
circuit(5 () mismatch)
circuit(1 1 mismatch)
circuit(1 1 match)
)
)
)

View File

@ -1120,7 +1120,7 @@ xref(
circuit(3 () mismatch)
circuit(4 () mismatch)
circuit(5 () mismatch)
circuit(1 1 mismatch)
circuit(1 1 match)
)
)
)

View File

@ -1,30 +1,25 @@
* 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
.SUBCKT INVCHAIN IN OUT VSS VDD
X$1 IN \$2 \$3 \$2 \$3 \$4 VDD VSS INV3
X$2 \$5 \$6 \$4 \$5 VDD VSS INV2
X$3 VSS VDD \$6 OUT 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
.SUBCKT INV3 3 5 7 4 6 8 \$I4 \$I2
X$1 \$I2 \$I4 3 4 INV
X$2 \$I2 \$I4 5 6 INV
X$3 \$I2 \$I4 7 8 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
.SUBCKT INV2 \$I8 \$I7 \$I6 \$I5 \$I4 \$I2
X$1 \$I2 \$I4 \$I6 \$I8 INV
X$2 \$I2 \$I4 \$I5 \$I7 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
.SUBCKT INV \$1 \$2 \$3 \$4
M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
+ PD=3.45U
M$2 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
+ PD=3.45U
.ENDS INV

View File

@ -1,30 +0,0 @@
* 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

View File

@ -1,30 +0,0 @@
* 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

View File

@ -1,30 +0,0 @@
* 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 \$6 \$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 \$6 \$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

View File

@ -6,7 +6,52 @@ 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")
# needs this delegate because we use MOS3 which is not available in Spice
class SpiceReaderDelegate < RBA::NetlistSpiceReaderDelegate
# says we want to catch these subcircuits as devices
def wants_subcircuit(name)
name == "HVNMOS" || name == "HVPMOS"
end
# translate the element
def element(circuit, el, name, model, value, nets, params)
if el != "M"
# all other elements are left to the standard implementation
return super
end
if nets.size != 4
error("Device #{model} needs four nodes")
end
# provide a device class
cls = circuit.netlist.device_class_by_name(model)
if ! cls
cls = RBA::DeviceClassMOS3Transistor::new
cls.name = model
circuit.netlist.add(cls)
end
# create a device
device = circuit.create_device(cls, name)
# and configure the device
[ "S", "G", "D" ].each_with_index do |t,index|
device.connect_terminal(t, nets[index])
end
device.set_parameter("W", params["W"] * 1e6)
device.set_parameter("L", params["L"] * 1e6)
device
end
end
reader = RBA::NetlistSpiceReader::new(SpiceReaderDelegate::new)
schematic("invchain_for_cheat.cir", reader)
deep
@ -15,32 +60,38 @@ deep
nwell = input(1, 0)
active = input(2, 0)
poly = input(3, 0)
poly_lbl = input(3, 1)
diff_cont = input(4, 0)
poly_cont = input(5, 0)
metal1 = input(6, 0)
metal1_lbl = input(6, 1)
via1 = input(7, 0)
metal2 = input(8, 0)
metal2_lbl = input(8, 1)
# 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
psd = nil
nsd = nil
cheat("INV") do
# 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
# PMOS transistor device extraction
extract_devices(mos3("PMOS"), { "SD" => psd, "G" => pgate,
"tS" => psd, "tD" => psd, "tG" => poly })
@ -62,12 +113,18 @@ connect(poly_cont, metal1)
connect(metal1, via1)
connect(via1, metal2)
# attach labels
connect(poly, poly_lbl)
connect(metal1, metal1_lbl)
connect(metal2, metal2_lbl)
# Global
connect_global(bulk, "SUBSTRATE")
# Compare section
netlist.simplify
align
compare

View File

@ -3,66 +3,50 @@ J(
W(INVCHAIN)
U(0.001)
L(l3 '3/0')
L(l11 '3/1')
L(l6 '4/0')
L(l7 '2/0')
L(l7 '5/0')
L(l8 '6/0')
L(l12 '6/1')
L(l9 '7/0')
L(l10 '8/0')
L(l11)
L(l13 '8/1')
L(l14)
L(l2)
L(l5)
C(l3 l3 l7)
C(l3 l3 l11 l7)
C(l11 l3 l11)
C(l6 l6 l8 l2 l5)
C(l7 l3 l7 l8)
C(l8 l6 l7 l8 l9)
C(l8 l6 l7 l8 l12 l9)
C(l12 l8 l12)
C(l9 l8 l9 l10)
C(l10 l9 l10)
C(l11 l11)
C(l10 l9 l10 l13)
C(l13 l10 l13)
C(l14 l14)
C(l2 l6 l2)
C(l5 l6 l5)
G(l11 SUBSTRATE)
G(l14 SUBSTRATE)
D(D$PMOS PMOS
T(S
R(l2 (-960 -475) (835 950))
R(l2 (-900 -475) (775 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))
R(l2 (125 -475) (775 950))
)
)
D(D$NMOS NMOS
T(S
R(l5 (-960 -475) (835 950))
R(l5 (-900 -475) (775 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))
R(l5 (125 -475) (775 950))
)
)
X(INV
@ -74,7 +58,7 @@ J(
R(l9 (-305 -705) (250 250))
R(l9 (-250 150) (250 250))
R(l10 (-2025 -775) (3000 900))
R(l5 (-1375 -925) (550 950))
R(l5 (-1375 -925) (775 950))
)
N(2
R(l6 (290 2490) (220 220))
@ -83,7 +67,7 @@ J(
R(l9 (-305 -705) (250 250))
R(l9 (-250 150) (250 250))
R(l10 (-2025 -775) (3000 900))
R(l2 (-1375 -925) (550 950))
R(l2 (-1375 -925) (775 950))
)
N(3
R(l3 (-125 -250) (250 2500))
@ -98,99 +82,55 @@ J(
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))
R(l2 (-680 -855) (775 950))
R(l5 (-775 -3750) (775 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)
E(AS 0.73625)
E(AD 0.73625)
E(PS 3.45)
E(PD 3.45)
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
D(2 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)
E(AS 0.73625)
E(AD 0.73625)
E(PS 3.45)
E(PD 3.45)
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
N(1
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
N(2
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
N(3)
N(4)
N(5
R(l6 (990 3290) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
@ -198,7 +138,7 @@ J(
R(l8 (-3590 -690) (360 760))
R(l8 (2940 -760) (360 760))
)
N(14
N(6
R(l6 (990 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (3080 -620) (220 220))
@ -212,63 +152,52 @@ J(
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(0 6)
P(1 5)
P(2 3)
P(3 11)
P(4 9)
P(5 7)
P(6 1)
P(7 5)
P(3 1)
)
X(2 INV Y(4000 800)
P(0 14)
P(1 13)
P(0 6)
P(1 5)
P(2 4)
P(3 12)
P(4 10)
P(5 8)
P(6 2)
P(7 6)
P(3 2)
)
)
X(INV3
R((0 0) (6300 4600))
N(1)
N(2
N(1 I('3')
R(l11 (1509 1929) (2 2))
)
N(2 I('5')
R(l11 (2319 1909) (2 2))
)
N(3 I('7')
R(l11 (4829 1889) (2 2))
)
N(4 I('4')
R(l6 (990 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l12 (-121 -1941) (2 2))
)
N(3)
N(4)
N(5)
N(6)
N(7)
N(8)
N(9
N(5 I('6')
R(l6 (2590 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l12 (-131 -1971) (2 2))
)
N(10
N(6 I('8')
R(l6 (4290 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l12 (-101 -1991) (2 2))
)
N(11
N(7
R(l6 (1790 3290) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 -620) (220 220))
@ -279,7 +208,7 @@ J(
R(l8 (-360 -760) (360 760))
R(l8 (2940 -760) (360 760))
)
N(12
N(8
R(l6 (1790 490) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 -620) (220 220))
@ -290,136 +219,92 @@ J(
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(1 I('3'))
P(2 I('5'))
P(3 I('7'))
P(4 I('4'))
P(5 I('6'))
P(6 I('8'))
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)
P(0 8)
P(1 7)
P(2 1)
P(3 4)
)
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)
P(0 8)
P(1 7)
P(2 2)
P(3 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)
P(0 8)
P(1 7)
P(2 3)
P(3 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(1 I(IN)
R(l3 (-1295 925) (1235 350))
R(l11 (-911 -151) (2 2))
)
N(2
R(l6 (3790 990) (220 220))
R(l6 (-1220 -1520) (220 220))
R(l3 (445 805) (480 550))
R(l6 (-1435 -1665) (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))
R(l7 (780 -2120) (220 220))
R(l8 (-1065 -285) (1105 350))
)
N(3
R(l6 (1405 990) (220 220))
R(l6 (-535 -1520) (220 220))
R(l3 (1345 925) (1945 350))
R(l6 (-2200 -1585) (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))
R(l7 (95 -2120) (220 220))
R(l8 (-295 -370) (440 520))
)
N(4
R(l6 (7090 990) (220 220))
R(l6 (-1220 -1520) (220 220))
R(l3 (3745 805) (480 550))
R(l6 (-1435 -1665) (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))
R(l7 (780 -2120) (220 220))
R(l8 (-1065 -285) (1105 350))
)
N(5
R(l6 (4705 990) (220 220))
R(l6 (-535 -1520) (220 220))
R(l3 (4645 925) (1945 350))
R(l6 (-2200 -1585) (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))
R(l7 (95 -2120) (220 220))
R(l8 (-295 -370) (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))
R(l6 (-1435 -1665) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l7 (780 -2120) (220 220))
R(l8 (-1065 -285) (1105 350))
)
N(12
N(7 I(OUT)
R(l6 (7690 -310) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-220 2180) (220 220))
R(l6 (-220 180) (220 220))
R(l12 (-121 -2011) (2 2))
)
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
N(8 I(VSS)
R(l6 (6890 -310) (220 220))
R(l6 (-220 180) (220 220))
R(l6 (-3520 -620) (220 220))
@ -438,136 +323,96 @@ J(
R(l8 (-6960 -760) (360 760))
R(l8 (-360 -760) (360 760))
R(l8 (2940 -760) (360 760))
R(l13 (2719 -381) (2 2))
R(l13 (-3302 -2) (2 2))
R(l13 (-3302 -2) (2 2))
)
N(9 I(VDD)
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))
R(l13 (-581 -381) (2 2))
R(l13 (3298 -2) (2 2))
R(l13 (-6602 -2) (2 2))
)
P(1 I(IN))
P(7 I(OUT))
P(8 I(VSS))
P(9 I(VDD))
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)
P(0 1)
P(1 2)
P(2 3)
P(3 2)
P(4 3)
P(5 4)
P(6 9)
P(7 8)
)
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)
P(0 5)
P(1 6)
P(2 4)
P(3 5)
P(4 9)
P(5 8)
)
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)
P(0 8)
P(1 9)
P(2 6)
P(3 7)
)
)
)
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)
E(AS 0)
E(AD 0)
E(PS 0)
E(PD 0)
T(S 1)
T(G 3)
T(D 2)
T(B 4)
T(D 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
D(2 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)
E(AS 0)
E(AD 0)
E(PS 0)
E(PD 0)
T(S 2)
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)
T(D 4)
)
)
X(INV3
@ -579,10 +424,6 @@ H(
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'))
@ -591,39 +432,23 @@ H(
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(0 1)
P(1 2)
P(2 3)
P(3 10)
P(4 8)
P(5 6)
P(6 1)
P(7 5)
P(3 4)
)
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)
P(0 1)
P(1 2)
P(2 5)
P(3 6)
)
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)
P(0 1)
P(1 2)
P(2 7)
P(3 8)
)
)
X(INV2
@ -633,125 +458,135 @@ H(
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(0 1)
P(1 2)
P(2 3)
P(3 11)
P(4 9)
P(5 7)
P(6 1)
P(7 5)
P(3 4)
)
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)
P(0 1)
P(1 2)
P(2 5)
P(3 6)
)
)
X(INVCHAIN
N(1 I('9'))
N(2 I('7'))
N(3 I('8'))
N(4 I('6'))
N(1 I('1'))
N(2 I('2'))
N(3 I('3'))
N(4 I('4'))
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'))
N(6 I('6'))
N(7 I('7'))
N(8 I('8'))
N(9 I('9'))
X(1 INV3 I($1)
P(0 1)
P(1 2)
P(2 3)
P(3 4)
P(4 1)
P(4 4)
P(5 5)
P(6 6)
P(7 5)
P(8 7)
P(9 8)
P(10 9)
P(11 10)
P(6 5)
P(7 6)
)
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)
P(0 1)
P(1 2)
P(2 6)
P(3 7)
P(4 7)
P(5 8)
)
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)
P(0 1)
P(1 2)
P(2 8)
P(3 9)
)
)
)
Z(
X(() TRANS 0
X(INV INV 1
Z(
N(2 1 1)
N(1 2 1)
N(3 3 1)
N(4 4 1)
P(1 0 1)
P(0 1 1)
P(2 2 1)
P(3 3 1)
D(2 2 1)
D(1 1 1)
)
)
X(INV INV S
X(INV2 INV2 1
Z(
N(5 1 1)
N(6 2 1)
N(3 3 1)
N(1 4 W)
N(4 5 1)
N(2 6 W)
P(4 0 1)
P(5 1 1)
P(2 2 1)
P(0 3 1)
P(3 4 1)
P(1 5 1)
X(1 1 1)
X(2 2 1)
)
)
X(INV2 INV2 S
X(INV3 INV3 1
Z(
N(7 1 1)
N(8 2 1)
N(1 3 1)
N(4 4 W)
N(2 5 1)
N(5 6 W)
N(3 7 1)
N(6 8 W)
P(6 0 1)
P(7 1 1)
P(0 2 1)
P(3 3 1)
P(1 4 1)
P(4 5 1)
P(2 6 1)
P(5 7 1)
X(1 1 1)
X(2 2 1)
X(3 3 1)
)
)
X(INV3 INV3 S
Z(
)
)
X(INVCHAIN INVCHAIN S
X(INVCHAIN INVCHAIN 1
Z(
N(2 4 1)
N(3 5 1)
N(4 6 1)
N(5 7 1)
N(6 8 1)
N(1 3 1)
N(7 9 1)
N(9 1 1)
N(8 2 1)
P(0 () 1)
P(1 () 1)
P(3 () 1)
P(2 () 1)
X(3 3 1)
X(2 2 1)
X(1 1 1)
)
)
)

View File

@ -1,85 +1,27 @@
* 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
X$1 1 2 3 4 4 5 5 6 INV3
X$2 1 2 6 7 7 8 INV2
X$3 1 2 8 9 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
.SUBCKT INV3 1 2 3 4 5 6 7 8
X$1 1 2 3 4 INV
X$2 1 2 5 6 INV
X$3 1 2 7 8 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
.SUBCKT INV2 1 2 3 4 5 6
X$1 1 2 3 4 INV
X$2 1 2 5 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
.SUBCKT INV 1 2 3 4
M$1 1 3 4 1 PMOS L=0.25U W=0.95U
M$3 2 3 4 2 NMOS L=0.25U W=0.95U
.ENDS INV
* cell TRANS
* pin
* pin
* pin
.SUBCKT TRANS 1 2 3
.ENDS TRANS

Binary file not shown.

View File

@ -170,6 +170,21 @@ class DBNetlist_TestClass < TestBase
c.each_pin { |p| names << p.name }
assert_equal(names, [ "A", "B" ])
assert_equal(c.pin_by_id(0) == nil, false)
assert_equal(c.pin_by_id(1) == nil, false)
assert_equal(c.pin_by_id(0).name, "A")
assert_equal(c.pin_by_id(1).name, "B")
c.remove_pin(0)
names = []
c.each_pin { |p| names << p.name }
assert_equal(names, [ "B" ])
assert_equal(c.pin_by_id(0) == nil, true)
assert_equal(c.pin_by_id(1) == nil, false)
assert_equal(c.pin_by_id(1).name, "B")
end
def test_4_Device