From e048ada23c256dabc090f38a737c010b51f4ff15 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 11 Dec 2019 17:56:55 -0800 Subject: [PATCH] Abstract basic DRC checks --- compiler/base/contact.py | 32 ++-- compiler/base/design.py | 9 +- compiler/drc/design_rules.py | 16 +- compiler/pgates/ptx.py | 8 +- compiler/tests/03_contact_test.py | 8 +- technology/freepdk45/tech/tech.py | 243 +++++++++++++++-------------- technology/scn4m_subm/tech/tech.py | 216 +++++++++++++------------ 7 files changed, 297 insertions(+), 235 deletions(-) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index acfcc265..26a59d31 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -7,7 +7,7 @@ # import hierarchy_design import debug -from tech import drc, layer +from tech import * from vector import vector @@ -75,13 +75,18 @@ class contact(hierarchy_design.hierarchy_design): self.second_layer_name = second_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"): self.via_layer_name = first_layer + "_" + via_layer + elif second_layer in ("active", "poly"): + self.via_layer_name = second_layer + "_" + via_layer else: - self.via_layer_name = second_layer + "_" + via_layer + debug.error("Invalid via layer {}".format(via_layer), -1) else: - self.via_layer_name = via_layer + debug.error("Invalid via layer {}".format(via_layer), -1) + def setup_layout_constants(self): @@ -224,23 +229,30 @@ from sram_factory import factory # This is not instantiated and used for calculations only. # These are static 1x1 contacts to reuse in all the design modules. well = factory.create(module_type="contact", - layer_stack=("active", "contact", "metal1"), + layer_stack=active_stack, directions=("H", "V")) active = factory.create(module_type="contact", - layer_stack=("active", "contact", "metal1"), + layer_stack=active_stack, directions=("H", "V")) poly = factory.create(module_type="contact", - layer_stack=("poly", "contact", "metal1"), + layer_stack=poly_stack, 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", - layer_stack=("metal1", "via1", "metal2"), + layer_stack=metal1_stack, directions=("H", "V")) m2m3 = factory.create(module_type="contact", - layer_stack=("metal2", "via2", "metal3"), + layer_stack=metal2_stack, directions=("V", "H")) if "metal4" in layer.keys(): m3m4 = factory.create(module_type="contact", - layer_stack=("metal3", "via3", "metal4"), + layer_stack=metal3_stack, directions=("H", "V")) else: m3m4 = None diff --git a/compiler/base/design.py b/compiler/base/design.py index c6385243..0ecfbbd4 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -48,12 +48,15 @@ class design(hierarchy_design): self.m4_space = drc("metal4_to_metal4") self.active_width = drc("minwidth_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_extend_active = drc("poly_extend_active") - self.poly_to_poly_contact = drc("poly_to_poly_contact") - self.active_contact_to_gate = drc("active_contact_to_gate") + self.poly_to_contact = drc("poly_to_contact") + self.contact_to_gate = drc("contact_to_gate") self.well_enclose_active = drc("well_enclosure_active") self.implant_enclose_active = drc("implant_enclosure_active") self.implant_space = drc("implant_to_implant") diff --git a/compiler/drc/design_rules.py b/compiler/drc/design_rules.py index 1017aca6..cf54bdb3 100644 --- a/compiler/drc/design_rules.py +++ b/compiler/drc/design_rules.py @@ -43,6 +43,20 @@ class design_rules(): else: 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) diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index a1606ac3..588152c0 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -130,18 +130,18 @@ class ptx(design.design): # 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) # 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. - active_enclose_contact = max(drc("active_enclosure_active_contact"), + active_enclose_contact = max(drc("active_enclosure_contact"), (self.active_width - self.contact_width) / 2) # 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, diff --git a/compiler/tests/03_contact_test.py b/compiler/tests/03_contact_test.py index 2e3f4f0f..60d8cd6b 100755 --- a/compiler/tests/03_contact_test.py +++ b/compiler/tests/03_contact_test.py @@ -21,7 +21,9 @@ class contact_test(openram_test): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) 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)) # 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)) c = factory.create(module_type="contact", layer_stack=layer_stack, dimensions=(1, 1), directions=("V","V")) 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 debug.info(2, "1 x 3 {} test".format(stack_name)) diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index a8b9d263..f8dc7d06 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -29,7 +29,28 @@ GDS["unit"] = (0.0005,1e-9) 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 @@ -44,8 +65,7 @@ layer["vtg"] = (6, 0) layer["vth"] = (7, 0) layer["thkox"] = (8, 0) layer["poly"] = (9, 0) -layer["active_contact"] = (10, 0) -layer["poly_contact"] = (10, 0) +layer["contact"] = (10, 0) layer["metal1"] = (11, 0) layer["via1"] = (12, 0) layer["metal2"] = (13, 0) @@ -69,11 +89,7 @@ layer["text"] = (239, 0) layer["boundary"]= (239, 0) ################################################### -##END GDS Layer Map -################################################### - -################################################### -##DRC/LVS Rules Setup +# DRC/LVS Rules Setup ################################################### #technology parameter @@ -105,18 +121,21 @@ drc["minlength_channel"] = 0.05 # WELL.2 Minimum spacing of nwell/pwell at different potential drc["pwell_to_nwell"] = 0.225 # WELL.3 Minimum spacing of nwell/pwell at the same potential -drc["well_to_well"] = 0.135 # 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 -drc["minwidth_poly"] = 0.05 # 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 drc["poly_extend_active"] = 0.055 # Not a rule -drc["poly_to_poly_contact"] = 0.075 +drc["poly_to_contact"] = 0.075 # POLY.4 Minimum enclosure of active around gate drc["active_enclosure_gate"] = 0.07 # POLY.5 Minimum spacing of field poly to active @@ -129,162 +148,164 @@ drc["minarea_poly"] = 0.0 # ACTIVE.2 Minimum spacing of active drc["active_to_body_active"] = 0.08 # ACTIVE.1 Minimum width of active -drc["minwidth_active"] = 0.09 -# Not a rule -drc["active_to_active"] = 0 +drc.add_layer("active", + width = 0.09, + spacing = 0) # ACTIVE.3 Minimum enclosure/spacing of nwell/pwell to active -drc["well_enclosure_active"] = 0.055 -# Reserved for asymmetric enclosures -drc["well_extend_active"] = 0.055 -# Not a rule -drc["minarea_active"] = 0 +drc.add_enclosure("well", + layer = "active", + enclosure = 0.055) # IMPLANT.1 Minimum spacing of nimplant/ pimplant to channel drc["implant_to_channel"] = 0.07 # Not a rule -drc["implant_enclosure_active"] = 0 +drc.add_enclosure("implant", + layer = "active", + enclosure = 0) # 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 drc["implant_to_contact"] = 0.025 # IMPLANT.3 Minimum width/ spacing of nimplant/ pimplant -drc["implant_to_implant"] = 0.045 # 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 -drc["minwidth_active_contact"] = 0.065 # 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 -drc["active_enclosure_active_contact"] = 0.005 -# Reserved for asymmetric enclosures -drc["active_extend_active_contact"] = 0.005 +drc.add_enclosure("active", + layer = "contact", + enclosure = 0.005) + # 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 -drc["active_contact_to_poly"] = 0.090 +drc["contact_to_poly"] = 0.090 # CONTACT.1 Minimum width of contact -drc["minwidth_poly_contact"] = 0.065 # CONTACT.2 Minimum spacing of contact -drc["poly_contact_to_poly_contact"] = 0.075 -# Reserved for asymmetric enclosures -drc["poly_extend_contact"] = 0.005 +drc.add_layer("contact", + width = 0.065, + spacing = 0.075) # CONTACT.5 Minimum enclosure of poly around contact -drc["poly_enclosure_poly_contact"] = 0.005 -# Reserved for asymmetric enclosures -drc["poly_extend_poly_contact"] = 0.005 +drc.add_enclosure("poly", + layer = "contact", + enclosure = 0.005) # 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 -drc["poly_contact_to_poly"] = 0.090 +drc["contact_to_poly"] = 0.090 # METAL1.1 Minimum width of metal1 -drc["minwidth_metal1"] = 0.065 # 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 -drc["metal1_enclosure_active_contact"] = 0 -# Reserved for asymmetric enclosures -drc["metal1_extend_active_contact"] = 0.035 -# METAL1.3 Minimum enclosure around contact on two opposite sides -drc["metal1_enclosure_poly_contact"] = 0 -# Reserved for asymmetric enclosures -drc["metal1_extend_poly_contact"] = 0.035 +drc.add_enclosure("metal1", + layer = "contact", + enclosure = 0, + extension = 0.035) # METAL1.4 inimum enclosure around via1 on two opposite sides -drc["metal1_extend_via1"] = 0.035 -# Reserved for asymmetric enclosures -drc["metal1_enclosure_via1"] = 0 -# Not a rule -drc["minarea_metal1"] = 0 +drc.add_enclosure("metal1", + layer = "via1", + enclosure = 0, + extension = 0.035) # VIA1.1 Minimum width of via1 -drc["minwidth_via1"] = 0.065 # 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 -drc["minwidth_metal2"] = 0.07 # 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 -drc["metal2_extend_via1"] = 0.035 -# Reserved for asymmetric enclosures -drc["metal2_enclosure_via1"] = 0 +drc.add_enclosure("metal2", + layer = "via1", + enclosure = 0, + extension = 0.035) + # METALINT.4 Minimum enclosure around via[2-3] on two opposite sides -drc["metal2_extend_via2"] = 0.035 -# Reserved for asymmetric enclosures -drc["metal2_enclosure_via2"] = 0 -# Not a rule -drc["minarea_metal2"] = 0 +drc.add_enclosure("metal2", + layer = "via2", + enclosure = 0, + extension = 0.035) # VIA2-3.1 Minimum width of Via[2-3] -drc["minwidth_via2"] = 0.065 # 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 -drc["minwidth_metal3"] = 0.07 # 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.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.9 & longer than 2.7 = 0.9 # 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, - (0.09, 0.3) : 0.09, - (0.27, 0.9) : 0.27, - (0.50, 1.8) : 0.5, - (0.90, 2.7) : 0.9, - (1.50, 4.0) : 1.5}) +drc.add_layer("metal3", + width = 0.07, + spacing = drc_lut({(0.00, 0.0) : 0.07, + (0.09, 0.3) : 0.09, + (0.27, 0.9) : 0.27, + (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 -drc["metal3_extend_via2"] = 0.035 -# Reserved for asymmetric enclosures -drc["metal3_enclosure_via2"] = 0 +drc.add_enclosure("metal3", + layer = "via2", + enclosure = 0, + extension = 0.035) + # METALINT.4 Minimum enclosure around via[2-3] on two opposite sides -drc["metal3_extend_via3"]=0.035 -# Reserved for asymmetric enclosures -drc["metal3_enclosure_via3"] = 0 -# Not a rule -drc["minarea_metal3"] = 0 +drc.add_enclosure("metal3", + layer = "via3", + enclosure = 0, + extension = 0.035) # VIA2-3.1 Minimum width of Via[2-3] -drc["minwidth_via3"] = 0.07 # 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 -drc["minwidth_metal4"] = 0.14 # 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.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 1.5 & longer than 4.0 = 1.5 -drc["metal4_to_metal4"] = drc_lut({(0.00, 0.0) : 0.14, - (0.27, 0.9) : 0.27, - (0.50, 1.8) : 0.5, - (0.90, 2.7) : 0.9, - (1.50, 4.0) : 1.5}) +drc.add_layer("metal4", + width = 0.14, + spacing = drc_lut({(0.00, 0.0) : 0.14, + (0.27, 0.9) : 0.27, + (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 -drc["metal4_extend_via3"] = 0.0025 -# Reserved for asymmetric enclosure -drc["metal4_enclosure_via3"] = 0.0025 -# Not a rule -drc["minarea_metal4"] = 0 +drc.add_enclosure("metal4", + layer = "via3", + enclosure = 0.0025) # Metal 5-10 are ommitted - - ################################################### -##END DRC/LVS Rules -################################################### - -################################################### -##Spice Simulation Parameters +# Spice Simulation Parameters ################################################### #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 ################################################### -##END Spice Simulation Parameters -################################################### - -################################################### -##BEGIN Technology Tool Preferences +# Technology Tool Preferences ################################################### drc_name = "calibre" @@ -359,7 +376,3 @@ lvs_name = "calibre" pex_name = "calibre" blackbox_bitcell = False - -################################################### -##END Technology Tool Preferences -################################################### diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 8e189efd..23a0d9fe 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -28,6 +28,27 @@ GDS["unit"]=(0.001,1e-6) # default label zoom 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 @@ -43,8 +64,8 @@ layer["active"] = (43, 0) layer["pimplant"] = (44, 0) layer["nimplant"] = (45, 0) layer["poly"] = (46, 0) -layer["active_contact"] = (48, 0) layer["poly_contact"] = (47, 0) +layer["active_contact"] = (48, 0) layer["metal1"] = (49, 0) layer["via1"] = (50, 0) layer["metal2"] = (51, 0) @@ -56,11 +77,7 @@ layer["text"] = (63, 0) layer["boundary"] = (63, 0) ################################################### -##END GDS Layer Map -################################################### - -################################################### -##DRC/LVS Rules Setup +# DRC/LVS Rules Setup ################################################### _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["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) drc["pwell_to_nwell"] = 0 +# 1.3 Minimum spacing between wells of same type (if both are drawn) # 1.1 Minimum width -drc["minwidth_well"] = 12*_lambda_ +drc.add_layer("well", + width = 12*_lambda_, + spacing = 6*_lambda_) # 3.1 Minimum width -drc["minwidth_poly"] = 2*_lambda_ # 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 drc["poly_extend_active"] = 2*_lambda_ # 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 # 3.5 Minimum field poly to active drc["poly_to_active"] = _lambda_ # 3.2.a Minimum spacing over field poly drc["poly_to_field_poly"] = 3*_lambda_ -# Not a rule -drc["minarea_poly"] = 0.0 # ?? drc["active_to_body_active"] = 4*_lambda_ # Fix me # 2.1 Minimum width -drc["minwidth_active"] = 3*_lambda_ # 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 -drc["well_enclosure_active"] = 6*_lambda_ -# Reserved for asymmetric enclosures -drc["well_extend_active"] = 6*_lambda_ -# Not a rule -drc["minarea_active"] = 0.0 +drc.add_enclosure("well", + layer = "active", + enclosure = 6*_lambda_) # 4.1 Minimum select spacing to channel of transistor to ensure adequate source/drain width drc["implant_to_channel"] = 3*_lambda_ # 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 -drc["implant_enclosure_contact"] = _lambda_ +drc.add_enclosure("implant", + layer = "contact", + enclosure = _lambda_) # Not a rule drc["implant_to_contact"] = 0 # Not a rule -drc["implant_to_implant"] = 0 -# Not a rule -drc["minwidth_implant"] = 0 +drc.add_layer("implant", + width = 0, + spacing = 0) # 6.1 Exact contact size -drc["minwidth_active_contact"] = 2*_lambda_ # 5.3 Minimum contact spacing -drc["active_contact_to_active_contact"] = 3*_lambda_ -# 6.2.b Minimum active overlap -drc["active_enclosure_active_contact"] = _lambda_ -# Reserved for asymmetric enclosure -drc["active_extend_active_contact"] = _lambda_ +drc.add_layer("active_contact", + width = 2*_lambda_, + spacing = 3*_lambda_) +# 6.2.b Minimum active overlap +drc.add_enclosure("active", + layer = "active_contact", + enclosure = _lambda_) +drc.add_enclosure("active", + layer = "contact", + enclosure = _lambda_) # 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 -drc["active_contact_to_poly"] = 2*_lambda_ +drc["contact_to_poly"] = 2*_lambda_ # 6.1 Exact contact size -drc["minwidth_poly_contact"] = 2*_lambda_ # 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 -drc["poly_enclosure_poly_contact"] = _lambda_ -# Reserved for asymmetric enclosures -drc["poly_extend_poly_contact"] = _lambda_ +drc.add_enclosure("poly", + layer = "poly_contact", + enclosure = _lambda_) # Reserved for other technologies drc["poly_contact_to_gate"] = 2*_lambda_ # 5.4 Minimum spacing to gate of transistor drc["poly_contact_to_poly"] = 2*_lambda_ # 7.1 Minimum width -drc["minwidth_metal1"] = 3*_lambda_ # 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 -drc["metal1_enclosure_active_contact"] = _lambda_ -# Reserved for asymmetric enclosure -drc["metal1_extend_active_contact"] = _lambda_ -# 7.3 Minimum overlap of any contact -drc["metal1_enclosure_poly_contact"] = _lambda_ -# Reserved for asymmetric enclosure -drc["metal1_extend_poly_contact"] = _lambda_ -# 8.3 Minimum overlap by metal1 -drc["metal1_enclosure_via1"] = _lambda_ -# Reserve for asymmetric enclosures -drc["metal1_extend_via1"] = _lambda_ -# Not a rule -drc["minarea_metal1"] = 0 +drc.add_enclosure("metal1", + layer = "poly_contact", + enclosure = _lambda_) +drc.add_enclosure("metal1", + layer = "active_contact", + enclosure = _lambda_) +# 8.3 Minimum overlap by metal1 +drc.add_enclosure("metal1", + layer = "via1", + enclosure = _lambda_) # 8.1 Exact size -drc["minwidth_via1"] = 2*_lambda_ # 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 -drc["minwidth_metal2"] = 3*_lambda_ # 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 -drc["metal2_extend_via1"] = _lambda_ -# Reserved for asymmetric enclosures -drc["metal2_enclosure_via1"] = _lambda_ +drc.add_enclosure("metal2", + layer = "via1", + enclosure = _lambda_) # 14.3 Minimum overlap by metal2 -drc["metal2_extend_via2"] = _lambda_ -# Reserved for asymmetric enclosures -drc["metal2_enclosure_via2"] = _lambda_ -# Not a rule -drc["minarea_metal2"] = 0 +drc.add_enclosure("metal2", + layer = "via2", + enclosure = _lambda_) # 14.1 Exact size -drc["minwidth_via2"] = 2*_lambda_ # 14.2 Minimum spacing -drc["via2_to_via2"] = 3*_lambda_ +drc.add_layer("via2", + width = 2*_lambda_, + spacing = 3*_lambda_) # 15.1 Minimum width -drc["minwidth_metal3"] = 3*_lambda_ # 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 -drc["metal3_extend_via2"] = _lambda_ -# Reserved for asymmetric enclosures -drc["metal3_enclosure_via2"] = _lambda_ +drc.add_enclosure("metal3", + layer = "via2", + enclosure = _lambda_) + # 21.3 Minimum overlap by metal3 -drc["metal3_extend_via3"] = _lambda_ -# Reserved for asymmetric enclosures -drc["metal3_enclosure_via3"] = _lambda_ -# Not a rule -drc["minarea_metal3"] = 0 +drc.add_enclosure("metal3", + layer = "via3", + enclosure = _lambda_) # 21.1 Exact size -drc["minwidth_via3"] = 2*_lambda_ # 21.2 Minimum spacing -drc["via3_to_via3"] = 3*_lambda_ +drc.add_layer("via3", + width = 2*_lambda_, + spacing = 3*_lambda_) # 22.1 Minimum width -drc["minwidth_metal4"] = 6*_lambda_ # 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 -drc["metal4_extend_via3"] = 2*_lambda_ -# Reserved for asymmetric enclosures -drc["metal4_enclosure_via3"] = 2*_lambda_ -# Not a rule -drc["minarea_metal4"] = 0 +drc.add_enclosure("metal4", + layer = "via3", + enclosure = 2*_lambda_) ################################################### -##END DRC/LVS Rules -################################################### - -################################################### -##Spice Simulation Parameters +# Spice Simulation Parameters ################################################### # 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 ################################################### -##END Spice Simulation Parameters -################################################### - -################################################### -##BEGIN Technology Tool Preferences +# Technology Tool Preferences ################################################### drc_name = "magic" @@ -323,7 +341,3 @@ lvs_name = "netgen" pex_name = "magic" blackbox_bitcell = False - -################################################### -##END Technology Tool Preferences -###################################################