mirror of https://github.com/KLayout/klayout.git
Implemented a fix for issue #1691
The root cause was that the terminal identity could not be derived in the presence of soft connections inside the device abstract cell. The solution is to join soft connected clusters in the device abstracts with a warning.
This commit is contained in:
parent
16ef23864c
commit
bb17250d94
|
|
@ -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