mirror of https://github.com/KLayout/klayout.git
208 lines
5.2 KiB
Plaintext
208 lines
5.2 KiB
Plaintext
|
|
source($drc_test_source)
|
|
|
|
# Drawing layers
|
|
|
|
nwell = input(1, 0)
|
|
diff = input(2, 0)
|
|
pplus = input(3, 0)
|
|
nplus = input(4, 0)
|
|
poly = input(5, 0)
|
|
thickox = input(6, 0)
|
|
polyres = input(7, 0)
|
|
contact = input(8, 0)
|
|
metal1 = input(9, 0)
|
|
via = input(10, 0)
|
|
metal2 = input(11, 0)
|
|
|
|
# Special layer for bulk terminals
|
|
|
|
bulk = make_layer
|
|
|
|
# Computed layers
|
|
|
|
poly_not_res = poly - polyres
|
|
poly_in_res = poly & polyres
|
|
|
|
diff_in_nwell = diff & nwell
|
|
pdiff = diff_in_nwell - nplus
|
|
ntie = diff_in_nwell & nplus
|
|
pgate = pdiff & poly_not_res
|
|
psd = pdiff - pgate
|
|
hv_pgate = pgate & thickox
|
|
lv_pgate = pgate - hv_pgate
|
|
hv_psd = psd & thickox
|
|
lv_psd = psd - thickox
|
|
|
|
diff_outside_nwell = diff - nwell
|
|
ndiff = diff_outside_nwell - pplus
|
|
ptie = diff_outside_nwell & pplus
|
|
ngate = ndiff & poly_not_res
|
|
nsd = ndiff - ngate
|
|
hv_ngate = ngate & thickox
|
|
lv_ngate = ngate - hv_ngate
|
|
hv_nsd = nsd & thickox
|
|
lv_nsd = nsd - thickox
|
|
|
|
# Resistor device extraction
|
|
|
|
class CustomResistorExtraction < RBA::GenericDeviceExtractor
|
|
|
|
def initialize(name, sheet_rho)
|
|
self.name = name
|
|
@sheet_rho = sheet_rho
|
|
end
|
|
|
|
def setup
|
|
|
|
define_layer("M", "Marker")
|
|
define_layer("C", "Conductor")
|
|
define_layer("R", "Resistor")
|
|
|
|
register_device_class (RBA::DeviceClassResistor::new);
|
|
|
|
end
|
|
|
|
def extract_devices(layer_geometry)
|
|
|
|
marker = layer_geometry[0]
|
|
conductor = layer_geometry[1]
|
|
resistor = layer_geometry[2]
|
|
|
|
conductor_geometry_index = 1
|
|
|
|
resistor_merged = resistor.merged
|
|
|
|
marker_edges = marker.merged.edges & resistor_merged.edges
|
|
|
|
resistor_merged.each do |r|
|
|
|
|
connection_edges = marker_edges.interacting(RBA::Region::new(r))
|
|
|
|
terminals = connection_edges.extended_out(1)
|
|
|
|
if terminals.size != 2
|
|
error("Resistor shape does not touch marker border in exactly two places", r)
|
|
else
|
|
|
|
# A = L*W
|
|
# P = 2*(L+W)
|
|
# -> L = p+sqrt(p*p-A)
|
|
# -> W = p-sqrt(p*p-A)
|
|
# (p=P/4)
|
|
|
|
p = sdbu * 0.25 * r.perimeter
|
|
a = sdbu * sdbu * r.area
|
|
|
|
d = Math.sqrt(p * p - a)
|
|
l = p + d
|
|
w = p - d
|
|
|
|
if w > 1e-3
|
|
|
|
device = create_device
|
|
|
|
device.trans = RBA::DCplxTrans::new(RBA::CplxTrans::new(dbu) * (r.bbox.center - RBA::Point::new));
|
|
|
|
device.set_parameter(RBA::DeviceClassResistor::PARAM_R, @sheet_rho * l / w);
|
|
device.set_parameter(RBA::DeviceClassResistor::PARAM_A, a);
|
|
|
|
define_terminal(device, RBA::DeviceClassResistor::TERMINAL_A, conductor_geometry_index, terminals[0]);
|
|
define_terminal(device, RBA::DeviceClassResistor::TERMINAL_B, conductor_geometry_index, terminals[1]);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
def get_connectivity(layout, layers)
|
|
|
|
# the layer definition is marker, conductor, resistor
|
|
# * resistor is used for extraction
|
|
# * conductor is used for producing the terminals
|
|
# * marker is included because it's required for the extraction
|
|
|
|
marker = layers[0]
|
|
conductor = layers[1]
|
|
resistor = layers[2]
|
|
|
|
conn = RBA::Connectivity::new
|
|
|
|
conn.connect(resistor, resistor)
|
|
conn.connect(conductor, resistor)
|
|
conn.connect(marker, resistor)
|
|
|
|
return conn;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Resistor
|
|
|
|
# Assumes a sheet rho of 150 Ohm/Square
|
|
res_ex = CustomResistorExtraction::new("RES", 150.0)
|
|
extract_devices(res_ex, { "C" => poly_not_res, "R" => poly_in_res, "M" => polyres })
|
|
|
|
# PMOS transistor device extraction
|
|
|
|
hvpmos_ex = RBA::DeviceExtractorMOS4Transistor::new("HVPMOS")
|
|
extract_devices(hvpmos_ex, { "SD" => psd, "G" => hv_pgate, "P" => poly_not_res, "W" => nwell })
|
|
|
|
lvpmos_ex = RBA::DeviceExtractorMOS4Transistor::new("LVPMOS")
|
|
extract_devices(lvpmos_ex, { "SD" => psd, "G" => lv_pgate, "P" => poly_not_res, "W" => nwell })
|
|
|
|
# NMOS transistor device extraction
|
|
|
|
lvnmos_ex = RBA::DeviceExtractorMOS4Transistor::new("LVNMOS")
|
|
extract_devices(lvnmos_ex, { "SD" => nsd, "G" => lv_ngate, "P" => poly_not_res, "W" => bulk })
|
|
|
|
hvnmos_ex = RBA::DeviceExtractorMOS4Transistor::new("HVNMOS")
|
|
extract_devices(hvnmos_ex, { "SD" => nsd, "G" => hv_ngate, "P" => poly_not_res, "W" => bulk })
|
|
|
|
|
|
# Define connectivity for netlist extraction
|
|
|
|
# Inter-layer
|
|
connect(contact, ntie)
|
|
connect(contact, ptie)
|
|
connect(nwell, ntie)
|
|
connect(psd, contact)
|
|
connect(nsd, contact)
|
|
connect(poly_not_res, contact)
|
|
connect(contact, metal1)
|
|
connect(metal1, via)
|
|
connect(via, metal2)
|
|
|
|
# Global connections
|
|
connect_global(ptie, "BULK")
|
|
connect_global(bulk, "BULK")
|
|
|
|
# Actually performs the extraction
|
|
|
|
netlist = l2n_data.netlist
|
|
|
|
# Write the netlist
|
|
|
|
writer = RBA::NetlistSpiceWriter::new
|
|
|
|
writer = RBA::NetlistSpiceWriter::new
|
|
netlist.write($drc_test_target, writer, "VDIV netlist before simplification")
|
|
|
|
# Netlist simplification
|
|
|
|
# NOTE: use make_top_level_pins before combine_devices as the pin
|
|
# stops the three resistors to be combined into one
|
|
netlist.make_top_level_pins
|
|
netlist.combine_devices
|
|
netlist.purge
|
|
netlist.purge_nets
|
|
|
|
netlist.write($drc_test_target_simplified, writer, "VDIV netlist after simplification")
|
|
|