#!/usr/bin/env python3 # See LICENSE for licensing information. # # Copyright (c) 2016-2021 Regents of the University of California # All rights reserved. # import os from design_rules import * from module_type import * from custom_cell_properties import cell_properties, cell from custom_layer_properties import layer_properties """ File containing the process technology parameters for Skywater 130nm. """ ################################################### # Custom modules ################################################### # This uses the default classes to instantiate module from # '$OPENRAM_HOME/compiler/modules'. # Using tech_modules['cellname'] you can override each class by providing a custom # implementation in '$OPENRAM_TECHDIR/modules/' # For example: tech_modules["contact"] = "contact_freepdk45" tech_modules = module_type() # These modules have been hand designed and provided in this repository. tech_modules["nand2_dec"] = "nand2_dec" tech_modules["nand3_dec"] = "nand3_dec" tech_modules["nand4_dec"] = "nand4_dec" # Override default OpenRAM modules to sky130 modules # These are for single port and dual port as a list, # or for both if there is no list, # or only applicable to one if there is no list. tech_modules["bitcell_1port"] = "sky130_bitcell" tech_modules["replica_bitcell_1port"] = "sky130_replica_bitcell" tech_modules["dummy_bitcell_1port"] = "sky130_dummy_bitcell" tech_modules["replica_bitcell_2port"] = "replica_bitcell_2port" tech_modules["dummy_bitcell_2port"] = "dummy_bitcell_2port" tech_modules["bitcell_2port"] = "bitcell_2port" tech_modules["bitcell_array"] = ["sky130_bitcell_array", "bitcell_array"] tech_modules["replica_bitcell_array"] = ["sky130_replica_bitcell_array", "replica_bitcell_array"] tech_modules["dummy_array"] = ["sky130_dummy_array", "dummy_array"] tech_modules["replica_column"] = ["sky130_replica_column", "replica_column"] tech_modules["col_cap_array"] = ["sky130_col_cap_array", "col_cap_array"] tech_modules["col_cap"] = ["sky130_col_cap", "col_cap_bitcell_2port"] tech_modules["corner"] = ["sky130_corner", None] tech_modules["internal"] = ["sky130_internal", None] tech_modules["row_cap_array"] = ["sky130_row_cap_array", "row_cap_array"] tech_modules["row_cap"] = ["sky130_row_cap", "row_cap_bitcell_2port"] # These modules are auto-generated from the nand decoders above and are not # found in this. tech_modules["buf_dec"] = "pbuf_dec" tech_modules["inv_dec"] = "pinv_dec" tech_modules["and2_dec"] = "and2_dec" tech_modules["and3_dec"] = "and3_dec" tech_modules["and4_dec"] = "and4_dec" ################################################### # Custom cell properties ################################################### cell_properties = cell_properties() cell_properties.bitcell_power_pin_directions = ("H", "H") cell_properties.bitcell_1port.mirror.x = True cell_properties.bitcell_1port.mirror.y = True cell_properties.bitcell_1port.end_caps = True cell_properties.bitcell_1port.boundary_layer = "mem" cell_properties.bitcell_1port.port_order = ['bl', 'br', 'gnd', 'vdd', 'vpb', 'vnb', 'wl'] cell_properties.bitcell_1port.port_types = ["OUTPUT", "OUTPUT", "GROUND", "POWER", "BIAS", "BIAS", "INPUT"] cell_properties.bitcell_1port.port_map = {'bl': 'BL', 'br': 'BR', 'wl': 'WL', 'vdd': 'VPWR', 'vnb': 'VNB', 'vpb': 'VPB', 'gnd': 'VGND'} cell_properties.bitcell_1port.wl_layer = "m2" cell_properties.bitcell_1port.bl_layer = "m1" cell_properties.bitcell_1port.vdd_layer = "m1" cell_properties.bitcell_1port.vdd_dir = "V" cell_properties.bitcell_1port.gnd_layer = "m2" cell_properties.bitcell_1port.gnd_dir = "H" cell_properties.bitcell_2port.mirror.x = True cell_properties.bitcell_2port.mirror.y = True cell_properties.bitcell_2port.end_caps = True cell_properties.bitcell_2port.port_order = ['bl0', 'br0', 'bl1', 'br1', 'wl0', 'wl1', 'vdd', 'gnd'] cell_properties.bitcell_2port.port_map = {'bl0': 'BL0', 'br0': 'BR0', 'bl1': 'BL1', 'br1': 'BR1', 'wl0': 'WL0', 'wl1': 'WL1', 'vdd': 'VDD', 'gnd': 'GND'} cell_properties.bitcell_1port.wl_layer = "m2" cell_properties.bitcell_1port.vdd_layer = "m2" cell_properties.bitcell_1port.vdd_dir = "H" cell_properties.bitcell_1port.gnd_layer = "m2" cell_properties.bitcell_1port.gnd_dir = "H" cell_properties.bitcell_2port.wl_layer = "m2" cell_properties.bitcell_2port.vdd_layer = "m1" cell_properties.bitcell_2port.vdd_dir = "H" cell_properties.bitcell_2port.gnd_layer = "m2" cell_properties.bitcell_2port.gnd_dir = "H" cell_properties.col_cap_1port_bitcell = cell(['br', 'vdd', 'gnd', 'bl', 'gate'], ['INPUT', 'POWER', 'GROUND', 'INPUT', 'INPUT'], {'bl': 'BL0', 'br': 'BL1', 'vdd': 'VPWR', 'gnd': 'VGND', 'gate': 'gate'}) cell_properties.col_cap_1port_bitcell.boundary_layer = "mem" cell_properties.col_cap_1port_strap_power = cell(['vdd', 'vpb', 'vnb'], ['POWER', 'BIAS', 'BIAS'], {'vnb': 'VNB', 'vpb': 'VPB', 'vdd': 'VPWR'}) cell_properties.col_cap_1port_strap_power.boundary_layer = "mem" cell_properties.col_cap_1port_strap_ground = cell(['gnd', 'vpb', 'vnb'], ['GROUND', 'BIAS', 'BIAS'], {'vnb': 'VNB', 'vpb': 'VPB', 'gnd': 'VGND'}) cell_properties.col_cap_1port_strap_ground.boundary_layer = "mem" cell_properties.row_cap_1port_cell = cell(['vdd', 'wl'], ['POWER', 'INPUT'], {'wl': 'WL', 'vdd': 'VPWR'}) cell_properties.row_cap_1port_cell.boundary_layer = "mem" cell_properties.col_cap_2port.port_order = ['bl0', 'br0', 'bl1', 'br1', 'vdd'] cell_properties.col_cap_2port.port_map = {'bl0': 'BL0', 'br0': 'BR0', 'bl1': 'BL1', 'br1': 'BR1', 'vdd': 'VDD'} cell_properties.row_cap_2port.port_order = ['wl0', 'wl1', 'gnd'] cell_properties.row_cap_2port.port_map = {'wl0': 'WL0', 'wl1': 'WL1', 'gnd': 'GND'} cell_properties.ptx.bin_spice_models = True cell_properties.ptx.model_is_subckt = True cell_properties.pgate.add_implants = True cell_properties.use_strap = True cell_properties.strap_module = "internal" cell_properties.strap_version = "wlstrap" cell_properties.dff.port_order = ['D', 'Q', 'clk', 'vdd', 'gnd'] cell_properties.dff.port_map = {'D': 'D', 'Q': 'Q', 'clk': 'CLK', 'vdd': 'VDD', 'gnd': 'GND'} cell_properties.nand2_dec.port_order = ['A', 'B', 'Z', 'vdd', 'gnd'] cell_properties.nand2_dec.port_map = {'A': 'A', 'B': 'B', 'Z': 'Z', 'vdd': 'VDD', 'gnd': 'GND'} cell_properties.nand3_dec.port_order = ['A', 'B', 'C', 'Z', 'vdd', 'gnd'] cell_properties.nand3_dec.port_map = {'A': 'A', 'B': 'B', 'C': 'C', 'Z': 'Z', 'vdd': 'VDD', 'gnd': 'GND'} cell_properties.nand4_dec.port_order = ['A', 'B', 'C', 'D', 'Z', 'vdd', 'gnd'] cell_properties.nand4_dec.port_map = {'A': 'A', 'B': 'B', 'C': 'C', 'D': 'D', 'Z': 'Z', 'vdd': 'VDD', 'gnd': 'GND'} cell_properties.sense_amp.port_order = ['bl', 'br', 'dout', 'en', 'vdd', 'gnd'] cell_properties.sense_amp.port_map = {'bl': 'BL', 'br': 'BR', 'dout': 'DOUT', 'en': 'EN', 'vdd': 'VDD', 'gnd': 'GND'} cell_properties.write_driver.port_order = ['din', 'bl', 'br', 'en', 'vdd', 'gnd'] cell_properties.write_driver.port_map = {'din': 'DIN', 'bl': 'BL', 'br': 'BR', 'en': 'EN', 'vdd': 'VDD', 'gnd': 'GND'} # You can override the GDS for custom cell using the following: # If it is a list, the first is single port and the second is dual port. # If it is string, it is used for both single and dual port. cell_properties.names["dff"] = "sky130_fd_bd_sram__openram_dff" cell_properties.names["nand2_dec"] = ["sky130_fd_bd_sram__openram_sp_nand2_dec", "sky130_fd_bd_sram__openram_dp_nand2_dec"] cell_properties.names["nand3_dec"] = ["sky130_fd_bd_sram__openram_sp_nand3_dec", "sky130_fd_bd_sram__openram_dp_nand3_dec"] cell_properties.names["nand4_dec"] = ["sky130_fd_bd_sram__openram_sp_nand4_dec", "sky130_fd_bd_sram__openram_dp_nand4_dec"] cell_properties.names["bitcell_2port"] = "sky130_fd_bd_sram__openram_dp_cell" cell_properties.names["dummy_bitcell_2port"] = "sky130_fd_bd_sram__openram_dp_cell_dummy" cell_properties.names["replica_bitcell_2port"] = "sky130_fd_bd_sram__openram_dp_cell_replica" cell_properties.names["col_cap_bitcell_2port"] = "sky130_fd_bd_sram__openram_dp_cell_cap_col" cell_properties.names["row_cap_bitcell_2port"] = "sky130_fd_bd_sram__openram_dp_cell_cap_row" cell_properties.names["sense_amp"] = "sky130_fd_bd_sram__openram_sense_amp" cell_properties.names["write_driver"] = "sky130_fd_bd_sram__openram_write_driver" array_row_multiple = 2 array_col_multiple = 2 ################################################### # Custom layer properties ################################################### layer_properties = layer_properties() layer_properties.hierarchical_decoder.bus_layer = "m1" layer_properties.hierarchical_decoder.bus_directions = "nonpref" layer_properties.hierarchical_decoder.input_layer = "li" layer_properties.hierarchical_decoder.output_layer = "m2" layer_properties.hierarchical_decoder.vertical_supply = True layer_properties.hierarchical_predecode.bus_layer = "m1" layer_properties.hierarchical_predecode.bus_directions = "nonpref" # This is added to allow the column decoder connections on m2 layer_properties.hierarchical_predecode.bus_pitch_factor = 1.2 layer_properties.hierarchical_predecode.bus_space_factor = 1.5 layer_properties.hierarchical_predecode.input_layer = "li" layer_properties.hierarchical_predecode.output_layer = "m2" layer_properties.hierarchical_predecode.vertical_supply = True layer_properties.hierarchical_predecode.force_horizontal_input_contact = True layer_properties.bank.stack = "m2_stack" layer_properties.bank.pitch = "m3_pitch" layer_properties.column_mux_array.select_layer = "m3" layer_properties.column_mux_array.bitline_layer = "m1" layer_properties.port_address.supply_offset = True layer_properties.port_data.enable_layer = "m1" layer_properties.port_data.channel_route_bitlines = False layer_properties.replica_column.even_rows = True layer_properties.wordline_driver.vertical_supply = True layer_properties.global_wordline_layer = "m5" ################################################### # Discrete tx bins ################################################### # enforce that tx sizes are within 25% of requested size after fingering. accuracy_requirement = 0.75 nmos_bins = { 0.15 : [0.36, 0.39, 0.42, 0.52, 0.54, 0.55, 0.58, 0.6, 0.61, 0.64, 0.65, 0.74, 0.84, 1.0, 1.26, 1.68, 2.0, 3.0, 5.0, 7.0], 0.18 : [0.42, 0.65, 1.0, 3.0, 5.0, 7.0], 0.25 : [0.65, 1.0, 3.0, 5.0, 7.0], 0.5 : [0.42, 0.55, 0.65, 1.0, 3.0, 5.0, 7.0], 1.0 : [0.42, 0.65, 1.0, 3.0, 5.0, 7.0], 2.0 : [0.42, 0.65, 1.0, 3.0, 5.0, 7.0], 4.0 : [0.42, 0.65, 1.0, 3.0, 5.0, 7.0], 8.0 : [0.42, 0.65, 1.0, 3.0, 5.0, 7.0], 20.0 : [0.42, 0.65, 1.0, 3.0, 5.0, 7.0] } pmos_bins = { 0.15 : [0.42, 0.55, 0.64, 0.84, 1.0, 1.12, 1.26, 1.65, 1.68, 2.0, 3.0, 5.0, 7.0], 1.0 : [0.42, 0.55, 1.0, 3.0, 5.0, 7.0], 2.0 : [0.42, 0.55, 1.0, 3.0, 5.0, 7.0], 4.0 : [0.42, 0.55, 1.0, 3.0, 5.0, 7.0], 8.0 : [0.42, 0.55, 1.0, 3.0, 5.0, 7.0], 0.17 : [0.42, 0.55, 0.64, 0.84, 1.0, 1.12], 0.18 : [0.42, 0.55, 0.64, 0.84, 1.0, 1.12, 1.26, 1.68, 2.0, 3.0, 5.0, 7.0], 0.25 : [1.0, 3.0, 5.0, 7.0], 0.5 : [0.42, 0.55, 1.0, 3.0, 5.0, 7.0], 20.0 : [0.42] } ################################################### # GDS file info ################################################### GDS = {} # gds units # From http://www.cnf.cornell.edu/cnf_spie9.html: "The first # is the size of a database unit in user units. The second is the size # of a database unit in meters. For example, if your library was # created with the default units (user unit = 1 um and 1000 database # units per user unit), then the first number would be 0.001 and the # second number would be 10-9. Typically, the first number is less than # 1, since you use more than 1 database unit per user unit. To # calculate the size of a user unit in meters, divide the second number # by the first." GDS["unit"] = (0.001, 1e-9) #GDS["unit"]=(0.001, 1e-6) ################################################### # Interconnect stacks ################################################### poly_stack = ("poly", "contact", "li") active_stack = ("active", "contact", "li") li_stack = ("li", "mcon", "m1") m1_stack = ("m1", "via1", "m2") m2_stack = ("m2", "via2", "m3") m3_stack = ("m3", "via3", "m4") m4_stack = ("m4", "via4", "m5") layer_indices = {"poly": 0, "active": 0, "nwell": 0, "li": 1, "m1": 2, "m2": 3, "m3": 4, "m4": 5, "m5": 6} # The FEOL stacks get us up to m1 feol_stacks = [poly_stack, active_stack, li_stack] # The BEOL stacks are m1 and up beol_stacks = [m1_stack, m2_stack, m3_stack, m4_stack] layer_stacks = feol_stacks + beol_stacks preferred_directions = {"poly": "V", "active": "V", "li": "V", "m1": "H", "m2": "V", "m3": "H", "m4": "V", "m5": "H"} ################################################### # GDS Layer Map ################################################### layer = {} layer["active"] = (65, 20) # diff layer["activep"] = (65, 20) # diff layer["tap"] = (65, 44) # tap layer["pwellp"] = (122,16) layer["nwell"] = (64, 20) # nwell layer["dnwell"] = (64,18) layer["nimplant"]= (93, 44) # nsdm layer["pimplant"]= (94, 20) # psdm layer["vtl"] = (125, 44) # lvtn layer["vth"] = (78, 44) # hvtp (pmos only) layer["thkox"] = (8, 0) layer["poly"] = (66, 20) layer["contact"] = (66, 44) # licon1 layer["npc"] = (95, 20) # npc (nitride cut) layer["li"] = (67, 20) # active li1 layer["mcon"] = (67, 44) # mcon layer["m1"] = (68, 20) # met1 layer["m1p"] = (68, 5) # met1 pin layer["via1"] = (68, 44) # via1 layer["m2"] = (69, 20) # met2 layer["m2p"] = (69, 5) # met2 pin layer["via2"] = (69, 44) # via2 layer["m3"] = (70, 20) # met3 layer["m3p"] = (70, 5) # met3 pin layer["via3"] = (70, 44) # via3 layer["m4"] = (71, 20) # met4 layer["m4p"] = (71, 5) # met4 pin layer["via4"] = (71, 44) # via4 layer["m5"] = (72, 20) # met5 layer["m5p"] = (72, 5) # met5 pin layer["boundary"]= (235, 4) # specific boundary type to define standard cell regions for DRC layer["stdc"] = (81, 4) layer["mem"] = (81, 2) # Not an official sky130 layer, but useful for router debug infos layer["text"]= (234, 5) # Excpected value according to sky130A tech file # If calibre is enabled, these will be swapped below #pin_purpose = 5 label_purpose = 5 #label_purpose = 16 #pin_purpose = 16 #label_purpose = 5 # pin_read purposes special_purposes = {layer["nwell"][0]: [layer["nwell"][1], 5, 59, 16]} #layer_override = {"VNB\x00": ["pwell",122]} layer_override = {"VNB": layer["pwellp"]} layer_override_name = {"VNB": "pwellp"} layer_override_purpose = {122: (64, 59)} # Layer names for external PDKs layer_names = {} layer_names["active"] = "diff" layer_names["activep"] = "diff" layer_names["tap"] = "tap" layer_names["pwellp"] = "pwellp" layer_names["nwell"] = "nwell" layer_names["dnwell"] = "dnwell" layer_names["nimplant"]= "nsdm" layer_names["pimplant"]= "psdm" layer_names["vtl"] = "lvtn" layer_names["vth"] = "hvtp" layer_names["thkox"] = "thkox" layer_names["poly"] = "poly" layer_names["contact"] = "licon1" layer_names["li"] = "li1" layer_names["mcon"] = "mcon" layer_names["m1"] = "met1" layer_names["m1p"] = "met1" layer_names["via1"] = "via" layer_names["m2"] = "met2" layer_names["m2p"] = "met2" layer_names["via2"] = "via2" layer_names["m3"] = "met3" layer_names["m3p"] = "met3" layer_names["via3"] = "via3" layer_names["m4"] = "met4" layer_names["m4p"] = "met4" layer_names["via4"] = "via4" layer_names["m5p"] = "met5" layer_names["boundary"]= "boundary" layer_names["stdc"] = "areaid.standardc" layer_names["mem"] = "areaid.core" layer_names["text"] = "text" ################################################### # DRC/LVS Rules Setup ################################################### # technology parameter parameter={} # difftap.2b parameter["min_tx_size"] = 0.150 parameter["beta"] = 3 parameter["6T_inv_nmos_size"] = 0.205 parameter["6T_inv_pmos_size"] = 0.09 parameter["6T_access_size"] = 0.135 drc = design_rules("sky130") # grid size drc["grid"] = 0.005 #DRC/LVS test set_up # Switching between calibre and magic can be useful for development, # it eventually should be deleted. NDA_PDK_ROOT = os.environ.get("NDA_PDK_ROOT", False) use_calibre = bool(NDA_PDK_ROOT) use_calibre = False use_klayout = False if use_calibre: # Correct order according to s8 pin_purpose = 16 label_purpose = 5 drc["drc_rules"] = NDA_PDK_ROOT + "/DRC/Calibre/s8_drcRules" drc["lvs_rules"] = NDA_PDK_ROOT + "/LVS/Calibre/lvs_s8_opts" drc["xrc_rules"] = NDA_PDK_ROOT + "/PEX/xRC/extLvsRules_s8_5lm" drc["layer_map"] = NDA_PDK_ROOT + "/VirtuosoOA/libs/technology_library/s8phirs_10r.layermap" # minwidth_tx with contact (no dog bone transistors) # difftap.2b drc["minwidth_tx"] = 0.360 drc["minlength_channel"] = 0.150 drc["pwell_to_nwell"] = 0 # nwell.1 Minimum width of nwell/pwell drc.add_layer("nwell", width=0.840, spacing=1.270) # poly.1a Minimum width of poly # poly.2 Minimum spacing of poly AND active drc.add_layer("poly", width=0.150, spacing=0.210) # poly.8 drc["poly_extend_active"] = 0.13 # Not a rule drc["poly_to_contact"] = 0 # poly.7 Minimum enclosure of active around gate drc["active_enclose_gate"] = 0.075 # poly.4 Minimum spacing of field poly to active drc["poly_to_active"] = 0.075 # poly.2 Minimum spacing of field poly drc["poly_to_field_poly"] = 0.210 # difftap.1 Minimum width of active # difftap.3 Minimum spacing of active drc.add_layer("active", width=0.150, spacing=0.270) # difftap.8 drc.add_enclosure("nwell", layer="active", enclosure=0.18, extension=0.18) # nsd/psd.5a drc.add_enclosure("implant", layer="active", enclosure=0.125) # Same as active enclosure? drc["implant_to_contact"] = 0.070 # nsd/psd.1 nsd/psd.2 drc.add_layer("implant", width=0.380, spacing=0.380, area=0.265) # licon.1, licon.2 drc.add_layer("contact", width=0.170, spacing=0.170) # licon.5c (0.06 extension), (licon.7 for extension) drc.add_enclosure("active", layer="contact", enclosure=0.040, extension=0.060) # licon.7 drc["tap_extend_contact"] = 0.120 # licon.8 Minimum enclosure of poly around contact drc.add_enclosure("poly", layer="contact", enclosure=0.08, extension=0.08) # licon.11a drc["active_contact_to_gate"] = 0.050 # npc.4 > licon.14 0.19 > licon.11a drc["poly_contact_to_gate"] = 0.270 # licon.15 drc["npc_enclose_poly"] = 0.1 # li.1, li.3 drc.add_layer("li", width=0.170, spacing=0.170) # licon.5 drc.add_enclosure("li", layer="contact", enclosure=0, extension=0.080) drc.add_enclosure("li", layer="mcon", enclosure=0, extension=0.080) # mcon.1, mcon.2 drc.add_layer("mcon", width=0.170, spacing=0.210) # m1.1 Minimum width of metal1 # m1.2 Minimum spacing of metal1 # m1.6 Minimum area of metal1 drc.add_layer("m1", width=0.140, spacing=0.140, area=0.083) # m1.4 Minimum enclosure of metal1 # m1.5 Minimum enclosure around contact on two opposite sides drc.add_enclosure("m1", layer="mcon", enclosure=0.030, extension=0.060) # via.4a Minimum enclosure around via1 # via.5a Minimum enclosure around via1 on two opposite sides drc.add_enclosure("m1", layer="via1", enclosure=0.055, extension=0.085) # via.1a Minimum width of via1 # via.2 Minimum spacing of via1 drc.add_layer("via1", width=0.150, spacing=0.170) # m2.1 Minimum width of intermediate metal # m2.2 Minimum spacing of intermediate metal # m2.6 Minimum area of metal2 drc.add_layer("m2", width=0.140, spacing=0.140, area=0.0676) # m2.4 Minimum enclosure around via1 # m2.5 Minimum enclosure around via1 on two opposite sides drc.add_enclosure("m2", layer="via1", enclosure=0.055, extension=0.085) # via2.4 Minimum enclosure around via2 # via2.5 Minimum enclosure around via2 on two opposite sides drc.add_enclosure("m2", layer="via2", enclosure=0.040, extension=0.085) # via2.1a Minimum width of Via2 # via2.2 Minimum spacing of Via2 drc.add_layer("via2", width=0.200, spacing=0.200) # m3.1 Minimum width of metal3 # m3.2 Minimum spacing of metal3 # m3.6 Minimum area of metal3 drc.add_layer("m3", width=0.300, spacing=0.300, area=0.240) # m3.4 Minimum enclosure around via2 drc.add_enclosure("m3", layer="via2", enclosure=0.065) # via3.4 Minimum enclosure around via3 # via3.5 Minimum enclosure around via3 on two opposite sides drc.add_enclosure("m3", layer="via3", enclosure=0.060, extension=0.090) # via3.1 Minimum width of Via3 # via3.2 Minimum spacing of Via3 drc.add_layer("via3", width=0.200, spacing=0.200) # m4.1 Minimum width of metal4 # m4.2 Minimum spacing of metal4 # m4.7 Minimum area of metal4 drc.add_layer("m4", width=0.300, spacing=0.300, area=0.240) # m4.3 Minimum enclosure around via3 drc.add_enclosure("m4", layer="via3", enclosure=0.065) # FIXME: Wrong rule m4.3 Minimum enclosure around via3 drc.add_enclosure("m4", layer="via4", enclosure=0.060) # via4.1 Minimum width of Via4 # via4.2 Minimum spacing of Via4 drc.add_layer("via4", width=0.800, spacing=0.800) # FIXME: Wrong rules # m5.1 Minimum width of metal5 # m5.2 Minimum spacing of metal5 # m5.7 Minimum area of metal5 drc.add_layer("m5", width=1.600, spacing=1.600, area=4.000) # m5.3 Minimum enclosure around via4 drc.add_enclosure("m5", layer="via4", enclosure=0.310) # Metal 5-10 are ommitted ################################################### # Spice Simulation Parameters ################################################### # spice info spice = {} spice["nmos"] = "sky130_fd_pr__nfet_01v8" spice["pmos"] = "sky130_fd_pr__pfet_01v8" spice["power"]="vccd1" spice["ground"]="vssd1" # whether or not the device model is actually a subckt spice["device_prefix"] = "X" spice["fet_libraries"] = {"TT": [[os.environ.get("SPICE_MODEL_DIR") + "/sky130.lib.spice", "tt"]]} # spice stimulus related variables spice["feasible_period"] = 10 # estimated feasible period in ns spice["supply_voltages"] = [1.7, 1.8, 1.9] # Supply voltage corners in [Volts] spice["nom_supply_voltage"] = 1.8 # Nominal supply voltage in [Volts] spice["rise_time"] = 0.005 # rise time in [Nano-seconds] spice["fall_time"] = 0.005 # fall time in [Nano-seconds] spice["temperatures"] = [0, 25, 100] # Temperature corners (celcius) spice["nom_temperature"] = 25 # Nominal temperature (celcius) # analytical delay parameters spice["nom_threshold"] = 0.49 # Typical Threshold voltage in Volts spice["wire_unit_r"] = 0.125 # Unit wire resistance in ohms/square spice["wire_unit_c"] = 0.134 # Unit wire capacitance ff/um^2 spice["min_tx_drain_c"] = 0.7 # Minimum transistor drain capacitance in ff spice["min_tx_gate_c"] = 0.2 # Minimum transistor gate capacitance in ff spice["dff_setup"] = 102.5391 # DFF setup time in ps spice["dff_hold"] = -56 # DFF hold time in ps spice["dff_in_cap"] = 6.89 # Input capacitance (D) [Femto-farad] spice["dff_out_cap"] = 6.89 # Output capacitance (Q) [Femto-farad] # analytical power parameters, many values are temporary spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nW spice["inv_leakage"] = 1 # Leakage power of inverter in nW spice["nand2_leakage"] = 1 # Leakage power of 2-input nand in nW spice["nand3_leakage"] = 1 # Leakage power of 3-input nand in nW spice["nor2_leakage"] = 1 # Leakage power of 2-input nor in nW spice["dff_leakage"] = 1 # Leakage power of flop in nW spice["default_event_frequency"] = 100 # Default event activity of every gate. MHz # Parameters related to sense amp enable timing and delay chain/RBL sizing parameter["le_tau"] = 2.25 # In pico-seconds. parameter["cap_relative_per_ff"] = 7.5 # Units of Relative Capacitance/ Femto-Farad parameter["dff_clk_cin"] = 30.6 # relative capacitance parameter["6tcell_wl_cin"] = 3 # relative capacitance parameter["min_inv_para_delay"] = 2.4 # Tau delay units parameter["sa_en_pmos_size"] = 0.72 # micro-meters parameter["sa_en_nmos_size"] = 0.27 # micro-meters parameter["sa_inv_pmos_size"] = 0.54 # micro-meters parameter["sa_inv_nmos_size"] = 0.27 # micro-meters parameter["bitcell_drain_cap"] = 0.1 # In Femto-Farad, approximation of drain capacitance ################################################### # Technology Tool Preferences ################################################### if use_calibre: drc_name = "calibre" lvs_name = "calibre" pex_name = "calibre" elif use_klayout: drc_name = "klayout" lvs_name = "klayout" pex_name = "klayout" else: drc_name = "magic" lvs_name = "netgen" pex_name = "magic" # This is used by uniqify to not rename the library cells library_prefix_name = "sky130_fd_bd_sram__" # List of cells to skip running DRC/LVS on directly # This will look for a maglef file and copy it over the mag file # before DRC after extraction blackbox_cells = ["sky130_fd_bd_sram__openram_dp_cell", "sky130_fd_bd_sram__openram_dp_cell_dummy", "sky130_fd_bd_sram__openram_dp_cell_replica", "sky130_fd_bd_sram__sram_sp_cell_opt1a", "sky130_fd_bd_sram__openram_sp_cell_opt1a_dummy", "sky130_fd_bd_sram__sram_sp_cell_opt1_ce", "sky130_fd_bd_sram__sram_sp_cell_opt1", "sky130_fd_bd_sram__openram_sp_cell_opt1_replica", "sky130_fd_bd_sram__openram_sp_cell_opt1a_replica", "sky130_fd_bd_sram__sram_sp_colend", "sky130_fd_bd_sram__sram_sp_colend_cent", "sky130_fd_bd_sram__sram_sp_colend_p_cent", "sky130_fd_bd_sram__sram_sp_colenda", "sky130_fd_bd_sram__sram_sp_colenda_cent", "sky130_fd_bd_sram__sram_sp_colenda_p_cent", "sky130_fd_bd_sram__sram_sp_rowend", "sky130_fd_bd_sram__sram_sp_rowenda", "sky130_fd_bd_sram__openram_sp_rowend_replica", "sky130_fd_bd_sram__openram_sp_rowenda_replica", "sky130_fd_bd_sram__sram_sp_corner", "sky130_fd_bd_sram__sram_sp_cornera", "sky130_fd_bd_sram__sram_sp_cornerb", "sky130_fd_bd_sram__sram_sp_wlstrapa", "sky130_fd_bd_sram__sram_sp_wlstrap_ce", "sky130_fd_bd_sram__sram_sp_wlstrap", "sky130_fd_bd_sram__sram_sp_wlstrap_p_ce", "sky130_fd_bd_sram__sram_sp_wlstrap_p"]