OpenRAM/technology/gf180mcu/tech/tech.py

448 lines
14 KiB
Python
Raw Normal View History

2023-01-10 01:02:25 +01:00
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import os
import drc as d
#from drc.design_rules import design_rules
#from drc.module_type import module_type
#from drc.custom_cell_properties import cell_properties
#from drc.custom_layer_properties import layer_properties
"""
File containing the process technology parameters for SCMOS 4m, 0.35um
"""
###################################################
# 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_scn4m'
tech_modules = d.module_type()
###################################################
# Custom cell properties
###################################################
cell_properties = d.cell_properties()
###################################################
# Custom cell properties
###################################################
layer_properties = d.layer_properties()
###################################################
# 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 m 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-6)
# default label zoom
GDS["zoom"] = 0.5
###################################################
# Interconnect stacks
###################################################
poly_stack = ("poly", "contact", "m1")
active_stack = ("active", "contact", "m1")
m1_stack = ("m1", "via1", "m2")
m2_stack = ("m2", "via2", "m3")
m3_stack = ("m3", "via3", "m4")
layer_indices = {"poly": 0,
"active": 0,
"m1": 1,
"m2": 2,
"m3": 3,
"m4": 4}
# The FEOL stacks get us up to m1
feol_stacks = [poly_stack,
active_stack]
# The BEOL stacks are m1 and up
beol_stacks = [m1_stack,
m2_stack,
m3_stack]
layer_stacks = feol_stacks + beol_stacks
preferred_directions = {"poly": "V",
"active": "V",
"m1": "H",
"m2": "V",
"m3": "H",
"m4": "V"}
###################################################
# Power grid
###################################################
# Use M3/M4
power_grid = m3_stack
###################################################
##GDS Layer Map
###################################################
# create the GDS layer map
layer={}
layer["pwell"] = (204, 0)
layer["nwell"] = (21, 0)
layer["dnwell"] = (12, 0)
layer["active"] = (22, 0)
layer["pimplant"] = (31, 0)
layer["nimplant"] = (32, 0)
layer["poly"] = (30, 0)
layer["contact"] = (33, 0)
layer["m1"] = (34, 0)
layer["via1"] = (35, 0)
layer["m2"] = (36, 0)
layer["via2"] = (38, 0)
layer["m3"] = (42, 0)
layer["via3"] = (40, 0)
layer["m4"] = (46, 0)
layer["via4"] = (41, 0)
layer["m5"] = (81, 0)
# Not an official layer
layer["text"] = (234, 5)
layer["mem"] = (108, 5)
layer["boundary"] = (0, 0)
label_purpose = 10
#use_purpose = {}
# Layer names for external PDKs
layer_names = {}
layer_names["active"] = "active"
layer_names["pwell"] = "pwell"
layer_names["nwell"] = "nwell"
2023-01-16 20:14:44 +01:00
layer_names["dnwell"] = "dnwell"
2023-01-10 01:02:25 +01:00
layer_names["nimplant"]= "nimplant"
layer_names["pimplant"]= "pimplant"
layer_names["poly"] = "poly"
layer_names["contact"] = "contact"
layer_names["m1"] = "metal1"
layer_names["via1"] = "via1"
layer_names["m2"] = "metal2"
layer_names["via2"] = "via2"
layer_names["m3"] = "metal3"
layer_names["via3"] = "via3"
layer_names["m4"] = "metal4"
layer_names["text"] = "text"
layer_names["mem"] = "SramCore"
layer_names["boundary"]= "boundary"
###################################################
# DRC/LVS Rules Setup
###################################################
# technology parameter
parameter={}
2023-01-16 20:14:44 +01:00
2023-01-10 01:02:25 +01:00
parameter["min_tx_size"] = 0.250
parameter["beta"] = 3
2023-01-16 20:14:44 +01:00
parameter["6T_inv_nmos_size"] = 0.6
parameter["6T_inv_pmos_size"] = 0.95
parameter["6T_access_size"] = 0.6
2023-01-10 01:02:25 +01:00
drc = d.design_rules("gf180")
# grid size
drc["grid"] = 0.005
2023-01-16 20:14:44 +01:00
drc["minwidth_tx"] = 0.28
#drc["minlength_channel"] = 0.150
drc["pwell_to_nwell"] = 0 # assuming same potential
2023-01-10 01:02:25 +01:00
drc.add_layer("nwell",
2023-01-16 20:14:44 +01:00
width=0.86,
spacing=0.6)
drc.add_layer("pwell",
width=0.74, # 0.6 for 1.5v
spacing=0.86) # equal potential 1.7 otherwise
2023-01-10 01:02:25 +01:00
drc.add_layer("poly",
2023-01-16 20:14:44 +01:00
width=0.18,
spacing=0.24)
2023-01-17 05:27:28 +01:00
drc["poly_extend_active"] = 0.22
drc["poly_to_contact"] = 0
2023-01-10 01:02:25 +01:00
# poly.7 Minimum enclosure of active around gate
2023-01-16 20:14:44 +01:00
#drc["active_enclose_gate"] = 0.075
2023-01-17 05:27:28 +01:00
drc["poly_to_active"] = 0.1
2023-01-10 01:02:25 +01:00
# poly.2 Minimum spacing of field poly
2023-01-16 20:14:44 +01:00
#drc["poly_to_field_poly"] = 0.210
2023-01-10 01:02:25 +01:00
drc.add_layer("active",
2023-01-16 20:14:44 +01:00
width=0.22,
spacing=0.280)
drc.add_enclosure("dnwell",
layer="pwell",
enclosure=2.5,
extension=2.5)
2023-01-10 01:02:25 +01:00
drc.add_enclosure("nwell",
layer="active",
2023-01-16 20:14:44 +01:00
enclosure=0.43,
extension=0.6)
2023-01-10 01:02:25 +01:00
2023-01-16 20:14:44 +01:00
drc.add_enclosure("pwell",
2023-01-10 01:02:25 +01:00
layer="active",
2023-01-16 20:14:44 +01:00
enclosure=0.43,
extension=0.6)
# nsd/psd.5a
#drc.add_enclosure("implant",
# layer="active",
# enclosure=0.125)
2023-01-10 01:02:25 +01:00
# Same as active enclosure?
2023-01-16 20:14:44 +01:00
#drc["implant_to_contact"] = 0.070
2023-01-10 01:02:25 +01:00
# nsd/psd.1 nsd/psd.2
2023-01-16 20:14:44 +01:00
#drc.add_layer("implant",
# width=0.380,
# spacing=0.380,
# area=0.265)
2023-01-10 01:02:25 +01:00
2023-01-17 05:27:28 +01:00
drc.add_layer("contact",
width=0.22,
spacing=0.25)
2023-01-10 01:02:25 +01:00
# licon.5c (0.06 extension), (licon.7 for extension)
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("active",
# layer="contact",
# enclosure=0.040,
# extension=0.060)
2023-01-10 01:02:25 +01:00
# licon.7
2023-01-16 20:14:44 +01:00
#drc["tap_extend_contact"] = 0.120
2023-01-10 01:02:25 +01:00
# licon.8 Minimum enclosure of poly around contact
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("poly",
# layer="contact",
# enclosure=0.08,
# extension=0.08)
2023-01-10 01:02:25 +01:00
# licon.11a
2023-01-16 20:14:44 +01:00
#drc["active_contact_to_gate"] = 0.050
2023-01-10 01:02:25 +01:00
# npc.4 > licon.14 0.19 > licon.11a
2023-01-16 20:14:44 +01:00
#drc["poly_contact_to_gate"] = 0.270
2023-01-10 01:02:25 +01:00
# licon.15
2023-01-16 20:14:44 +01:00
#drc["npc_enclose_poly"] = 0.1
2023-01-10 01:02:25 +01:00
# li.1, li.3
2023-01-16 20:14:44 +01:00
#drc.add_layer("li",
# width=0.170,
# spacing=0.170)
2023-01-10 01:02:25 +01:00
# licon.5
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("li",
# layer="contact",
# enclosure=0,
# extension=0.080)
#drc.add_enclosure("li",
# layer="mcon",
# enclosure=0,
# extension=0.080)
2023-01-10 01:02:25 +01:00
# mcon.1, mcon.2
2023-01-16 20:14:44 +01:00
#drc.add_layer("mcon",
# width=0.170,
# spacing=0.210)
2023-01-10 01:02:25 +01:00
drc.add_layer("m1",
2023-01-16 20:14:44 +01:00
width=0.23,
spacing=0.23,
area=0.1444)
2023-01-10 01:02:25 +01:00
# m1.4 Minimum enclosure of metal1
# m1.5 Minimum enclosure around contact on two opposite sides
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("m1",
# layer="mcon",
# enclosure=0.030,
# extension=0.060)
2023-01-10 01:02:25 +01:00
# via.4a Minimum enclosure around via1
# via.5a Minimum enclosure around via1 on two opposite sides
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("m1",
# layer="via1",
# enclosure=0.055,
# extension=0.085)
2023-01-10 01:02:25 +01:00
# via.1a Minimum width of via1
# via.2 Minimum spacing of via1
2023-01-16 20:14:44 +01:00
#drc.add_layer("via1",
# width=0.150,
# spacing=0.170)
2023-01-10 01:02:25 +01:00
drc.add_layer("m2",
2023-01-16 20:14:44 +01:00
width=0.28,
spacing=0.28,
area=0.1444)
2023-01-10 01:02:25 +01:00
# m2.4 Minimum enclosure around via1
# m2.5 Minimum enclosure around via1 on two opposite sides
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("m2",
# layer="via1",
# enclosure=0.055,
# extension=0.085)
2023-01-10 01:02:25 +01:00
# via2.4 Minimum enclosure around via2
# via2.5 Minimum enclosure around via2 on two opposite sides
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("m2",
# layer="via2",
# enclosure=0.040,
# extension=0.085)
2023-01-10 01:02:25 +01:00
# via2.1a Minimum width of Via2
# via2.2 Minimum spacing of Via2
2023-01-16 20:14:44 +01:00
#drc.add_layer("via2",
# width=0.200,
# spacing=0.200)
2023-01-10 01:02:25 +01:00
drc.add_layer("m3",
2023-01-16 20:14:44 +01:00
width=0.28,
spacing=0.28,
area=0.1444)
2023-01-10 01:02:25 +01:00
# m3.4 Minimum enclosure around via2
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("m3",
# layer="via2",
# enclosure=0.065)
2023-01-10 01:02:25 +01:00
# via3.4 Minimum enclosure around via3
# via3.5 Minimum enclosure around via3 on two opposite sides
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("m3",
# layer="via3",
# enclosure=0.060,
# extension=0.090)
2023-01-10 01:02:25 +01:00
# via3.1 Minimum width of Via3
# via3.2 Minimum spacing of Via3
2023-01-16 20:14:44 +01:00
#drc.add_layer("via3",
# width=0.200,
# spacing=0.200)
2023-01-10 01:02:25 +01:00
drc.add_layer("m4",
2023-01-16 20:14:44 +01:00
width=0.28,
spacing=0.28,
area=0.1444)
2023-01-10 01:02:25 +01:00
# m4.3 Minimum enclosure around via3
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("m4",
# layer="via3",
# enclosure=0.065)
#drc.add_enclosure("m4",
# layer="via4",
# enclosure=0.060)
2023-01-10 01:02:25 +01:00
# via4.1 Minimum width of Via4
# via4.2 Minimum spacing of Via4
2023-01-16 20:14:44 +01:00
#drc.add_layer("via4",
# width=0.800,
# spacing=0.800)
2023-01-10 01:02:25 +01:00
# m5.1 Minimum width of metal5
# m5.2 Minimum spacing of metal5
# m5.7 Minimum area of metal5
2023-01-16 20:14:44 +01:00
#drc.add_layer("m5",
# width=1.600,
# spacing=1.600,
# area=4.000)
2023-01-10 01:02:25 +01:00
# m5.3 Minimum enclosure around via4
2023-01-16 20:14:44 +01:00
#drc.add_enclosure("m5",
# layer="via4",
# enclosure=0.310)
2023-01-10 01:02:25 +01:00
# 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
###################################################
2023-01-16 20:14:44 +01:00
#if use_calibre:
# drc_name = "calibre"
# lvs_name = "calibre"
# pex_name = "calibre"
#if use_klayout:
# drc_name = "klayout"
# lvs_name = "klayout"
# pex_name = "klayout"
#else:
drc_name = "magic"
lvs_name = "netgen"
pex_name = "magic"
2023-01-10 01:02:25 +01:00