mirror of https://github.com/KLayout/klayout.git
Merge pull request #2352 from KLayout/bugfix/issue-2345
A contribution to issue #2345 mitigation
This commit is contained in:
commit
10860d5a68
|
|
@ -103,6 +103,13 @@ EdgePairs::EdgePairs (DeepShapeStore &dss)
|
||||||
mp_delegate = new DeepEdgePairs (DeepLayer (&dss, layout_index, dss.layout (layout_index).insert_layer ()));
|
mp_delegate = new DeepEdgePairs (DeepLayer (&dss, layout_index, dss.layout (layout_index).insert_layer ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EdgePairs::convert_to_deep (const db::DeepLayer &layer)
|
||||||
|
{
|
||||||
|
tl_assert (mp_delegate->deep () == 0);
|
||||||
|
set_delegate (copy_data_id (new db::DeepEdgePairs (layer)));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EdgePairs::write (const std::string &fn) const
|
EdgePairs::write (const std::string &fn) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,11 @@ public:
|
||||||
*/
|
*/
|
||||||
explicit EdgePairs (DeepShapeStore &dss);
|
explicit EdgePairs (DeepShapeStore &dss);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts the shape collection to a deep one using the specified layer
|
||||||
|
*/
|
||||||
|
virtual void convert_to_deep (const db::DeepLayer &layer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes the edge pair collection to a file
|
* @brief Writes the edge pair collection to a file
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,13 @@ Edges::Edges (DeepShapeStore &dss)
|
||||||
mp_delegate = new DeepEdges (DeepLayer (&dss, layout_index, dss.layout (layout_index).insert_layer ()));
|
mp_delegate = new DeepEdges (DeepLayer (&dss, layout_index, dss.layout (layout_index).insert_layer ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Edges::convert_to_deep (const db::DeepLayer &layer)
|
||||||
|
{
|
||||||
|
tl_assert (mp_delegate->deep () == 0);
|
||||||
|
set_delegate (copy_data_id (new db::DeepEdges (layer)));
|
||||||
|
}
|
||||||
|
|
||||||
const db::RecursiveShapeIterator &
|
const db::RecursiveShapeIterator &
|
||||||
Edges::iter () const
|
Edges::iter () const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,11 @@ public:
|
||||||
*/
|
*/
|
||||||
explicit Edges (DeepShapeStore &dss);
|
explicit Edges (DeepShapeStore &dss);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts the shape collection to a deep one using the specified layer
|
||||||
|
*/
|
||||||
|
virtual void convert_to_deep (const db::DeepLayer &layer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implementation of the ShapeCollection interface
|
* @brief Implementation of the ShapeCollection interface
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -130,8 +130,10 @@ void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, unsigned int layo
|
||||||
|
|
||||||
std::pair<bool, db::DeepLayer> alias = dss.layer_for_flat (tl::id_of (l->second->get_delegate ()));
|
std::pair<bool, db::DeepLayer> alias = dss.layer_for_flat (tl::id_of (l->second->get_delegate ()));
|
||||||
if (alias.first) {
|
if (alias.first) {
|
||||||
// use deep layer alias for a given flat one (if found)
|
// use deep layer alias for a given flat one (if found) and convert layer to a deep one
|
||||||
layers.push_back (alias.second.layer ());
|
db::DeepLayer dl = alias.second;
|
||||||
|
l->second->convert_to_deep (dl);
|
||||||
|
layers.push_back (dl.layer ());
|
||||||
} else {
|
} else {
|
||||||
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Invalid region passed to input layer '%s' for device extraction (device %s): must be of deep region kind")), ld->name, name ()));
|
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Invalid region passed to input layer '%s' for device extraction (device %s): must be of deep region kind")), ld->name, name ()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,13 @@ Region::Region (DeepShapeStore &dss)
|
||||||
mp_delegate = new db::DeepRegion (db::DeepLayer (&dss, layout_index, dss.layout (layout_index).insert_layer ()));
|
mp_delegate = new db::DeepRegion (db::DeepLayer (&dss, layout_index, dss.layout (layout_index).insert_layer ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Region::convert_to_deep (const db::DeepLayer &layer)
|
||||||
|
{
|
||||||
|
tl_assert (mp_delegate->deep () == 0);
|
||||||
|
set_delegate (copy_data_id (new db::DeepRegion (layer)));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Region::write (const std::string &fn) const
|
Region::write (const std::string &fn) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void write (const std::string &fn) const;
|
void write (const std::string &fn) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts the shape collection to a deep one using the specified layer
|
||||||
|
*/
|
||||||
|
virtual void convert_to_deep (const db::DeepLayer &layer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implementation of the ShapeCollection interface
|
* @brief Implementation of the ShapeCollection interface
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,12 @@ class DB_PUBLIC ShapeCollectionDelegateBase
|
||||||
: public tl::UniqueId
|
: public tl::UniqueId
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ShapeCollectionDelegateBase () { }
|
ShapeCollectionDelegateBase ()
|
||||||
|
: m_data_id (tl::id_of (this))
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~ShapeCollectionDelegateBase () { }
|
virtual ~ShapeCollectionDelegateBase () { }
|
||||||
|
|
||||||
virtual DeepShapeCollectionDelegateBase *deep () { return 0; }
|
virtual DeepShapeCollectionDelegateBase *deep () { return 0; }
|
||||||
|
|
@ -88,6 +93,22 @@ public:
|
||||||
apply_property_translator (db::PropertiesTranslator::make_remove_all ());
|
apply_property_translator (db::PropertiesTranslator::make_remove_all ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tl::id_type data_id () const
|
||||||
|
{
|
||||||
|
return m_data_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ShapeCollection;
|
||||||
|
|
||||||
|
tl::id_type m_data_id;
|
||||||
|
|
||||||
|
// used for conversion to deep
|
||||||
|
void set_data_id (tl::id_type data_id)
|
||||||
|
{
|
||||||
|
m_data_id = data_id;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -102,6 +123,11 @@ public:
|
||||||
|
|
||||||
virtual ShapeCollectionDelegateBase *get_delegate () const = 0;
|
virtual ShapeCollectionDelegateBase *get_delegate () const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts the shape collection to a deep one using the specified layer
|
||||||
|
*/
|
||||||
|
virtual void convert_to_deep (const db::DeepLayer &layer) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Applies a PropertyTranslator
|
* @brief Applies a PropertyTranslator
|
||||||
*
|
*
|
||||||
|
|
@ -111,6 +137,14 @@ public:
|
||||||
* delivered by "properties_repository".
|
* delivered by "properties_repository".
|
||||||
*/
|
*/
|
||||||
void apply_property_translator (const db::PropertiesTranslator &pt);
|
void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
template <class Delegate>
|
||||||
|
Delegate *copy_data_id (Delegate *dlg)
|
||||||
|
{
|
||||||
|
dlg->set_data_id (get_delegate ()->data_id ());
|
||||||
|
return dlg;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,13 @@ Texts::Texts (DeepShapeStore &dss)
|
||||||
mp_delegate = new DeepTexts (DeepLayer (&dss, layout_index, dss.layout (layout_index).insert_layer ()));
|
mp_delegate = new DeepTexts (DeepLayer (&dss, layout_index, dss.layout (layout_index).insert_layer ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Texts::convert_to_deep (const db::DeepLayer &layer)
|
||||||
|
{
|
||||||
|
tl_assert (mp_delegate->deep () == 0);
|
||||||
|
set_delegate (copy_data_id (new db::DeepTexts (layer)));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Texts::write (const std::string &fn) const
|
Texts::write (const std::string &fn) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void write (const std::string &fn) const;
|
void write (const std::string &fn) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts the shape collection to a deep one using the specified layer
|
||||||
|
*/
|
||||||
|
virtual void convert_to_deep (const db::DeepLayer &layer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implementation of the ShapeCollection interface
|
* @brief Implementation of the ShapeCollection interface
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -630,9 +630,9 @@ static bool is_deep (const db::EdgePairs *ep)
|
||||||
return dynamic_cast<const db::DeepEdgePairs *> (ep->delegate ()) != 0;
|
return dynamic_cast<const db::DeepEdgePairs *> (ep->delegate ()) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t id (const db::EdgePairs *ep)
|
static size_t data_id (const db::EdgePairs *ep)
|
||||||
{
|
{
|
||||||
return tl::id_of (ep->delegate ());
|
return ep->delegate ()->data_id ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::EdgePairs filtered (const db::EdgePairs *r, const gsi::EdgePairFilterBase *f)
|
static db::EdgePairs filtered (const db::EdgePairs *r, const gsi::EdgePairFilterBase *f)
|
||||||
|
|
@ -1114,7 +1114,7 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been added in version 0.26."
|
"This method has been added in version 0.26."
|
||||||
) +
|
) +
|
||||||
method_ext ("data_id", &id,
|
method_ext ("data_id", &data_id,
|
||||||
"@brief Returns the data ID (a unique identifier for the underlying data storage)\n"
|
"@brief Returns the data ID (a unique identifier for the underlying data storage)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been added in version 0.26."
|
"This method has been added in version 0.26."
|
||||||
|
|
|
||||||
|
|
@ -892,9 +892,9 @@ static db::Edges *new_texts_as_dots2 (const db::RecursiveShapeIterator &si, db::
|
||||||
return new db::Edges (db::Region (si).texts_as_dots (pat, pattern, dss));
|
return new db::Edges (db::Region (si).texts_as_dots (pat, pattern, dss));
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t id (const db::Edges *e)
|
static size_t data_id (const db::Edges *e)
|
||||||
{
|
{
|
||||||
return tl::id_of (e->delegate ());
|
return e->delegate ()->data_id ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<db::Edges> andnot_with_edges (const db::Edges *r, const db::Edges &other)
|
static std::vector<db::Edges> andnot_with_edges (const db::Edges *r, const db::Edges &other)
|
||||||
|
|
@ -2572,7 +2572,7 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been added in version 0.26."
|
"This method has been added in version 0.26."
|
||||||
) +
|
) +
|
||||||
method_ext ("data_id", &id,
|
method_ext ("data_id", &data_id,
|
||||||
"@brief Returns the data ID (a unique identifier for the underlying data storage)\n"
|
"@brief Returns the data ID (a unique identifier for the underlying data storage)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been added in version 0.26."
|
"This method has been added in version 0.26."
|
||||||
|
|
|
||||||
|
|
@ -1288,9 +1288,9 @@ static bool is_deep (const db::Region *region)
|
||||||
return dynamic_cast<const db::DeepRegion *> (region->delegate ()) != 0;
|
return dynamic_cast<const db::DeepRegion *> (region->delegate ()) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t id (const db::Region *r)
|
static size_t data_id (const db::Region *r)
|
||||||
{
|
{
|
||||||
return tl::id_of (r->delegate ());
|
return r->delegate ()->data_id ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4214,7 +4214,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been added in version 0.26."
|
"This method has been added in version 0.26."
|
||||||
) +
|
) +
|
||||||
method_ext ("data_id", &id,
|
method_ext ("data_id", &data_id,
|
||||||
"@brief Returns the data ID (a unique identifier for the underlying data storage)\n"
|
"@brief Returns the data ID (a unique identifier for the underlying data storage)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been added in version 0.26."
|
"This method has been added in version 0.26."
|
||||||
|
|
|
||||||
|
|
@ -477,9 +477,9 @@ static bool is_deep (const db::Texts *t)
|
||||||
return dynamic_cast<const db::DeepTexts *> (t->delegate ()) != 0;
|
return dynamic_cast<const db::DeepTexts *> (t->delegate ()) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t id (const db::Texts *t)
|
static size_t data_id (const db::Texts *t)
|
||||||
{
|
{
|
||||||
return tl::id_of (t->delegate ());
|
return t->delegate ()->data_id ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::Texts filtered (const db::Texts *r, const gsi::TextFilterBase *f)
|
static db::Texts filtered (const db::Texts *r, const gsi::TextFilterBase *f)
|
||||||
|
|
@ -686,7 +686,7 @@ Class<db::Texts> decl_Texts (decl_dbShapeCollection, "db", "Texts",
|
||||||
method_ext ("is_deep?", &is_deep,
|
method_ext ("is_deep?", &is_deep,
|
||||||
"@brief Returns true if the edge pair collection is a deep (hierarchical) one\n"
|
"@brief Returns true if the edge pair collection is a deep (hierarchical) one\n"
|
||||||
) +
|
) +
|
||||||
method_ext ("data_id", &id,
|
method_ext ("data_id", &data_id,
|
||||||
"@brief Returns the data ID (a unique identifier for the underlying data storage)\n"
|
"@brief Returns the data ID (a unique identifier for the underlying data storage)\n"
|
||||||
) +
|
) +
|
||||||
method ("+|join", &db::Texts::operator+, gsi::arg ("other"),
|
method ("+|join", &db::Texts::operator+, gsi::arg ("other"),
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,9 @@ module DRC
|
||||||
#
|
#
|
||||||
# If layers are not named, they will be given a name made from the
|
# If layers are not named, they will be given a name made from the
|
||||||
# \name_prefix and an incremental number when the layer is used for the
|
# \name_prefix and an incremental number when the layer is used for the
|
||||||
# first time.
|
# first time. As the default name prefix is "l", you may can name conflicts
|
||||||
|
# with auto-named layers, if you register explicit layer names like "l5".
|
||||||
|
# Consider changing the name prefix in that case to some prefix you are not using.
|
||||||
#
|
#
|
||||||
# \name can only be used once on a layer and the layer names must be
|
# \name can only be used once on a layer and the layer names must be
|
||||||
# unique (not taken by another layer).
|
# unique (not taken by another layer).
|
||||||
|
|
|
||||||
|
|
@ -362,3 +362,9 @@ TEST(63_FlagMissingPorts)
|
||||||
run_test (_this, "flag_missing_ports", "flag_missing_ports.gds", false, true, "TOP");
|
run_test (_this, "flag_missing_ports", "flag_missing_ports.gds", false, true, "TOP");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Split substrate - marker and global connection (issue #2345)
|
||||||
|
TEST(64_SplitSubstrate)
|
||||||
|
{
|
||||||
|
run_test (_this, "split_substrate", "split_substrate.gds", true, false /*no LVS*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,13 @@
|
||||||
|
* Extracted by KLayout
|
||||||
|
|
||||||
|
.SUBCKT TOP A Q IOSUB SUBSTRATE
|
||||||
|
X$1 \$7 \$1 Q IOSUB IOSUB INV
|
||||||
|
X$2 \$7 A \$1 SUBSTRATE SUBSTRATE INV
|
||||||
|
.ENDS TOP
|
||||||
|
|
||||||
|
.SUBCKT INV \$2 \$4 \$5 \$1 \$I11
|
||||||
|
M$1 \$2 \$4 \$5 \$2 PMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
|
||||||
|
+ PD=3.45U
|
||||||
|
M$2 \$1 \$4 \$5 \$I11 NMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
|
||||||
|
+ PD=3.45U
|
||||||
|
.ENDS INV
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,215 @@
|
||||||
|
#%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)
|
||||||
|
L(l22 '10/0')
|
||||||
|
L(l7)
|
||||||
|
L(l10)
|
||||||
|
L(l2)
|
||||||
|
L(l9)
|
||||||
|
L(l6)
|
||||||
|
L(l21)
|
||||||
|
L(l18)
|
||||||
|
L(l20)
|
||||||
|
L(l19)
|
||||||
|
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(l22 l22 l21 l20)
|
||||||
|
C(l7 l7 l18 l20)
|
||||||
|
C(l10 l3 l8 l10)
|
||||||
|
CS(l10 l3)
|
||||||
|
C(l2 l8 l2)
|
||||||
|
C(l9 l8 l9 l21 l19)
|
||||||
|
C(l6 l8 l6)
|
||||||
|
C(l21 l22 l9 l21)
|
||||||
|
CS(l21 l22)
|
||||||
|
C(l18 l7 l18)
|
||||||
|
C(l20 l22 l7 l20)
|
||||||
|
C(l19 l9 l19)
|
||||||
|
G(l22 IOSUB)
|
||||||
|
G(l18 SUBSTRATE)
|
||||||
|
G(l19 SUBSTRATE)
|
||||||
|
GS(l19 SUBSTRATE)
|
||||||
|
H(W B('Net with incomplete wiring (soft-connected partial nets)') C(TOP) X('soft-connection-check'))
|
||||||
|
H(B('\tPartial net #1: TOP/INV[r0 3,1.6]:$1 - $2') C(TOP) Q('(1.5,3.95;1.5,4.85;5.3,4.85;5.3,3.95)'))
|
||||||
|
H(B('\tPartial net #2: TOP/INV[r0 7.7,1.6]:$2 - $2') C(TOP) Q('(6.2,3.95;6.2,4.85;10,4.85;10,3.95)'))
|
||||||
|
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) (3800 4600))
|
||||||
|
N(1 I($1)
|
||||||
|
R(l8 (1700 100) (200 200))
|
||||||
|
R(l8 (-200 -600) (200 200))
|
||||||
|
R(l8 (-1610 -210) (220 220))
|
||||||
|
R(l8 (-220 180) (220 220))
|
||||||
|
R(l12 (890 -760) (800 900))
|
||||||
|
R(l12 (-1980 -830) (360 760))
|
||||||
|
R(l13 (-305 -705) (250 250))
|
||||||
|
R(l13 (-250 150) (250 250))
|
||||||
|
R(l13 (1175 -225) (200 200))
|
||||||
|
R(l13 (-200 -600) (200 200))
|
||||||
|
R(l14 (-3400 -350) (3000 900))
|
||||||
|
R(l14 (-200 -900) (1000 900))
|
||||||
|
R(l9 (-700 -950) (400 1000))
|
||||||
|
R(l6 (-1875 -975) (775 950))
|
||||||
|
)
|
||||||
|
N(2 I($2)
|
||||||
|
R(l3 (-1500 1800) (3000 2000))
|
||||||
|
R(l3 (-200 -2000) (1000 2000))
|
||||||
|
R(l8 (-2010 -1310) (220 220))
|
||||||
|
R(l8 (-220 180) (220 220))
|
||||||
|
R(l8 (1190 -210) (200 200))
|
||||||
|
R(l8 (-200 -600) (200 200))
|
||||||
|
R(l12 (-1680 -280) (360 760))
|
||||||
|
R(l12 (820 -830) (800 900))
|
||||||
|
R(l13 (-1925 -775) (250 250))
|
||||||
|
R(l13 (-250 150) (250 250))
|
||||||
|
R(l13 (1175 -225) (200 200))
|
||||||
|
R(l13 (-200 -600) (200 200))
|
||||||
|
R(l14 (-3400 -350) (3000 900))
|
||||||
|
R(l14 (-200 -900) (1000 900))
|
||||||
|
R(l10 (-700 -950) (400 1000))
|
||||||
|
R(l2 (-1875 -975) (775 950))
|
||||||
|
)
|
||||||
|
N(3 I($4)
|
||||||
|
R(l4 (-125 -250) (250 2500))
|
||||||
|
R(l4 (-250 -3050) (250 1600))
|
||||||
|
R(l4 (-250 1200) (250 1600))
|
||||||
|
)
|
||||||
|
N(4 I($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(5 I($I11))
|
||||||
|
P(2)
|
||||||
|
P(3)
|
||||||
|
P(4)
|
||||||
|
P(1)
|
||||||
|
P(5)
|
||||||
|
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 4)
|
||||||
|
T(G 3)
|
||||||
|
T(D 2)
|
||||||
|
T(B 2)
|
||||||
|
)
|
||||||
|
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 4)
|
||||||
|
T(G 3)
|
||||||
|
T(D 1)
|
||||||
|
T(B 5)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
X(TOP
|
||||||
|
R((1334 621) (9246 5073))
|
||||||
|
N(1 I($1)
|
||||||
|
R(l4 (2920 2600) (3980 400))
|
||||||
|
R(l11 (-300 -300) (200 200))
|
||||||
|
R(l12 (-300 -300) (690 400))
|
||||||
|
)
|
||||||
|
N(2 I(A)
|
||||||
|
R(l4 (7700 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(IOSUB)
|
||||||
|
R(l22 (1334 621) (4230 5073))
|
||||||
|
R(l21 (-964 -4594) (400 1000))
|
||||||
|
R(l20 (-2125 -975) (250 950))
|
||||||
|
)
|
||||||
|
N(5 I($7)
|
||||||
|
R(l3 (4000 3400) (2700 2000))
|
||||||
|
)
|
||||||
|
N(6 I(SUBSTRATE)
|
||||||
|
R(l18 (7575 1125) (250 950))
|
||||||
|
R(l19 (1475 -975) (400 1000))
|
||||||
|
)
|
||||||
|
P(2 I(A))
|
||||||
|
P(3 I(Q))
|
||||||
|
P(4 I(IOSUB))
|
||||||
|
P(6 I(SUBSTRATE))
|
||||||
|
X(1 INV Y(3000 1600)
|
||||||
|
P(0 5)
|
||||||
|
P(1 1)
|
||||||
|
P(2 3)
|
||||||
|
P(3 4)
|
||||||
|
P(4 4)
|
||||||
|
)
|
||||||
|
X(2 INV Y(7700 1600)
|
||||||
|
P(0 5)
|
||||||
|
P(1 2)
|
||||||
|
P(2 1)
|
||||||
|
P(3 6)
|
||||||
|
P(4 6)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
|
||||||
|
$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)
|
||||||
|
iosub = input(10, 0)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# Split bulk and ptie into inside and outside iosub
|
||||||
|
(bulk_io, bulk_reg) = bulk.andnot(iosub)
|
||||||
|
(ptie_io, ptie_reg) = ptie.andnot(iosub)
|
||||||
|
|
||||||
|
# connect outside to "SUBSTRATE" globally
|
||||||
|
connect(bulk, bulk_reg)
|
||||||
|
connect(ptie, ptie_reg)
|
||||||
|
connect_global(bulk_reg, "SUBSTRATE")
|
||||||
|
soft_connect_global(ptie_reg, "SUBSTRATE")
|
||||||
|
|
||||||
|
# connect inside to "IOSUB" via polygons
|
||||||
|
connect(bulk, bulk_io)
|
||||||
|
connect(ptie, ptie_io)
|
||||||
|
connect(bulk_io, iosub)
|
||||||
|
soft_connect(ptie_io, iosub)
|
||||||
|
connect_global(iosub, "IOSUB")
|
||||||
|
|
||||||
|
# Netlist section (NOTE: we only check log here)
|
||||||
|
# for debugging: _make_soft_connection_diodes(true)
|
||||||
|
netlist
|
||||||
|
|
||||||
|
netlist.simplify
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue