Abstract basic DRC checks

This commit is contained in:
Matt Guthaus 2019-12-11 17:56:55 -08:00
parent f9a66e86b4
commit e048ada23c
7 changed files with 297 additions and 235 deletions

View File

@ -7,7 +7,7 @@
# #
import hierarchy_design import hierarchy_design
import debug import debug
from tech import drc, layer from tech import *
from vector import vector from vector import vector
@ -75,13 +75,18 @@ class contact(hierarchy_design.hierarchy_design):
self.second_layer_name = second_layer self.second_layer_name = second_layer
# Contacts will have unique per first layer # Contacts will have unique per first layer
if via_layer == "contact": if via_layer in layer.keys():
self.via_layer_name = via_layer
elif via_layer == "contact":
if first_layer in ("active", "poly"): if first_layer in ("active", "poly"):
self.via_layer_name = first_layer + "_" + via_layer self.via_layer_name = first_layer + "_" + via_layer
elif second_layer in ("active", "poly"):
self.via_layer_name = second_layer + "_" + via_layer
else: else:
self.via_layer_name = second_layer + "_" + via_layer debug.error("Invalid via layer {}".format(via_layer), -1)
else: else:
self.via_layer_name = via_layer debug.error("Invalid via layer {}".format(via_layer), -1)
def setup_layout_constants(self): def setup_layout_constants(self):
@ -224,23 +229,30 @@ from sram_factory import factory
# This is not instantiated and used for calculations only. # This is not instantiated and used for calculations only.
# These are static 1x1 contacts to reuse in all the design modules. # These are static 1x1 contacts to reuse in all the design modules.
well = factory.create(module_type="contact", well = factory.create(module_type="contact",
layer_stack=("active", "contact", "metal1"), layer_stack=active_stack,
directions=("H", "V")) directions=("H", "V"))
active = factory.create(module_type="contact", active = factory.create(module_type="contact",
layer_stack=("active", "contact", "metal1"), layer_stack=active_stack,
directions=("H", "V")) directions=("H", "V"))
poly = factory.create(module_type="contact", poly = factory.create(module_type="contact",
layer_stack=("poly", "contact", "metal1"), layer_stack=poly_stack,
directions=("V", "H")) directions=("V", "H"))
if "li" in layer.keys():
lim1 = factory.create(module_type="contact",
layer_stack=li_stack,
directions=("V", "H"))
else:
lim1 = None
m1m2 = factory.create(module_type="contact", m1m2 = factory.create(module_type="contact",
layer_stack=("metal1", "via1", "metal2"), layer_stack=metal1_stack,
directions=("H", "V")) directions=("H", "V"))
m2m3 = factory.create(module_type="contact", m2m3 = factory.create(module_type="contact",
layer_stack=("metal2", "via2", "metal3"), layer_stack=metal2_stack,
directions=("V", "H")) directions=("V", "H"))
if "metal4" in layer.keys(): if "metal4" in layer.keys():
m3m4 = factory.create(module_type="contact", m3m4 = factory.create(module_type="contact",
layer_stack=("metal3", "via3", "metal4"), layer_stack=metal3_stack,
directions=("H", "V")) directions=("H", "V"))
else: else:
m3m4 = None m3m4 = None

View File

@ -48,12 +48,15 @@ class design(hierarchy_design):
self.m4_space = drc("metal4_to_metal4") self.m4_space = drc("metal4_to_metal4")
self.active_width = drc("minwidth_active") self.active_width = drc("minwidth_active")
self.active_space = drc("active_to_body_active") self.active_space = drc("active_to_body_active")
self.contact_width = drc("minwidth_active_contact") if "contact" in layer:
self.contact_width = drc("minwidth_contact")
else:
self.contact_width = drc("minwidth_active_contact")
self.poly_to_active = drc("poly_to_active") self.poly_to_active = drc("poly_to_active")
self.poly_extend_active = drc("poly_extend_active") self.poly_extend_active = drc("poly_extend_active")
self.poly_to_poly_contact = drc("poly_to_poly_contact") self.poly_to_contact = drc("poly_to_contact")
self.active_contact_to_gate = drc("active_contact_to_gate") self.contact_to_gate = drc("contact_to_gate")
self.well_enclose_active = drc("well_enclosure_active") self.well_enclose_active = drc("well_enclosure_active")
self.implant_enclose_active = drc("implant_enclosure_active") self.implant_enclose_active = drc("implant_enclosure_active")
self.implant_space = drc("implant_to_implant") self.implant_space = drc("implant_to_implant")

View File

@ -43,6 +43,20 @@ class design_rules():
else: else:
debug.error("Must call complex DRC rule {} with arguments.".format(b),-1) debug.error("Must call complex DRC rule {} with arguments.".format(b),-1)
def add_layer(self, name, width, spacing, area=0):
# Minimum width
self.add("minwidth_{}".format(name), width)
# Minimum spacing (could be a table too)
self.add("{0}_to_{0}".format(name), spacing)
# Minimum area
self.add("minarea_{}".format(name), area)
def add_enclosure(self, name, layer, enclosure, extension=None):
self.add("{0}_enclosure_{1}".format(name, layer), enclosure)
# Reserved for asymmetric enclosures
if extension:
self.add("{0}_extend_{1}".format(name, layer), extension)
else:
self.add("{0}_extend_{1}".format(name, layer), enclosure)

View File

@ -130,18 +130,18 @@ class ptx(design.design):
# The contacted poly pitch (or uncontacted in an odd technology) # The contacted poly pitch (or uncontacted in an odd technology)
self.poly_pitch = max(2 * self.active_contact_to_gate + self.contact_width + self.poly_width, self.poly_pitch = max(2 * self.contact_to_gate + self.contact_width + self.poly_width,
self.poly_space) self.poly_space)
# The contacted poly pitch (or uncontacted in an odd technology) # The contacted poly pitch (or uncontacted in an odd technology)
self.contact_pitch = 2 * self.active_contact_to_gate + self.contact_width + self.poly_width self.contact_pitch = 2 * self.contact_to_gate + self.contact_width + self.poly_width
# The enclosure of an active contact. Not sure about second term. # The enclosure of an active contact. Not sure about second term.
active_enclose_contact = max(drc("active_enclosure_active_contact"), active_enclose_contact = max(drc("active_enclosure_contact"),
(self.active_width - self.contact_width) / 2) (self.active_width - self.contact_width) / 2)
# This is the distance from the edge of poly to the contacted end of active # This is the distance from the edge of poly to the contacted end of active
self.end_to_poly = active_enclose_contact + self.contact_width + self.active_contact_to_gate self.end_to_poly = active_enclose_contact + self.contact_width + self.contact_to_gate
# Active width is determined by enclosure on both ends and contacted pitch, # Active width is determined by enclosure on both ends and contacted pitch,

View File

@ -21,7 +21,9 @@ class contact_test(openram_test):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file) globals.init_openram(config_file)
for layer_stack in [("metal1", "via1", "metal2"), ("poly", "contact", "metal1")]: from tech import poly_stack, beol_stacks
for layer_stack in [poly_stack] + beol_stacks:
stack_name = ":".join(map(str, layer_stack)) stack_name = ":".join(map(str, layer_stack))
# Check single 1 x 1 contact" # Check single 1 x 1 contact"
@ -43,6 +45,10 @@ class contact_test(openram_test):
debug.info(2, "1 x 1 {} test".format(stack_name)) debug.info(2, "1 x 1 {} test".format(stack_name))
c = factory.create(module_type="contact", layer_stack=layer_stack, dimensions=(1, 1), directions=("V","V")) c = factory.create(module_type="contact", layer_stack=layer_stack, dimensions=(1, 1), directions=("V","V"))
self.local_drc_check(c) self.local_drc_check(c)
# Only do multiple contacts for BEOL
for layer_stack in beol_stacks:
stack_name = ":".join(map(str, layer_stack))
# check vertical array with one in the middle and two ends # check vertical array with one in the middle and two ends
debug.info(2, "1 x 3 {} test".format(stack_name)) debug.info(2, "1 x 3 {} test".format(stack_name))

View File

@ -29,7 +29,28 @@ GDS["unit"] = (0.0005,1e-9)
GDS["zoom"] = 0.05 GDS["zoom"] = 0.05
################################################### ###################################################
##GDS Layer Map # Interconnect stacks
###################################################
poly_stack = ("poly", "contact", "metal1")
active_stack = ("active", "contact", "metal1")
metal1_stack = ("metal1", "via1", "metal2")
metal2_stack = ("metal2", "via2", "metal3")
metal3_stack = ("metal3", "via3", "metal4")
# The FEOL stacks get us up to metal1
feol_stacks = [poly_stack,
active_stack]
# The BEOL stacks are metal1 and up
beol_stacks = [metal1_stack,
metal2_stack,
metal3_stack]
layer_stacks = feol_stacks + beol_stacks
###################################################
# GDS Layer Map
################################################### ###################################################
# create the GDS layer map # create the GDS layer map
@ -44,8 +65,7 @@ layer["vtg"] = (6, 0)
layer["vth"] = (7, 0) layer["vth"] = (7, 0)
layer["thkox"] = (8, 0) layer["thkox"] = (8, 0)
layer["poly"] = (9, 0) layer["poly"] = (9, 0)
layer["active_contact"] = (10, 0) layer["contact"] = (10, 0)
layer["poly_contact"] = (10, 0)
layer["metal1"] = (11, 0) layer["metal1"] = (11, 0)
layer["via1"] = (12, 0) layer["via1"] = (12, 0)
layer["metal2"] = (13, 0) layer["metal2"] = (13, 0)
@ -69,11 +89,7 @@ layer["text"] = (239, 0)
layer["boundary"]= (239, 0) layer["boundary"]= (239, 0)
################################################### ###################################################
##END GDS Layer Map # DRC/LVS Rules Setup
###################################################
###################################################
##DRC/LVS Rules Setup
################################################### ###################################################
#technology parameter #technology parameter
@ -105,18 +121,21 @@ drc["minlength_channel"] = 0.05
# WELL.2 Minimum spacing of nwell/pwell at different potential # WELL.2 Minimum spacing of nwell/pwell at different potential
drc["pwell_to_nwell"] = 0.225 drc["pwell_to_nwell"] = 0.225
# WELL.3 Minimum spacing of nwell/pwell at the same potential # WELL.3 Minimum spacing of nwell/pwell at the same potential
drc["well_to_well"] = 0.135
# WELL.4 Minimum width of nwell/pwell # WELL.4 Minimum width of nwell/pwell
drc["minwidth_well"] = 0.2 drc.add_layer("well",
width = 0.2,
spacing = 0.135)
# POLY.1 Minimum width of poly # POLY.1 Minimum width of poly
drc["minwidth_poly"] = 0.05
# POLY.2 Minimum spacing of poly AND active # POLY.2 Minimum spacing of poly AND active
drc["poly_to_poly"] = 0.14 drc.add_layer("poly",
width = 0.05,
spacing = 0.14)
# POLY.3 Minimum poly extension beyond active # POLY.3 Minimum poly extension beyond active
drc["poly_extend_active"] = 0.055 drc["poly_extend_active"] = 0.055
# Not a rule # Not a rule
drc["poly_to_poly_contact"] = 0.075 drc["poly_to_contact"] = 0.075
# POLY.4 Minimum enclosure of active around gate # POLY.4 Minimum enclosure of active around gate
drc["active_enclosure_gate"] = 0.07 drc["active_enclosure_gate"] = 0.07
# POLY.5 Minimum spacing of field poly to active # POLY.5 Minimum spacing of field poly to active
@ -129,162 +148,164 @@ drc["minarea_poly"] = 0.0
# ACTIVE.2 Minimum spacing of active # ACTIVE.2 Minimum spacing of active
drc["active_to_body_active"] = 0.08 drc["active_to_body_active"] = 0.08
# ACTIVE.1 Minimum width of active # ACTIVE.1 Minimum width of active
drc["minwidth_active"] = 0.09 drc.add_layer("active",
# Not a rule width = 0.09,
drc["active_to_active"] = 0 spacing = 0)
# ACTIVE.3 Minimum enclosure/spacing of nwell/pwell to active # ACTIVE.3 Minimum enclosure/spacing of nwell/pwell to active
drc["well_enclosure_active"] = 0.055 drc.add_enclosure("well",
# Reserved for asymmetric enclosures layer = "active",
drc["well_extend_active"] = 0.055 enclosure = 0.055)
# Not a rule
drc["minarea_active"] = 0
# IMPLANT.1 Minimum spacing of nimplant/ pimplant to channel # IMPLANT.1 Minimum spacing of nimplant/ pimplant to channel
drc["implant_to_channel"] = 0.07 drc["implant_to_channel"] = 0.07
# Not a rule # Not a rule
drc["implant_enclosure_active"] = 0 drc.add_enclosure("implant",
layer = "active",
enclosure = 0)
# Not a rule # Not a rule
drc["implant_enclosure_contact"] = 0 drc.add_enclosure("implant",
layer = "contact",
enclosure = 0)
# IMPLANT.2 Minimum spacing of nimplant/ pimplant to contact # IMPLANT.2 Minimum spacing of nimplant/ pimplant to contact
drc["implant_to_contact"] = 0.025 drc["implant_to_contact"] = 0.025
# IMPLANT.3 Minimum width/ spacing of nimplant/ pimplant # IMPLANT.3 Minimum width/ spacing of nimplant/ pimplant
drc["implant_to_implant"] = 0.045
# IMPLANT.4 Minimum width/ spacing of nimplant/ pimplant # IMPLANT.4 Minimum width/ spacing of nimplant/ pimplant
drc["minwidth_implant"] = 0.045 drc.add_layer("implant",
width = 0.045,
spacing = 0.045)
# CONTACT.1 Minimum width of contact # CONTACT.1 Minimum width of contact
drc["minwidth_active_contact"] = 0.065
# CONTACT.2 Minimum spacing of contact # CONTACT.2 Minimum spacing of contact
drc["active_contact_to_active_contact"] = 0.075 drc.add_layer("contact",
width = 0.065,
spacing = 0.075)
# CONTACT.4 Minimum enclosure of active around contact # CONTACT.4 Minimum enclosure of active around contact
drc["active_enclosure_active_contact"] = 0.005 drc.add_enclosure("active",
# Reserved for asymmetric enclosures layer = "contact",
drc["active_extend_active_contact"] = 0.005 enclosure = 0.005)
# CONTACT.6 Minimum spacing of contact and gate # CONTACT.6 Minimum spacing of contact and gate
drc["active_contact_to_gate"] = 0.0375 #changed from 0.035 drc["contact_to_gate"] = 0.0375 #changed from 0.035
# CONTACT.7 Minimum spacing of contact and poly # CONTACT.7 Minimum spacing of contact and poly
drc["active_contact_to_poly"] = 0.090 drc["contact_to_poly"] = 0.090
# CONTACT.1 Minimum width of contact # CONTACT.1 Minimum width of contact
drc["minwidth_poly_contact"] = 0.065
# CONTACT.2 Minimum spacing of contact # CONTACT.2 Minimum spacing of contact
drc["poly_contact_to_poly_contact"] = 0.075 drc.add_layer("contact",
# Reserved for asymmetric enclosures width = 0.065,
drc["poly_extend_contact"] = 0.005 spacing = 0.075)
# CONTACT.5 Minimum enclosure of poly around contact # CONTACT.5 Minimum enclosure of poly around contact
drc["poly_enclosure_poly_contact"] = 0.005 drc.add_enclosure("poly",
# Reserved for asymmetric enclosures layer = "contact",
drc["poly_extend_poly_contact"] = 0.005 enclosure = 0.005)
# CONTACT.6 Minimum spacing of contact and gate # CONTACT.6 Minimum spacing of contact and gate
drc["poly_contact_to_gate"] = 0.0375 #changed from 0.035 drc["contact_to_gate"] = 0.0375 #changed from 0.035
# CONTACT.7 Minimum spacing of contact and poly # CONTACT.7 Minimum spacing of contact and poly
drc["poly_contact_to_poly"] = 0.090 drc["contact_to_poly"] = 0.090
# METAL1.1 Minimum width of metal1 # METAL1.1 Minimum width of metal1
drc["minwidth_metal1"] = 0.065
# METAL1.2 Minimum spacing of metal1 # METAL1.2 Minimum spacing of metal1
drc["metal1_to_metal1"] = 0.065 drc.add_layer("metal1",
width = 0.065,
spacing = 0.065)
# METAL1.3 Minimum enclosure around contact on two opposite sides # METAL1.3 Minimum enclosure around contact on two opposite sides
drc["metal1_enclosure_active_contact"] = 0 drc.add_enclosure("metal1",
# Reserved for asymmetric enclosures layer = "contact",
drc["metal1_extend_active_contact"] = 0.035 enclosure = 0,
# METAL1.3 Minimum enclosure around contact on two opposite sides extension = 0.035)
drc["metal1_enclosure_poly_contact"] = 0
# Reserved for asymmetric enclosures
drc["metal1_extend_poly_contact"] = 0.035
# METAL1.4 inimum enclosure around via1 on two opposite sides # METAL1.4 inimum enclosure around via1 on two opposite sides
drc["metal1_extend_via1"] = 0.035 drc.add_enclosure("metal1",
# Reserved for asymmetric enclosures layer = "via1",
drc["metal1_enclosure_via1"] = 0 enclosure = 0,
# Not a rule extension = 0.035)
drc["minarea_metal1"] = 0
# VIA1.1 Minimum width of via1 # VIA1.1 Minimum width of via1
drc["minwidth_via1"] = 0.065
# VIA1.2 Minimum spacing of via1 # VIA1.2 Minimum spacing of via1
drc["via1_to_via1"] = 0.075 drc.add_layer("via1",
width = 0.065,
spacing = 0.075)
# METALINT.1 Minimum width of intermediate metal # METALINT.1 Minimum width of intermediate metal
drc["minwidth_metal2"] = 0.07
# METALINT.2 Minimum spacing of intermediate metal # METALINT.2 Minimum spacing of intermediate metal
drc["metal2_to_metal2"] = 0.07 drc.add_layer("metal2",
width = 0.07,
spacing = 0.07)
# METALINT.3 Minimum enclosure around via1 on two opposite sides # METALINT.3 Minimum enclosure around via1 on two opposite sides
drc["metal2_extend_via1"] = 0.035 drc.add_enclosure("metal2",
# Reserved for asymmetric enclosures layer = "via1",
drc["metal2_enclosure_via1"] = 0 enclosure = 0,
extension = 0.035)
# METALINT.4 Minimum enclosure around via[2-3] on two opposite sides # METALINT.4 Minimum enclosure around via[2-3] on two opposite sides
drc["metal2_extend_via2"] = 0.035 drc.add_enclosure("metal2",
# Reserved for asymmetric enclosures layer = "via2",
drc["metal2_enclosure_via2"] = 0 enclosure = 0,
# Not a rule extension = 0.035)
drc["minarea_metal2"] = 0
# VIA2-3.1 Minimum width of Via[2-3] # VIA2-3.1 Minimum width of Via[2-3]
drc["minwidth_via2"] = 0.065
# VIA2-3.2 Minimum spacing of Via[2-3] # VIA2-3.2 Minimum spacing of Via[2-3]
drc["via2_to_via2"] = 0.075 drc.add_layer("via2",
width = 0.065,
spacing = 0.075)
# METALINT.1 Minimum width of intermediate metal # METALINT.1 Minimum width of intermediate metal
drc["minwidth_metal3"] = 0.07
# METALINT.2 Minimum spacing of intermediate metal # METALINT.2 Minimum spacing of intermediate metal
#drc["metal3_to_metal3"] = 0.07
# Minimum spacing of metal3 wider than 0.09 & longer than 0.3 = 0.09 # Minimum spacing of metal3 wider than 0.09 & longer than 0.3 = 0.09
# Minimum spacing of metal3 wider than 0.27 & longer than 0.9 = 0.27 # Minimum spacing of metal3 wider than 0.27 & longer than 0.9 = 0.27
# Minimum spacing of metal3 wider than 0.5 & longer than 1.8 = 0.5 # Minimum spacing of metal3 wider than 0.5 & longer than 1.8 = 0.5
# Minimum spacing of metal3 wider than 0.9 & longer than 2.7 = 0.9 # Minimum spacing of metal3 wider than 0.9 & longer than 2.7 = 0.9
# Minimum spacing of metal3 wider than 1.5 & longer than 4.0 = 1.5 # Minimum spacing of metal3 wider than 1.5 & longer than 4.0 = 1.5
drc["metal3_to_metal3"] = drc_lut({(0.00, 0.0) : 0.07, drc.add_layer("metal3",
(0.09, 0.3) : 0.09, width = 0.07,
(0.27, 0.9) : 0.27, spacing = drc_lut({(0.00, 0.0) : 0.07,
(0.50, 1.8) : 0.5, (0.09, 0.3) : 0.09,
(0.90, 2.7) : 0.9, (0.27, 0.9) : 0.27,
(1.50, 4.0) : 1.5}) (0.50, 1.8) : 0.5,
(0.90, 2.7) : 0.9,
(1.50, 4.0) : 1.5}))
# METALINT.3 Minimum enclosure around via1 on two opposite sides # METALINT.3 Minimum enclosure around via1 on two opposite sides
drc["metal3_extend_via2"] = 0.035 drc.add_enclosure("metal3",
# Reserved for asymmetric enclosures layer = "via2",
drc["metal3_enclosure_via2"] = 0 enclosure = 0,
extension = 0.035)
# METALINT.4 Minimum enclosure around via[2-3] on two opposite sides # METALINT.4 Minimum enclosure around via[2-3] on two opposite sides
drc["metal3_extend_via3"]=0.035 drc.add_enclosure("metal3",
# Reserved for asymmetric enclosures layer = "via3",
drc["metal3_enclosure_via3"] = 0 enclosure = 0,
# Not a rule extension = 0.035)
drc["minarea_metal3"] = 0
# VIA2-3.1 Minimum width of Via[2-3] # VIA2-3.1 Minimum width of Via[2-3]
drc["minwidth_via3"] = 0.07
# VIA2-3.2 Minimum spacing of Via[2-3] # VIA2-3.2 Minimum spacing of Via[2-3]
drc["via3_to_via3"] = 0.085 drc.add_layer("via3",
width = 0.07,
spacing = 0.085)
# METALSMG.1 Minimum width of semi-global metal # METALSMG.1 Minimum width of semi-global metal
drc["minwidth_metal4"] = 0.14
# METALSMG.2 Minimum spacing of semi-global metal # METALSMG.2 Minimum spacing of semi-global metal
#drc["metal4_to_metal4"] = 0.14
# Minimum spacing of metal4 wider than 0.27 & longer than 0.9 = 0.27 # Minimum spacing of metal4 wider than 0.27 & longer than 0.9 = 0.27
# Minimum spacing of metal4 wider than 0.5 & longer than 1.8 = 0.5 # Minimum spacing of metal4 wider than 0.5 & longer than 1.8 = 0.5
# Minimum spacing of metal4 wider than 0.9 & longer than 2.7 = 0.9 # Minimum spacing of metal4 wider than 0.9 & longer than 2.7 = 0.9
# Minimum spacing of metal4 wider than 1.5 & longer than 4.0 = 1.5 # Minimum spacing of metal4 wider than 1.5 & longer than 4.0 = 1.5
drc["metal4_to_metal4"] = drc_lut({(0.00, 0.0) : 0.14, drc.add_layer("metal4",
(0.27, 0.9) : 0.27, width = 0.14,
(0.50, 1.8) : 0.5, spacing = drc_lut({(0.00, 0.0) : 0.14,
(0.90, 2.7) : 0.9, (0.27, 0.9) : 0.27,
(1.50, 4.0) : 1.5}) (0.50, 1.8) : 0.5,
(0.90, 2.7) : 0.9,
(1.50, 4.0) : 1.5}))
# METALSMG.3 Minimum enclosure around via[3-6] on two opposite sides # METALSMG.3 Minimum enclosure around via[3-6] on two opposite sides
drc["metal4_extend_via3"] = 0.0025 drc.add_enclosure("metal4",
# Reserved for asymmetric enclosure layer = "via3",
drc["metal4_enclosure_via3"] = 0.0025 enclosure = 0.0025)
# Not a rule
drc["minarea_metal4"] = 0
# Metal 5-10 are ommitted # Metal 5-10 are ommitted
################################################### ###################################################
##END DRC/LVS Rules # Spice Simulation Parameters
###################################################
###################################################
##Spice Simulation Parameters
################################################### ###################################################
#spice info #spice info
@ -347,11 +368,7 @@ parameter["sa_inv_nmos_size"] = 0.27 #micro-meters
parameter["bitcell_drain_cap"] = 0.1 #In Femto-Farad, approximation of drain capacitance parameter["bitcell_drain_cap"] = 0.1 #In Femto-Farad, approximation of drain capacitance
################################################### ###################################################
##END Spice Simulation Parameters # Technology Tool Preferences
###################################################
###################################################
##BEGIN Technology Tool Preferences
################################################### ###################################################
drc_name = "calibre" drc_name = "calibre"
@ -359,7 +376,3 @@ lvs_name = "calibre"
pex_name = "calibre" pex_name = "calibre"
blackbox_bitcell = False blackbox_bitcell = False
###################################################
##END Technology Tool Preferences
###################################################

View File

@ -28,6 +28,27 @@ GDS["unit"]=(0.001,1e-6)
# default label zoom # default label zoom
GDS["zoom"] = 0.5 GDS["zoom"] = 0.5
###################################################
# Interconnect stacks
###################################################
poly_stack = ("poly", "poly_contact", "metal1")
active_stack = ("active", "active_contact", "metal1")
metal1_stack = ("metal1", "via1", "metal2")
metal2_stack = ("metal2", "via2", "metal3")
metal3_stack = ("metal3", "via3", "metal4")
# The FEOL stacks get us up to metal1
feol_stacks = [poly_stack,
active_stack]
# The BEOL stacks are metal1 and up
beol_stacks = [metal1_stack,
metal2_stack,
metal3_stack]
layer_stacks = feol_stacks + beol_stacks
################################################### ###################################################
##GDS Layer Map ##GDS Layer Map
@ -43,8 +64,8 @@ layer["active"] = (43, 0)
layer["pimplant"] = (44, 0) layer["pimplant"] = (44, 0)
layer["nimplant"] = (45, 0) layer["nimplant"] = (45, 0)
layer["poly"] = (46, 0) layer["poly"] = (46, 0)
layer["active_contact"] = (48, 0)
layer["poly_contact"] = (47, 0) layer["poly_contact"] = (47, 0)
layer["active_contact"] = (48, 0)
layer["metal1"] = (49, 0) layer["metal1"] = (49, 0)
layer["via1"] = (50, 0) layer["via1"] = (50, 0)
layer["metal2"] = (51, 0) layer["metal2"] = (51, 0)
@ -56,11 +77,7 @@ layer["text"] = (63, 0)
layer["boundary"] = (63, 0) layer["boundary"] = (63, 0)
################################################### ###################################################
##END GDS Layer Map # DRC/LVS Rules Setup
###################################################
###################################################
##DRC/LVS Rules Setup
################################################### ###################################################
_lambda_ = 0.2 _lambda_ = 0.2
@ -90,163 +107,168 @@ drc["layer_map"]=os.environ.get("OPENRAM_TECH")+"/scn3me_subm/layers.map"
drc["minwidth_tx"] = 4*_lambda_ drc["minwidth_tx"] = 4*_lambda_
drc["minlength_channel"] = 2*_lambda_ drc["minlength_channel"] = 2*_lambda_
# 1.3 Minimum spacing between wells of same type (if both are drawn)
drc["well_to_well"] = 6*_lambda_
# 1.4 Minimum spacing between wells of different type (if both are drawn) # 1.4 Minimum spacing between wells of different type (if both are drawn)
drc["pwell_to_nwell"] = 0 drc["pwell_to_nwell"] = 0
# 1.3 Minimum spacing between wells of same type (if both are drawn)
# 1.1 Minimum width # 1.1 Minimum width
drc["minwidth_well"] = 12*_lambda_ drc.add_layer("well",
width = 12*_lambda_,
spacing = 6*_lambda_)
# 3.1 Minimum width # 3.1 Minimum width
drc["minwidth_poly"] = 2*_lambda_
# 3.2 Minimum spacing over active # 3.2 Minimum spacing over active
drc["poly_to_poly"] = 3*_lambda_ drc.add_layer("poly",
width = 2*_lambda_,
spacing = 3*_lambda_)
# 3.3 Minimum gate extension of active # 3.3 Minimum gate extension of active
drc["poly_extend_active"] = 2*_lambda_ drc["poly_extend_active"] = 2*_lambda_
# 5.5.b Minimum spacing between poly contact and other poly (alternative rules) # 5.5.b Minimum spacing between poly contact and other poly (alternative rules)
drc["poly_to_poly_contact"] = 4*_lambda_ drc["poly_to_contact"] = 4*_lambda_
# ?? # ??
drc["active_enclosure_gate"] = 0.0 drc["active_enclosure_gate"] = 0.0
# 3.5 Minimum field poly to active # 3.5 Minimum field poly to active
drc["poly_to_active"] = _lambda_ drc["poly_to_active"] = _lambda_
# 3.2.a Minimum spacing over field poly # 3.2.a Minimum spacing over field poly
drc["poly_to_field_poly"] = 3*_lambda_ drc["poly_to_field_poly"] = 3*_lambda_
# Not a rule
drc["minarea_poly"] = 0.0
# ?? # ??
drc["active_to_body_active"] = 4*_lambda_ # Fix me drc["active_to_body_active"] = 4*_lambda_ # Fix me
# 2.1 Minimum width # 2.1 Minimum width
drc["minwidth_active"] = 3*_lambda_
# 2.2 Minimum spacing # 2.2 Minimum spacing
drc["active_to_active"] = 3*_lambda_ drc.add_layer("active",
width = 3*_lambda_,
spacing = 3*_lambda_)
# 2.3 Source/drain active to well edge # 2.3 Source/drain active to well edge
drc["well_enclosure_active"] = 6*_lambda_ drc.add_enclosure("well",
# Reserved for asymmetric enclosures layer = "active",
drc["well_extend_active"] = 6*_lambda_ enclosure = 6*_lambda_)
# Not a rule
drc["minarea_active"] = 0.0
# 4.1 Minimum select spacing to channel of transistor to ensure adequate source/drain width # 4.1 Minimum select spacing to channel of transistor to ensure adequate source/drain width
drc["implant_to_channel"] = 3*_lambda_ drc["implant_to_channel"] = 3*_lambda_
# 4.2 Minimum select overlap of active # 4.2 Minimum select overlap of active
drc["implant_enclosure_active"] = 2*_lambda_ drc.add_enclosure("implant",
layer = "active",
enclosure = 2*_lambda_)
# 4.3 Minimum select overlap of contact # 4.3 Minimum select overlap of contact
drc["implant_enclosure_contact"] = _lambda_ drc.add_enclosure("implant",
layer = "contact",
enclosure = _lambda_)
# Not a rule # Not a rule
drc["implant_to_contact"] = 0 drc["implant_to_contact"] = 0
# Not a rule # Not a rule
drc["implant_to_implant"] = 0 drc.add_layer("implant",
# Not a rule width = 0,
drc["minwidth_implant"] = 0 spacing = 0)
# 6.1 Exact contact size # 6.1 Exact contact size
drc["minwidth_active_contact"] = 2*_lambda_
# 5.3 Minimum contact spacing # 5.3 Minimum contact spacing
drc["active_contact_to_active_contact"] = 3*_lambda_ drc.add_layer("active_contact",
# 6.2.b Minimum active overlap width = 2*_lambda_,
drc["active_enclosure_active_contact"] = _lambda_ spacing = 3*_lambda_)
# Reserved for asymmetric enclosure # 6.2.b Minimum active overlap
drc["active_extend_active_contact"] = _lambda_ drc.add_enclosure("active",
layer = "active_contact",
enclosure = _lambda_)
drc.add_enclosure("active",
layer = "contact",
enclosure = _lambda_)
# Reserved for other technologies # Reserved for other technologies
drc["active_contact_to_gate"] = 2*_lambda_ drc["contact_to_gate"] = 2*_lambda_
# 5.4 Minimum spacing to gate of transistor # 5.4 Minimum spacing to gate of transistor
drc["active_contact_to_poly"] = 2*_lambda_ drc["contact_to_poly"] = 2*_lambda_
# 6.1 Exact contact size # 6.1 Exact contact size
drc["minwidth_poly_contact"] = 2*_lambda_
# 5.3 Minimum contact spacing # 5.3 Minimum contact spacing
drc["poly_contact_to_poly_contact"] = 3*_lambda_ drc.add_layer("poly_contact",
width = 2*_lambda_,
spacing = 3*_lambda_)
# 5.2.b Minimum poly overlap # 5.2.b Minimum poly overlap
drc["poly_enclosure_poly_contact"] = _lambda_ drc.add_enclosure("poly",
# Reserved for asymmetric enclosures layer = "poly_contact",
drc["poly_extend_poly_contact"] = _lambda_ enclosure = _lambda_)
# Reserved for other technologies # Reserved for other technologies
drc["poly_contact_to_gate"] = 2*_lambda_ drc["poly_contact_to_gate"] = 2*_lambda_
# 5.4 Minimum spacing to gate of transistor # 5.4 Minimum spacing to gate of transistor
drc["poly_contact_to_poly"] = 2*_lambda_ drc["poly_contact_to_poly"] = 2*_lambda_
# 7.1 Minimum width # 7.1 Minimum width
drc["minwidth_metal1"] = 3*_lambda_
# 7.2 Minimum spacing # 7.2 Minimum spacing
drc["metal1_to_metal1"] = 3*_lambda_ drc.add_layer("metal1",
width = 3*_lambda_,
spacing = 3*_lambda_)
# 7.3 Minimum overlap of any contact # 7.3 Minimum overlap of any contact
drc["metal1_enclosure_active_contact"] = _lambda_ drc.add_enclosure("metal1",
# Reserved for asymmetric enclosure layer = "poly_contact",
drc["metal1_extend_active_contact"] = _lambda_ enclosure = _lambda_)
# 7.3 Minimum overlap of any contact drc.add_enclosure("metal1",
drc["metal1_enclosure_poly_contact"] = _lambda_ layer = "active_contact",
# Reserved for asymmetric enclosure enclosure = _lambda_)
drc["metal1_extend_poly_contact"] = _lambda_ # 8.3 Minimum overlap by metal1
# 8.3 Minimum overlap by metal1 drc.add_enclosure("metal1",
drc["metal1_enclosure_via1"] = _lambda_ layer = "via1",
# Reserve for asymmetric enclosures enclosure = _lambda_)
drc["metal1_extend_via1"] = _lambda_
# Not a rule
drc["minarea_metal1"] = 0
# 8.1 Exact size # 8.1 Exact size
drc["minwidth_via1"] = 2*_lambda_
# 8.2 Minimum via1 spacing # 8.2 Minimum via1 spacing
drc["via1_to_via1"] = 3*_lambda_ drc.add_layer("via1",
width = 2*_lambda_,
spacing = 3*_lambda_)
# 9.1 Minimum width # 9.1 Minimum width
drc["minwidth_metal2"] = 3*_lambda_
# 9.2 Minimum spacing # 9.2 Minimum spacing
drc["metal2_to_metal2"] = 3*_lambda_ drc.add_layer("metal2",
width = 3*_lambda_,
spacing = 3*_lambda_)
# 9.3 Minimum overlap of via1 # 9.3 Minimum overlap of via1
drc["metal2_extend_via1"] = _lambda_ drc.add_enclosure("metal2",
# Reserved for asymmetric enclosures layer = "via1",
drc["metal2_enclosure_via1"] = _lambda_ enclosure = _lambda_)
# 14.3 Minimum overlap by metal2 # 14.3 Minimum overlap by metal2
drc["metal2_extend_via2"] = _lambda_ drc.add_enclosure("metal2",
# Reserved for asymmetric enclosures layer = "via2",
drc["metal2_enclosure_via2"] = _lambda_ enclosure = _lambda_)
# Not a rule
drc["minarea_metal2"] = 0
# 14.1 Exact size # 14.1 Exact size
drc["minwidth_via2"] = 2*_lambda_
# 14.2 Minimum spacing # 14.2 Minimum spacing
drc["via2_to_via2"] = 3*_lambda_ drc.add_layer("via2",
width = 2*_lambda_,
spacing = 3*_lambda_)
# 15.1 Minimum width # 15.1 Minimum width
drc["minwidth_metal3"] = 3*_lambda_
# 15.2 Minimum spacing to metal3 # 15.2 Minimum spacing to metal3
drc["metal3_to_metal3"] = 3*_lambda_ drc.add_layer("metal3",
width = 3*_lambda_,
spacing = 3*_lambda_)
# 15.3 Minimum overlap of via 2 # 15.3 Minimum overlap of via 2
drc["metal3_extend_via2"] = _lambda_ drc.add_enclosure("metal3",
# Reserved for asymmetric enclosures layer = "via2",
drc["metal3_enclosure_via2"] = _lambda_ enclosure = _lambda_)
# 21.3 Minimum overlap by metal3 # 21.3 Minimum overlap by metal3
drc["metal3_extend_via3"] = _lambda_ drc.add_enclosure("metal3",
# Reserved for asymmetric enclosures layer = "via3",
drc["metal3_enclosure_via3"] = _lambda_ enclosure = _lambda_)
# Not a rule
drc["minarea_metal3"] = 0
# 21.1 Exact size # 21.1 Exact size
drc["minwidth_via3"] = 2*_lambda_
# 21.2 Minimum spacing # 21.2 Minimum spacing
drc["via3_to_via3"] = 3*_lambda_ drc.add_layer("via3",
width = 2*_lambda_,
spacing = 3*_lambda_)
# 22.1 Minimum width # 22.1 Minimum width
drc["minwidth_metal4"] = 6*_lambda_
# 22.2 Minimum spacing to metal4 # 22.2 Minimum spacing to metal4
drc["metal4_to_metal4"] = 6*_lambda_ drc.add_layer("metal4",
width = 6*_lambda_,
spacing = 6*_lambda_)
# 22.3 Minimum overlap of via 3 # 22.3 Minimum overlap of via 3
drc["metal4_extend_via3"] = 2*_lambda_ drc.add_enclosure("metal4",
# Reserved for asymmetric enclosures layer = "via3",
drc["metal4_enclosure_via3"] = 2*_lambda_ enclosure = 2*_lambda_)
# Not a rule
drc["minarea_metal4"] = 0
################################################### ###################################################
##END DRC/LVS Rules # Spice Simulation Parameters
###################################################
###################################################
##Spice Simulation Parameters
################################################### ###################################################
# spice model info # spice model info
@ -311,11 +333,7 @@ parameter["sa_inv_nmos_size"] = 9*_lambda_
parameter["bitcell_drain_cap"] = 0.2 #In Femto-Farad, approximation of drain capacitance parameter["bitcell_drain_cap"] = 0.2 #In Femto-Farad, approximation of drain capacitance
################################################### ###################################################
##END Spice Simulation Parameters # Technology Tool Preferences
###################################################
###################################################
##BEGIN Technology Tool Preferences
################################################### ###################################################
drc_name = "magic" drc_name = "magic"
@ -323,7 +341,3 @@ lvs_name = "netgen"
pex_name = "magic" pex_name = "magic"
blackbox_bitcell = False blackbox_bitcell = False
###################################################
##END Technology Tool Preferences
###################################################