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")