mirror of https://github.com/KLayout/klayout.git
A contribution to issue #2345 mitigation
With this patch, empty layers can be used to place device terminals on and these shapes are visible on those layers. This allows splitting the terminal shapes and used those shapes to connect down to different substrates. The patch turns EmptyLayer into a DeepLayer when used as terminal layer for device extraction.
This commit is contained in:
parent
5ccf6260f1
commit
9630bff240
|
|
@ -103,6 +103,13 @@ EdgePairs::EdgePairs (DeepShapeStore &dss)
|
|||
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 (new db::DeepEdgePairs (layer));
|
||||
}
|
||||
|
||||
void
|
||||
EdgePairs::write (const std::string &fn) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -204,6 +204,11 @@ public:
|
|||
*/
|
||||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -114,6 +114,13 @@ Edges::Edges (DeepShapeStore &dss)
|
|||
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 (new db::DeepEdges (layer));
|
||||
}
|
||||
|
||||
const db::RecursiveShapeIterator &
|
||||
Edges::iter () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -264,6 +264,11 @@ public:
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 ()));
|
||||
if (alias.first) {
|
||||
// use deep layer alias for a given flat one (if found)
|
||||
layers.push_back (alias.second.layer ());
|
||||
// use deep layer alias for a given flat one (if found) and convert layer to a deep one
|
||||
db::DeepLayer dl = alias.second;
|
||||
l->second->convert_to_deep (dl);
|
||||
layers.push_back (dl.layer ());
|
||||
} 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 ()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,13 @@ Region::Region (DeepShapeStore &dss)
|
|||
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 (new db::DeepRegion (layer));
|
||||
}
|
||||
|
||||
void
|
||||
Region::write (const std::string &fn) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -256,6 +256,11 @@ public:
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -102,6 +102,11 @@ public:
|
|||
|
||||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -99,6 +99,13 @@ Texts::Texts (DeepShapeStore &dss)
|
|||
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 (new db::DeepTexts (layer));
|
||||
}
|
||||
|
||||
void
|
||||
Texts::write (const std::string &fn) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -208,6 +208,11 @@ public:
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -362,3 +362,9 @@ TEST(63_FlagMissingPorts)
|
|||
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*/);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(l23 '10/0')
|
||||
L(l18)
|
||||
L(l10)
|
||||
L(l2)
|
||||
L(l9)
|
||||
L(l6)
|
||||
L(l22)
|
||||
L(l19)
|
||||
L(l21)
|
||||
L(l20)
|
||||
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(l23 l23 l22 l21)
|
||||
C(l18 l18 l19 l21)
|
||||
C(l10 l3 l8 l10)
|
||||
CS(l10 l3)
|
||||
C(l2 l8 l2)
|
||||
C(l9 l8 l9 l22 l20)
|
||||
C(l6 l8 l6)
|
||||
C(l22 l23 l9 l22)
|
||||
CS(l22 l23)
|
||||
C(l19 l18 l19)
|
||||
C(l21 l23 l18 l21)
|
||||
C(l20 l9 l20)
|
||||
G(l23 IOSUB)
|
||||
G(l19 SUBSTRATE)
|
||||
G(l20 SUBSTRATE)
|
||||
GS(l20 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(l18 (-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(l23 (1334 621) (4230 5073))
|
||||
R(l22 (-964 -4594) (400 1000))
|
||||
R(l21 (-2125 -975) (250 950))
|
||||
)
|
||||
N(5 I($7)
|
||||
R(l3 (4000 3400) (2700 2000))
|
||||
)
|
||||
N(6 I(SUBSTRATE)
|
||||
R(l19 (7575 1125) (250 950))
|
||||
R(l20 (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