Skip to content

2019 01 07

Matthias Köfferlein edited this page Jan 7, 2019 · 5 revisions

2019-01-07

The latest version (dvb branch) is fairly stable and has been tested on a medium-size SoC thoroughly. Here are some numbers: Extraction of all nets takes ~1hr/7GB memory. With the net tracer, the extraction of the VSS net alone was taking 5hrs and 10GB of memory. The VSS net alone has about 30M shapes. After taking the shapes of all nets and outputting them to an OASIS file, the original layout was reproduced (with the exception of a few text marker shapes). This means that all nets are captured and no shape is lost. The VSS net from this extracted netlist is XOR-identical to the one delived by the net tracer.

This was a pure backend extraction without devices.

The script used for this extraction was similar to this one:

top_cell = nil

prefix = "xout"

ly = RBA::Layout::new
ly.read("layout.oas")
tc = ly.top_cell

l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, tc, []))

# only plain connectivity

puts "Making layers ..."

rpoly       = l2n.make_polygon_layer( ly.layer(1,  0 ) )  # GDS #1 -> poly
rcont       = l2n.make_polygon_layer( ly.layer(2,  0 ) )  # GDS #2 -> contact (poly or diff)
rmetal1     = l2n.make_polygon_layer( ly.layer(3,  0 ) )  # GDS #3 -> metal 1
rmetal1_lbl = l2n.make_text_layer(    ly.layer(103,0 ) )  # GDS #103 -> metal 1 labels
rvia1       = l2n.make_polygon_layer( ly.layer(4,  0 ) )  # GDS #4 -> via 1
rmetal2     = l2n.make_polygon_layer( ly.layer(5,  0 ) )  # GDS #5 -> metal 2
rmetal2_lbl = l2n.make_text_layer(    ly.layer(105,0 ) )  # GDS #105 -> metal 2 labels
rvia2       = l2n.make_polygon_layer( ly.layer(6,  0 ) )  # GDS #6 -> via 2
rmetal3     = l2n.make_polygon_layer( ly.layer(7,  0 ) )  # GDS #7 -> metal 3
rmetal3_lbl = l2n.make_text_layer(    ly.layer(107,0 ) )  # GDS #107 -> metal 3 labels
rvia3       = l2n.make_polygon_layer( ly.layer(8,  0 ) )  # GDS #8 -> via 3
rmetal4     = l2n.make_polygon_layer( ly.layer(9,  0 ) )  # GDS #9 -> metal 4
rmetal4_lbl = l2n.make_text_layer(    ly.layer(109,0 ) )  # GDS #109 -> metal 4 labels
rvia4       = l2n.make_polygon_layer( ly.layer(10, 0 ) )  # GDS #10 -> via 4
rmetal5     = l2n.make_polygon_layer( ly.layer(11, 0 ) )  # GDS #11 -> metal 5
rmetal5_lbl = l2n.make_text_layer(    ly.layer(111,0 ) )  # GDS #111 -> metal 5 labels

puts "Connecting ..."

# Intra-layer
l2n.connect(rpoly)
l2n.connect(rcont)
l2n.connect(rmetal1)
l2n.connect(rvia1)
l2n.connect(rmetal2)
l2n.connect(rvia2)
l2n.connect(rmetal3)
l2n.connect(rvia3)
l2n.connect(rmetal4)
l2n.connect(rvia4)
l2n.connect(rmetal5)

# Inter-layer
l2n.connect(rpoly,      rcont)
l2n.connect(rcont,      rmetal1)
l2n.connect(rmetal1,    rvia1)
l2n.connect(rvia1,      rmetal2)
l2n.connect(rmetal2,    rvia2)
l2n.connect(rvia2,      rmetal3)
l2n.connect(rmetal3,    rvia3)
l2n.connect(rvia3,      rmetal4)
l2n.connect(rmetal4,    rvia4)
l2n.connect(rvia4,      rmetal5)
l2n.connect(rmetal1,    rmetal1_lbl)   #  attaches labels
l2n.connect(rmetal2,    rmetal2_lbl)   #  attaches labels
l2n.connect(rmetal3,    rmetal3_lbl)   #  attaches labels
l2n.connect(rmetal4,    rmetal4_lbl)   #  attaches labels
l2n.connect(rmetal5,    rmetal5_lbl)   #  attaches labels

puts "Running netlist extraction ..."

# Perform netlist extraction 
l2n.extract_netlist

out = { 
  1  => rpoly, 
  2 => rcont, 
  3 => rmetal1, 
  103 => rmetal1_lbl, 
  4 => rvia1, 
  5 => rmetal2, 
  105 => rmetal2_lbl, 
  6 => rvia2, 
  7 => rmetal3, 
  107 => rmetal3_lbl, 
  8 => rvia3, 
  9 => rmetal4, 
  109 => rmetal4_lbl,
  10 => rvia4, 
  11 => rmetal5, 
  111 => rmetal5_lbl
}

# write an annotated layout - all nets are put into 
# cells called "NET_" + net name. The nets are output
# hierarchically where the circuits are put into cells
# called "CIRCUIT_" + circuit name

ly2 = RBA::Layout::new
top2 = ly2.create_cell(net.expanded_name)

lmap = {}
out.each do |ln,r|
  lmap[ly2.layer(ln, 0)] = r
end
l2n.build_all_nets(l2n.cell_mapping_into(ly2, top2), ly2, lmap, "NET_", "CIRCUIT_")

ly2.write("#{prefix}_all.oas.gz")
ly2._destroy

Support for extracting four-terminal MOS devices and global nets

Four-terminal devices with a bulk connection require the concept of global nets. A specific global net represents the bulk (p-body) of the wafer. n-type transistors will have their bulk terminal connected to this virtual net. Such a net is represented by a global net. Global nets are inherited by parent circuits automatically. Global nets can be included in a connectivity specification with "connect_global".

A MOS4 device extractor emits bulk terminal shapes as copies of the gate shape to a layer as "W" input (well). When connecting this layer to the global "BULK" net, the "B" (bulk) terminal of the MOS4 devices will be connected to this global net.

Here is code for such an extraction. It also recognizes tie-down diodes for substrate and well connections. The p-tie-down diode will also connect to the "BULK" global net. The n diode will connect to the n-well area. n-well is included in the net extraction like a conductive layer.

 ly = RBA::Layout::new
ly.read(File.join($ut_testsrc, "testdata", "algo", "device_extract_l3.gds"))

l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, []))

rbulk       = l2n.make_polygon_layer( ly.layer       )
rnwell      = l2n.make_polygon_layer( ly.layer(1, 0) )
ractive     = l2n.make_polygon_layer( ly.layer(2, 0) )
rpoly       = l2n.make_polygon_layer( ly.layer(3, 0) )
rpoly_lbl   = l2n.make_text_layer(    ly.layer(3, 1) )
rdiff_cont  = l2n.make_polygon_layer( ly.layer(4, 0) )
rpoly_cont  = l2n.make_polygon_layer( ly.layer(5, 0) )
rmetal1     = l2n.make_polygon_layer( ly.layer(6, 0) )
rmetal1_lbl = l2n.make_text_layer(    ly.layer(6, 1) )
rvia1       = l2n.make_polygon_layer( ly.layer(7, 0) )
rmetal2     = l2n.make_polygon_layer( ly.layer(8, 0) )
rmetal2_lbl = l2n.make_text_layer(    ly.layer(8, 1) )
rpplus      = l2n.make_polygon_layer( ly.layer(10, 0) )
rnplus      = l2n.make_polygon_layer( ly.layer(11, 0) )

ractive_in_nwell = ractive & rnwell
rpactive    = ractive_in_nwell & rpplus
rntie       = ractive_in_nwell & rnplus
rpgate      = rpactive & rpoly
rpsd        = rpactive - rpgate

ractive_outside_nwell = ractive - rnwell
rnactive    = ractive_outside_nwell & rnplus
rptie       = ractive_outside_nwell & rpplus
rngate      = rnactive & rpoly
rnsd        = rnactive - rngate

# PMOS transistor device extraction
pmos_ex = RBA::DeviceExtractorMOS4Transistor::new("PMOS")
l2n.extract_devices(pmos_ex, { "SD" => rpsd, "G" => rpgate, "P" => rpoly, "W" => rnwell })

# NMOS transistor device extraction
nmos_ex = RBA::DeviceExtractorMOS4Transistor::new("NMOS")
l2n.extract_devices(nmos_ex, { "SD" => rnsd, "G" => rngate, "P" => rpoly, "W" => rbulk })

# Define connectivity for netlist extraction

# Intra-layer
l2n.connect(rpsd)
l2n.connect(rnsd)
l2n.connect(rnwell)
l2n.connect(rpoly)
l2n.connect(rdiff_cont)
l2n.connect(rpoly_cont)
l2n.connect(rmetal1)
l2n.connect(rvia1)
l2n.connect(rmetal2)
l2n.connect(rptie)
l2n.connect(rntie)

# 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(rdiff_cont, rntie)
l2n.connect(rdiff_cont, rptie)
l2n.connect(rnwell,     rntie)
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

# Global connections
l2n.connect_global(rptie, "BULK")
l2n.connect_global(rbulk, "BULK")

# Perform netlist extraction 
l2n.extract_netlist

puts l2n.netlist.to_s

Clone this wiki locally