mirror of https://github.com/KLayout/klayout.git
Merge pull request #1692 from KLayout/bugfix/issue-1691
Implemented a fix for issue #1691
This commit is contained in:
commit
fbf52c444a
|
|
@ -1216,11 +1216,13 @@ struct cluster_building_receiver
|
||||||
db::Connectivity::global_nets_iterator ge = mp_conn->end_global_connections (p.first);
|
db::Connectivity::global_nets_iterator ge = mp_conn->end_global_connections (p.first);
|
||||||
for (db::Connectivity::global_nets_iterator g = mp_conn->begin_global_connections (p.first); g != ge; ++g) {
|
for (db::Connectivity::global_nets_iterator g = mp_conn->begin_global_connections (p.first); g != ge; ++g) {
|
||||||
|
|
||||||
|
bool soft = (g->second != 0);
|
||||||
|
|
||||||
typename std::map<size_t, typename std::list<cluster_value>::iterator>::iterator icg = m_global_to_clusters.find (g->first);
|
typename std::map<size_t, typename std::list<cluster_value>::iterator>::iterator icg = m_global_to_clusters.find (g->first);
|
||||||
|
|
||||||
if (icg == m_global_to_clusters.end ()) {
|
if (icg == m_global_to_clusters.end ()) {
|
||||||
|
|
||||||
if (g->second != 0) {
|
if (soft) {
|
||||||
|
|
||||||
// soft connection to a new global cluster
|
// soft connection to a new global cluster
|
||||||
m_clusters.push_back (cluster_value ());
|
m_clusters.push_back (cluster_value ());
|
||||||
|
|
@ -1240,7 +1242,7 @@ struct cluster_building_receiver
|
||||||
|
|
||||||
} else if (ic->second != icg->second) {
|
} else if (ic->second != icg->second) {
|
||||||
|
|
||||||
if (g->second != 0) {
|
if (soft) {
|
||||||
|
|
||||||
register_soft_connection (ic->second, icg->second, g->second);
|
register_soft_connection (ic->second, icg->second, g->second);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -513,6 +513,7 @@ public:
|
||||||
typedef db::box_tree<box_type, local_cluster<T>, local_cluster_box_convert<T> > tree_type;
|
typedef db::box_tree<box_type, local_cluster<T>, local_cluster_box_convert<T> > tree_type;
|
||||||
typedef typename tree_type::touching_iterator touching_iterator;
|
typedef typename tree_type::touching_iterator touching_iterator;
|
||||||
typedef typename tree_type::const_iterator const_iterator;
|
typedef typename tree_type::const_iterator const_iterator;
|
||||||
|
typedef typename tree_type::iterator iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates an empty collection
|
* @brief Creates an empty collection
|
||||||
|
|
@ -566,6 +567,22 @@ public:
|
||||||
return m_clusters.end ();
|
return m_clusters.end ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the clusters (begin iterator)
|
||||||
|
*/
|
||||||
|
iterator begin ()
|
||||||
|
{
|
||||||
|
return m_clusters.begin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the clusters (end iterator)
|
||||||
|
*/
|
||||||
|
iterator end ()
|
||||||
|
{
|
||||||
|
return m_clusters.end ();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets a value indicating whether the cluster set is empty
|
* @brief Gets a value indicating whether the cluster set is empty
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -228,8 +228,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
||||||
|
|
||||||
const db::Cell &cell = mp_layout->cell (*cid);
|
const db::Cell &cell = mp_layout->cell (*cid);
|
||||||
|
|
||||||
const connected_clusters_type &clusters = mp_clusters->clusters_per_cell (*cid);
|
connected_clusters_type &per_cell_clusters = mp_clusters->clusters_per_cell (*cid);
|
||||||
if (clusters.empty ()) {
|
if (per_cell_clusters.empty ()) {
|
||||||
|
|
||||||
bool any_good = false;
|
bool any_good = false;
|
||||||
|
|
||||||
|
|
@ -251,7 +251,7 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
||||||
if (dm) {
|
if (dm) {
|
||||||
// This is a device abstract cell:
|
// This is a device abstract cell:
|
||||||
// make the terminal to cluster ID connections for the device abstract from the device cells
|
// make the terminal to cluster ID connections for the device abstract from the device cells
|
||||||
make_device_abstract_connections (dm, clusters);
|
make_device_abstract_connections (dm, per_cell_clusters);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -284,12 +284,12 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (connected_clusters_type::all_iterator c = clusters.begin_all (); ! c.at_end (); ++c) {
|
for (connected_clusters_type::all_iterator c = per_cell_clusters.begin_all (); ! c.at_end (); ++c) {
|
||||||
|
|
||||||
const db::local_cluster<db::NetShape> &lc = clusters.cluster_by_id (*c);
|
const db::local_cluster<db::NetShape> &lc = per_cell_clusters.cluster_by_id (*c);
|
||||||
const connected_clusters_type::connections_type &cc = clusters.connections_for_cluster (*c);
|
const connected_clusters_type::connections_type &cc = per_cell_clusters.connections_for_cluster (*c);
|
||||||
const std::set<size_t> &sc_up = clusters.upward_soft_connections (*c);
|
const std::set<size_t> &sc_up = per_cell_clusters.upward_soft_connections (*c);
|
||||||
const std::set<size_t> &sc_down = clusters.downward_soft_connections (*c);
|
const std::set<size_t> &sc_down = per_cell_clusters.downward_soft_connections (*c);
|
||||||
if (cc.empty () && sc_up.empty () && sc_down.empty () && lc.empty ()) {
|
if (cc.empty () && sc_up.empty () && sc_down.empty () && lc.empty ()) {
|
||||||
// this is an entirely empty cluster so we skip it.
|
// this is an entirely empty cluster so we skip it.
|
||||||
// Such clusters are left over when joining clusters.
|
// Such clusters are left over when joining clusters.
|
||||||
|
|
@ -301,14 +301,14 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
||||||
circuit->add_net (net);
|
circuit->add_net (net);
|
||||||
|
|
||||||
// make subcircuit connections (also make the subcircuits if required) from the connections of the clusters
|
// make subcircuit connections (also make the subcircuits if required) from the connections of the clusters
|
||||||
make_and_connect_subcircuits (circuit, clusters, *c, net, subcircuits, circuits, pins_per_cluster_per_cell);
|
make_and_connect_subcircuits (circuit, per_cell_clusters, *c, net, subcircuits, circuits, pins_per_cluster_per_cell);
|
||||||
|
|
||||||
// connect devices
|
// connect devices
|
||||||
connect_devices (circuit, clusters, *c, net);
|
connect_devices (circuit, per_cell_clusters, *c, net);
|
||||||
|
|
||||||
// collect labels to net names
|
// collect labels to net names
|
||||||
std::set<std::string> net_names;
|
std::set<std::string> net_names;
|
||||||
collect_labels (clusters, *c, net_names);
|
collect_labels (per_cell_clusters, *c, net_names);
|
||||||
|
|
||||||
// add the global names as second priority
|
// add the global names as second priority
|
||||||
if (net_names.empty ()) {
|
if (net_names.empty ()) {
|
||||||
|
|
@ -323,7 +323,7 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
||||||
// made to satisfy the subcircuit's pin, but not to make a physical connection.
|
// made to satisfy the subcircuit's pin, but not to make a physical connection.
|
||||||
// Don't know whether this is a good idea, so this code is disabled for now.
|
// Don't know whether this is a good idea, so this code is disabled for now.
|
||||||
|
|
||||||
if (net_names.empty () && clusters.is_dummy (*c) && net->subcircuit_pin_count () == 1) {
|
if (net_names.empty () && per_cell_clusters.is_dummy (*c) && net->subcircuit_pin_count () == 1) {
|
||||||
// in the case of a dummy connection (partially connected subcircuits) create a
|
// in the case of a dummy connection (partially connected subcircuits) create a
|
||||||
// new name indicating the subcircuit and the subcircuit net name - this makes subcircuit
|
// new name indicating the subcircuit and the subcircuit net name - this makes subcircuit
|
||||||
// net names available (the net is pseudo-root inside in the subcircuit)
|
// net names available (the net is pseudo-root inside in the subcircuit)
|
||||||
|
|
@ -337,7 +337,7 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
||||||
|
|
||||||
assign_net_names (net, net_names);
|
assign_net_names (net, net_names);
|
||||||
|
|
||||||
if (! clusters.is_root (*c)) {
|
if (! per_cell_clusters.is_root (*c)) {
|
||||||
// a non-root cluster makes a pin
|
// a non-root cluster makes a pin
|
||||||
size_t pin_id = make_pin (circuit, net);
|
size_t pin_id = make_pin (circuit, net);
|
||||||
c2p.insert (std::make_pair (*c, pin_id));
|
c2p.insert (std::make_pair (*c, pin_id));
|
||||||
|
|
@ -364,16 +364,44 @@ NetlistExtractor::assign_net_names (db::Net *net, const std::set<std::string> &n
|
||||||
net->set_name (nn);
|
net->set_name (nn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
collect_soft_connected_clusters (size_t from_id, const NetlistExtractor::connected_clusters_type &clusters, std::set<size_t> &ids)
|
||||||
|
{
|
||||||
|
if (ids.find (from_id) != ids.end ()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ids.insert (from_id);
|
||||||
|
|
||||||
|
auto upward = clusters.upward_soft_connections (from_id);
|
||||||
|
for (auto i = upward.begin (); i != upward.end (); ++i) {
|
||||||
|
collect_soft_connected_clusters (*i, clusters, ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto downward = clusters.downward_soft_connections (from_id);
|
||||||
|
for (auto i = downward.begin (); i != downward.end (); ++i) {
|
||||||
|
collect_soft_connected_clusters (*i, clusters, ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetlistExtractor::make_device_abstract_connections (db::DeviceAbstract *dm, const connected_clusters_type &clusters)
|
NetlistExtractor::make_device_abstract_connections (db::DeviceAbstract *dm, connected_clusters_type &clusters)
|
||||||
{
|
{
|
||||||
// make the terminal to cluster ID connections for the device abstract from the device cells
|
// make the terminal to cluster ID connections for the device abstract from the device cells
|
||||||
|
|
||||||
if (m_terminal_annot_name_id.first) {
|
if (m_terminal_annot_name_id.first) {
|
||||||
|
|
||||||
for (connected_clusters_type::const_iterator dc = clusters.begin (); dc != clusters.end (); ++dc) {
|
for (connected_clusters_type::iterator dc = clusters.begin (); dc != clusters.end (); ++dc) {
|
||||||
|
|
||||||
for (local_cluster_type::attr_iterator a = dc->begin_attr (); a != dc->end_attr (); ++a) {
|
std::set<size_t> ids;
|
||||||
|
collect_soft_connected_clusters (dc->id (), clusters, ids);
|
||||||
|
|
||||||
|
for (auto id = ids.begin (); id != ids.end (); ++id) {
|
||||||
|
|
||||||
|
const local_cluster_type &lc = clusters.cluster_by_id (*id);
|
||||||
|
bool join = false;
|
||||||
|
|
||||||
|
for (local_cluster_type::attr_iterator a = lc.begin_attr (); a != lc.end_attr (); ++a) {
|
||||||
|
|
||||||
if (! db::is_prop_id_attr (*a)) {
|
if (! db::is_prop_id_attr (*a)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -383,9 +411,26 @@ NetlistExtractor::make_device_abstract_connections (db::DeviceAbstract *dm, cons
|
||||||
|
|
||||||
const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (pi);
|
const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (pi);
|
||||||
for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) {
|
for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) {
|
||||||
|
|
||||||
if (j->first == m_terminal_annot_name_id.second) {
|
if (j->first == m_terminal_annot_name_id.second) {
|
||||||
dm->set_cluster_id_for_terminal (j->second.to<size_t> (), dc->id ());
|
|
||||||
|
size_t terminal_id = j->second.to<size_t> ();
|
||||||
|
if (*id != dc->id ()) {
|
||||||
|
tl::warn << tl::sprintf (tl::to_string (tr ("Ignoring soft connection at device terminal %s for device %s")), dm->device_class ()->terminal_definition (terminal_id)->name (), dm->device_class ()->name ());
|
||||||
|
join = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dm->set_cluster_id_for_terminal (terminal_id, dc->id ());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (join) {
|
||||||
|
// copy the terminal attributes and shapes so we attach the terminal here in the device connection step
|
||||||
|
clusters.join_cluster_with (dc->id (), *id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ private:
|
||||||
/**
|
/**
|
||||||
* @brief Makes the terminal to cluster ID connections of the device abstract
|
* @brief Makes the terminal to cluster ID connections of the device abstract
|
||||||
*/
|
*/
|
||||||
void make_device_abstract_connections (db::DeviceAbstract *dm, const connected_clusters_type &clusters);
|
void make_device_abstract_connections (db::DeviceAbstract *dm, connected_clusters_type &clusters);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,8 @@ TEST(40_DeviceExtractorErrors)
|
||||||
TEST(50_BasicSoftConnection)
|
TEST(50_BasicSoftConnection)
|
||||||
{
|
{
|
||||||
run_test (_this, "soft_connect1", "soft_connect1.gds", true, false /*no LVS*/);
|
run_test (_this, "soft_connect1", "soft_connect1.gds", true, false /*no LVS*/);
|
||||||
|
// issue #1691
|
||||||
|
run_test (_this, "soft_connect1a", "soft_connect1.gds", true, false /*no LVS*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No errors
|
// No errors
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
* Extracted by KLayout
|
||||||
|
|
||||||
|
.SUBCKT TOP A Q VDD SUBSTRATE|VSS
|
||||||
|
X$1 SUBSTRATE|VSS VDD VDD \$1 Q SUBSTRATE|VSS INV
|
||||||
|
X$2 SUBSTRATE|VSS VDD VDD A \$1 SUBSTRATE|VSS INV
|
||||||
|
.ENDS TOP
|
||||||
|
|
||||||
|
.SUBCKT INV \$1 \$2 \$3 \$4 \$5 SUBSTRATE
|
||||||
|
M$1 \$2 \$4 \$5 \$3 PMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
|
||||||
|
+ PD=3.45U
|
||||||
|
M$2 \$1 \$4 \$5 SUBSTRATE NMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
|
||||||
|
+ PD=3.45U
|
||||||
|
.ENDS INV
|
||||||
|
|
@ -0,0 +1,218 @@
|
||||||
|
#%l2n-klayout
|
||||||
|
W(TOP)
|
||||||
|
U(0.001)
|
||||||
|
L(l3 '1/0')
|
||||||
|
L(l4 '3/0')
|
||||||
|
L(l15 '3/1')
|
||||||
|
L(l8 '4/0')
|
||||||
|
L(l11 '5/0')
|
||||||
|
L(l12 '6/0')
|
||||||
|
L(l16 '6/1')
|
||||||
|
L(l13 '7/0')
|
||||||
|
L(l14 '8/0')
|
||||||
|
L(l17 '8/1')
|
||||||
|
L(l7)
|
||||||
|
L(l10)
|
||||||
|
L(l2)
|
||||||
|
L(l9)
|
||||||
|
L(l6)
|
||||||
|
C(l3 l3 l10)
|
||||||
|
C(l4 l4 l15 l11)
|
||||||
|
C(l15 l4 l15)
|
||||||
|
C(l8 l8 l12 l10 l2 l9 l6)
|
||||||
|
CS(l8 l10 l2 l9 l6)
|
||||||
|
C(l11 l4 l11 l12)
|
||||||
|
CS(l11 l4)
|
||||||
|
C(l12 l8 l11 l12 l16 l13)
|
||||||
|
C(l16 l12 l16)
|
||||||
|
C(l13 l12 l13 l14)
|
||||||
|
C(l14 l13 l14 l17)
|
||||||
|
C(l17 l14 l17)
|
||||||
|
C(l7 l7)
|
||||||
|
C(l10 l3 l8 l10)
|
||||||
|
CS(l10 l3)
|
||||||
|
C(l2 l8 l2)
|
||||||
|
C(l9 l8 l9)
|
||||||
|
C(l6 l8 l6)
|
||||||
|
G(l7 SUBSTRATE)
|
||||||
|
GS(l7 SUBSTRATE)
|
||||||
|
G(l9 SUBSTRATE)
|
||||||
|
GS(l9 SUBSTRATE)
|
||||||
|
H(W B('Net with incomplete wiring (soft-connected partial nets)') C(TOP) X('soft-connection-check'))
|
||||||
|
H(B('\tPartial net #1: TOP - VDD') C(TOP) Q('(0.6,3.95;0.6,4.85;4.5,4.85;4.5,3.95)'))
|
||||||
|
H(B('\tPartial net #2: TOP - $I4') C(TOP) Q('(5.1,3.95;5.1,4.85;9,4.85;9,3.95)'))
|
||||||
|
H(W B('Net with incomplete wiring (soft-connected partial nets)') C(TOP) X('soft-connection-check'))
|
||||||
|
H(B('\tPartial net #1: TOP - VSS') C(TOP) Q('(0.6,1.15;0.6,2.05;4.5,2.05;4.5,1.15)'))
|
||||||
|
H(B('\tPartial net #2: TOP - $I1') C(TOP) Q('(5.1,1.15;5.1,2.05;9,2.05;9,1.15)'))
|
||||||
|
K(PMOS MOS4)
|
||||||
|
K(NMOS MOS4)
|
||||||
|
D(D$PMOS PMOS
|
||||||
|
T(S
|
||||||
|
R(l2 (-900 -475) (775 950))
|
||||||
|
)
|
||||||
|
T(G
|
||||||
|
R(l4 (-125 -475) (250 950))
|
||||||
|
)
|
||||||
|
T(D
|
||||||
|
R(l2 (125 -475) (775 950))
|
||||||
|
)
|
||||||
|
T(B
|
||||||
|
R(l3 (-125 -475) (250 950))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
D(D$NMOS NMOS
|
||||||
|
T(S
|
||||||
|
R(l6 (-900 -475) (775 950))
|
||||||
|
)
|
||||||
|
T(G
|
||||||
|
R(l4 (-125 -475) (250 950))
|
||||||
|
)
|
||||||
|
T(D
|
||||||
|
R(l6 (125 -475) (775 950))
|
||||||
|
)
|
||||||
|
T(B
|
||||||
|
R(l7 (-125 -475) (250 950))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
X(INV
|
||||||
|
R((-1500 -800) (3000 4600))
|
||||||
|
N(1
|
||||||
|
R(l8 (290 -310) (220 220))
|
||||||
|
R(l8 (-220 180) (220 220))
|
||||||
|
R(l12 (-290 -690) (360 760))
|
||||||
|
R(l13 (-305 -705) (250 250))
|
||||||
|
R(l13 (-250 150) (250 250))
|
||||||
|
R(l14 (-2025 -775) (3000 900))
|
||||||
|
R(l6 (-1375 -925) (775 950))
|
||||||
|
)
|
||||||
|
N(2
|
||||||
|
R(l8 (290 2490) (220 220))
|
||||||
|
R(l8 (-220 180) (220 220))
|
||||||
|
R(l12 (-290 -690) (360 760))
|
||||||
|
R(l13 (-305 -705) (250 250))
|
||||||
|
R(l13 (-250 150) (250 250))
|
||||||
|
R(l14 (-2025 -775) (3000 900))
|
||||||
|
R(l2 (-1375 -925) (775 950))
|
||||||
|
)
|
||||||
|
N(3
|
||||||
|
R(l3 (-1500 1800) (3000 2000))
|
||||||
|
)
|
||||||
|
N(4
|
||||||
|
R(l4 (-125 -250) (250 2500))
|
||||||
|
R(l4 (-250 -3050) (250 1600))
|
||||||
|
R(l4 (-250 1200) (250 1600))
|
||||||
|
)
|
||||||
|
N(5
|
||||||
|
R(l8 (-510 -310) (220 220))
|
||||||
|
R(l8 (-220 180) (220 220))
|
||||||
|
R(l8 (-220 2180) (220 220))
|
||||||
|
R(l8 (-220 180) (220 220))
|
||||||
|
R(l12 (-290 -3530) (360 2840))
|
||||||
|
R(l12 (-360 -2800) (360 760))
|
||||||
|
R(l12 (-360 2040) (360 760))
|
||||||
|
R(l2 (-680 -855) (775 950))
|
||||||
|
R(l6 (-775 -3750) (775 950))
|
||||||
|
)
|
||||||
|
N(6 I(SUBSTRATE))
|
||||||
|
P(1)
|
||||||
|
P(2)
|
||||||
|
P(3)
|
||||||
|
P(4)
|
||||||
|
P(5)
|
||||||
|
P(6 I(SUBSTRATE))
|
||||||
|
D(1 D$PMOS
|
||||||
|
Y(0 2800)
|
||||||
|
E(L 0.25)
|
||||||
|
E(W 0.95)
|
||||||
|
E(AS 0.73625)
|
||||||
|
E(AD 0.73625)
|
||||||
|
E(PS 3.45)
|
||||||
|
E(PD 3.45)
|
||||||
|
T(S 5)
|
||||||
|
T(G 4)
|
||||||
|
T(D 2)
|
||||||
|
T(B 3)
|
||||||
|
)
|
||||||
|
D(2 D$NMOS
|
||||||
|
Y(0 0)
|
||||||
|
E(L 0.25)
|
||||||
|
E(W 0.95)
|
||||||
|
E(AS 0.73625)
|
||||||
|
E(AD 0.73625)
|
||||||
|
E(PS 3.45)
|
||||||
|
E(PD 3.45)
|
||||||
|
T(S 5)
|
||||||
|
T(G 4)
|
||||||
|
T(D 1)
|
||||||
|
T(B 6)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
X(TOP
|
||||||
|
R((600 800) (8880 4600))
|
||||||
|
N(1
|
||||||
|
R(l4 (2920 2600) (2880 400))
|
||||||
|
R(l11 (-300 -300) (200 200))
|
||||||
|
R(l12 (-300 -300) (690 400))
|
||||||
|
)
|
||||||
|
N(2 I(A)
|
||||||
|
R(l4 (6600 2600) (2880 400))
|
||||||
|
R(l15 (-2380 -200) (0 0))
|
||||||
|
)
|
||||||
|
N(3 I(Q)
|
||||||
|
R(l12 (1810 2600) (690 400))
|
||||||
|
R(l16 (-400 -200) (0 0))
|
||||||
|
)
|
||||||
|
N(4 I(VDD)
|
||||||
|
R(l3 (4000 3400) (1600 2000))
|
||||||
|
R(l3 (-5000 -2000) (1000 2000))
|
||||||
|
R(l3 (6400 -2000) (1000 2000))
|
||||||
|
R(l8 (-8000 -900) (200 200))
|
||||||
|
R(l8 (-200 -600) (200 200))
|
||||||
|
R(l8 (7200 200) (200 200))
|
||||||
|
R(l8 (-200 -600) (200 200))
|
||||||
|
R(l12 (-7900 -350) (800 900))
|
||||||
|
R(l12 (6600 -900) (800 900))
|
||||||
|
R(l13 (-7900 -350) (200 200))
|
||||||
|
R(l13 (-200 -600) (200 200))
|
||||||
|
R(l13 (7200 200) (200 200))
|
||||||
|
R(l13 (-200 -600) (200 200))
|
||||||
|
R(l14 (-8000 -350) (1000 900))
|
||||||
|
R(l14 (6400 -900) (1000 900))
|
||||||
|
R(l17 (-4800 -450) (0 0))
|
||||||
|
)
|
||||||
|
N(5 I('SUBSTRATE,VSS')
|
||||||
|
R(l8 (1000 1700) (200 200))
|
||||||
|
R(l8 (-200 -600) (200 200))
|
||||||
|
R(l8 (7200 200) (200 200))
|
||||||
|
R(l8 (-200 -600) (200 200))
|
||||||
|
R(l12 (-7900 -350) (800 900))
|
||||||
|
R(l12 (6600 -900) (800 900))
|
||||||
|
R(l13 (-7900 -350) (200 200))
|
||||||
|
R(l13 (-200 -600) (200 200))
|
||||||
|
R(l13 (7200 200) (200 200))
|
||||||
|
R(l13 (-200 -600) (200 200))
|
||||||
|
R(l14 (-8000 -350) (1000 900))
|
||||||
|
R(l14 (6400 -900) (1000 900))
|
||||||
|
R(l17 (-4800 -550) (0 0))
|
||||||
|
)
|
||||||
|
P(2 I(A))
|
||||||
|
P(3 I(Q))
|
||||||
|
P(4 I(VDD))
|
||||||
|
P(5 I('SUBSTRATE,VSS'))
|
||||||
|
X(1 INV Y(3000 1600)
|
||||||
|
P(0 5)
|
||||||
|
P(1 4)
|
||||||
|
P(2 4)
|
||||||
|
P(3 1)
|
||||||
|
P(4 3)
|
||||||
|
P(5 5)
|
||||||
|
)
|
||||||
|
X(2 INV Y(6600 1600)
|
||||||
|
P(0 5)
|
||||||
|
P(1 4)
|
||||||
|
P(2 4)
|
||||||
|
P(3 2)
|
||||||
|
P(4 1)
|
||||||
|
P(5 5)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
|
||||||
|
$lvs_test_source && source($lvs_test_source)
|
||||||
|
|
||||||
|
if $lvs_test_target_l2n
|
||||||
|
report_netlist($lvs_test_target_l2n)
|
||||||
|
else
|
||||||
|
report_netlist
|
||||||
|
end
|
||||||
|
|
||||||
|
writer = write_spice(true, false)
|
||||||
|
$lvs_test_target_cir && target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
|
||||||
|
|
||||||
|
deep
|
||||||
|
|
||||||
|
# Drawing layers
|
||||||
|
|
||||||
|
nwell = input(1, 0)
|
||||||
|
active = input(2, 0)
|
||||||
|
nplus = input(2, 1)
|
||||||
|
pplus = input(2, 2)
|
||||||
|
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
|
||||||
|
|
||||||
|
psd = nil
|
||||||
|
nsd = nil
|
||||||
|
|
||||||
|
# Computed layers
|
||||||
|
|
||||||
|
active_in_nwell = active & nwell
|
||||||
|
pactive = active_in_nwell & pplus
|
||||||
|
ntie = active_in_nwell & nplus
|
||||||
|
pgate = pactive & poly
|
||||||
|
psd = pactive - pgate
|
||||||
|
|
||||||
|
active_outside_nwell = active - nwell
|
||||||
|
nactive = active_outside_nwell & nplus
|
||||||
|
ptie = active_outside_nwell & pplus
|
||||||
|
ngate = nactive & poly
|
||||||
|
nsd = nactive - ngate
|
||||||
|
|
||||||
|
# Device extraction
|
||||||
|
|
||||||
|
# PMOS transistor device extraction
|
||||||
|
extract_devices(mos4("PMOS"), { "SD" => psd, "G" => pgate, "W" => nwell,
|
||||||
|
"tS" => psd, "tD" => psd, "tG" => poly })
|
||||||
|
|
||||||
|
# NMOS transistor device extraction
|
||||||
|
extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk,
|
||||||
|
"tS" => nsd, "tD" => nsd, "tG" => poly })
|
||||||
|
|
||||||
|
# Define connectivity for netlist extraction
|
||||||
|
|
||||||
|
# Inter-layer
|
||||||
|
|
||||||
|
soft_connect(diff_cont, psd)
|
||||||
|
soft_connect(diff_cont, nsd)
|
||||||
|
soft_connect(diff_cont, ptie)
|
||||||
|
soft_connect(diff_cont, ntie)
|
||||||
|
soft_connect(ntie, nwell)
|
||||||
|
soft_connect(poly_cont, poly)
|
||||||
|
|
||||||
|
connect(diff_cont, metal1)
|
||||||
|
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
|
||||||
|
soft_connect_global(bulk, "SUBSTRATE")
|
||||||
|
soft_connect_global(ptie, "SUBSTRATE")
|
||||||
|
|
||||||
|
# Netlist section (NOTE: we only check log here)
|
||||||
|
netlist
|
||||||
|
|
||||||
|
netlist.simplify
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue