mirror of https://github.com/KLayout/klayout.git
Page:
2018 12 31
Pages
2018 12 31
2019 01 07
2019 01 19
2019 02 01
2019 02 03
2019 02 05
2019 02 17
2019 03 01
2019 03 09
2019 04 14
2019 05 05
2019 07 13
Deep Verification Base
Home
KLayout Package Manager (Salt)
KLayout Python Module
klayout Standalone KLayout Python Module
klayout Python Module Bridging Code
klayout Python Module Technical
5
2018 12 31
Matthias Köfferlein edited this page 2019-02-02 23:57:34 +01:00
First functional implementation of a netlist extractor
As of today, the "dvb" branch contains a basic hierarchical netlist extraction feature. It can be used from Ruby and Python. The basic entry point is "db::LayoutToNetlist" aka "RBA::LayoutToNetlist".
Highlights are:
- Customizable connectivity extraction with support for hierachical boolean operations.
- Customizable device recognition and extraction. A device extractor is provided currently for three-terminal MOSFET devices.
- Net extraction in device-less mode for net geometry extraction.
- Hierarchical netlist extraction.
- Netlist cleaning ("purge") and device combination.
- Backannotation of layout to nets.
- Net probing by location.
The current implementation is fairly tested and not performance-optimized. Advanced features are missing yet.
After all, the whole thing needs to be wrapped into a nice DSL similar to the DRC language which is a wrapper around the pretty basic RBA::Region class.
Here is a some code you can try:
Device-less extraction
The input for this sample is part of the sources:
ly = RBA::Layout::new
ly.read("testdata/algo/device_extract_l1.gds")
l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, []))
# only plain connectivity
ractive = l2n.make_layer( ly.layer(2, 0), "active" )
rpoly = l2n.make_polygon_layer( ly.layer(3, 0), "poly" )
rpoly_lbl = l2n.make_text_layer( ly.layer(3, 1), "poly_lbl" )
rdiff_cont = l2n.make_polygon_layer( ly.layer(4, 0), "diff_cont" )
rpoly_cont = l2n.make_polygon_layer( ly.layer(5, 0), "poly_cont" )
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0), "metal1" )
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1), "metal1_lbl" )
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0), "via1" )
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0), "metal2" )
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1), "metal2_lbl" )
# compute the source/drain shapes and register
# the layer (this will make it persisted)
rsd = ractive - rpoly
l2n.register(rsd, "sd")
# Intra-layer
l2n.connect(rsd)
l2n.connect(rpoly)
l2n.connect(rdiff_cont)
l2n.connect(rpoly_cont)
l2n.connect(rmetal1)
l2n.connect(rvia1)
l2n.connect(rmetal2)
# Inter-layer
l2n.connect(rsd, rdiff_cont)
l2n.connect(rpoly, rpoly_cont)
l2n.connect(rpoly_cont, rmetal1)
l2n.connect(rdiff_cont, rmetal1)
l2n.connect(rmetal1, rvia1)
l2n.connect(rvia1, rmetal2)
l2n.connect(rpoly, rpoly_lbl) # attaches labels
l2n.connect(rmetal1, rmetal1_lbl) # attaches labels
l2n.connect(rmetal2, rmetal2_lbl) # attaches labels
# Perform netlist extraction
l2n.extract_netlist
puts l2n.netlist.to_s
The output of this script is:
Circuit TRANS ($1=$1,$2=$2,$3=$3):
Circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5):
XTRANS $1 ($1=$2,$2=$4,$3=IN)
XTRANS $2 ($1=$2,$2=$5,$3=IN)
XTRANS $3 ($1=$5,$2=OUT,$3=$2)
XTRANS $4 ($1=$4,$2=OUT,$3=$2)
Circuit RINGO ():
XINV2 $1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD)
XINV2 $2 (IN=FB,$2=$I38,OUT=$I19,$4=VSS,$5=VDD)
XINV2 $3 (IN=$I19,$2=$I39,OUT=$I1,$4=VSS,$5=VDD)
XINV2 $4 (IN=$I1,$2=$I40,OUT=$I2,$4=VSS,$5=VDD)
XINV2 $5 (IN=$I2,$2=$I41,OUT=$I3,$4=VSS,$5=VDD)
XINV2 $6 (IN=$I3,$2=$I42,OUT=$I4,$4=VSS,$5=VDD)
XINV2 $7 (IN=$I4,$2=$I43,OUT=$I5,$4=VSS,$5=VDD)
XINV2 $8 (IN=$I5,$2=$I44,OUT=$I6,$4=VSS,$5=VDD)
XINV2 $9 (IN=$I6,$2=$I45,OUT=$I7,$4=VSS,$5=VDD)
XINV2 $10 (IN=$I7,$2=$I46,OUT=$I8,$4=VSS,$5=VDD)
Net extraction with devices:
ly = RBA::Layout::new
ly.read("testdata/algo/device_extract_l1.gds")
l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, []))
rnwell = l2n.make_layer( ly.layer(1, 0), "nwell" )
ractive = l2n.make_layer( ly.layer(2, 0), "active" )
rpoly = l2n.make_polygon_layer( ly.layer(3, 0), "poly" )
rpoly_lbl = l2n.make_text_layer( ly.layer(3, 1), "poly_lbl" )
rdiff_cont = l2n.make_polygon_layer( ly.layer(4, 0), "diff_cont" )
rpoly_cont = l2n.make_polygon_layer( ly.layer(5, 0), "poly_cont" )
rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0), "metal1" )
rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1), "metal1_lbl" )
rvia1 = l2n.make_polygon_layer( ly.layer(7, 0), "via1" )
rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0), "metal2" )
rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1), "metal2_lbl" )
# compute the PMOS source/drain areas and register
# these layers so they become persisted
rpactive = ractive & rnwell
rpgate = rpactive & rpoly
rpsd = rpactive - rpgate
l2n.register(rpsd, "psd")
# compute the NMOS source/drain areas and register
# these layers so they become persisted
rnactive = ractive - rnwell
rngate = rnactive & rpoly
rnsd = rnactive - rngate
l2n.register(rnsd, "nsd")
# PMOS transistor device extraction
pmos_ex = RBA::DeviceExtractorMOS3Transistor::new("PMOS")
l2n.extract_devices(pmos_ex, { "SD" => rpsd, "G" => rpgate, "P" => rpoly })
# NMOS transistor device extraction
nmos_ex = RBA::DeviceExtractorMOS3Transistor::new("NMOS")
l2n.extract_devices(nmos_ex, { "SD" => rnsd, "G" => rngate, "P" => rpoly })
# Define connectivity for netlist extraction
# Intra-layer
l2n.connect(rpsd)
l2n.connect(rnsd)
l2n.connect(rpoly)
l2n.connect(rdiff_cont)
l2n.connect(rpoly_cont)
l2n.connect(rmetal1)
l2n.connect(rvia1)
l2n.connect(rmetal2)
# Inter-layer
l2n.connect(rpsd, rdiff_cont)
l2n.connect(rnsd, rdiff_cont)
l2n.connect(rpoly, rpoly_cont)
l2n.connect(rpoly_cont, rmetal1)
l2n.connect(rdiff_cont, rmetal1)
l2n.connect(rmetal1, rvia1)
l2n.connect(rvia1, rmetal2)
l2n.connect(rpoly, rpoly_lbl) # attaches labels
l2n.connect(rmetal1, rmetal1_lbl) # attaches labels
l2n.connect(rmetal2, rmetal2_lbl) # attaches labels
# Perform netlist extraction
l2n.extract_netlist
# Simplification
l2n.netlist.purge
puts l2n.netlist.to_s
The output of this script is:
Circuit RINGO ():
XINV2 $1 (IN=$I8,$2=FB,OUT=(null),$4=VSS,$5=VDD)
XINV2 $2 (IN=FB,$2=(null),OUT=$I19,$4=VSS,$5=VDD)
XINV2 $3 (IN=$I19,$2=(null),OUT=$I1,$4=VSS,$5=VDD)
XINV2 $4 (IN=$I1,$2=(null),OUT=$I2,$4=VSS,$5=VDD)
XINV2 $5 (IN=$I2,$2=(null),OUT=$I3,$4=VSS,$5=VDD)
XINV2 $6 (IN=$I3,$2=(null),OUT=$I4,$4=VSS,$5=VDD)
XINV2 $7 (IN=$I4,$2=(null),OUT=$I5,$4=VSS,$5=VDD)
XINV2 $8 (IN=$I5,$2=(null),OUT=$I6,$4=VSS,$5=VDD)
XINV2 $9 (IN=$I6,$2=(null),OUT=$I7,$4=VSS,$5=VDD)
XINV2 $10 (IN=$I7,$2=(null),OUT=$I8,$4=VSS,$5=VDD)
Circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5):
DPMOS $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]
DPMOS $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]
DNMOS $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]
DNMOS $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]