Clean up and generalize layer rules.

Convert metalN to mN.
Generalize helper constants in modules for
space, width, enclose, etc.
Use layer stacks whever possible.
Try to remove drc() calls in liu of helper constants.
This commit is contained in:
Matt Guthaus
2019-12-17 11:03:36 -08:00
parent a79d03fef4
commit ed28b4983b
52 changed files with 604 additions and 578 deletions
+9 -9
View File
@@ -104,11 +104,11 @@ class contact(hierarchy_design.hierarchy_design):
# The enclosure rule applies to symmetric enclosure component.
first_layer_minwidth = drc("minwidth_{0}".format(self.first_layer_name))
first_layer_enclosure = drc("{0}_enclosure_{1}".format(self.first_layer_name, self.via_layer_name))
first_layer_enclosure = drc("{0}_enclose_{1}".format(self.first_layer_name, self.via_layer_name))
first_layer_extend = drc("{0}_extend_{1}".format(self.first_layer_name, self.via_layer_name))
second_layer_minwidth = drc("minwidth_{0}".format(self.second_layer_name))
second_layer_enclosure = drc("{0}_enclosure_{1}".format(self.second_layer_name, self.via_layer_name))
second_layer_enclosure = drc("{0}_enclose_{1}".format(self.second_layer_name, self.via_layer_name))
second_layer_extend = drc("{0}_extend_{1}".format(self.second_layer_name, self.via_layer_name))
# In some technologies, the minimum width may be larger
@@ -204,16 +204,16 @@ class contact(hierarchy_design.hierarchy_design):
height=self.second_layer_height)
def create_implant_well_enclosures(self):
implant_position = self.first_layer_position - [drc("implant_enclosure_active")] * 2
implant_width = self.first_layer_width + 2 * drc("implant_enclosure_active")
implant_height = self.first_layer_height + 2 * drc("implant_enclosure_active")
implant_position = self.first_layer_position - [drc("implant_enclose_active")] * 2
implant_width = self.first_layer_width + 2 * drc("implant_enclose_active")
implant_height = self.first_layer_height + 2 * drc("implant_enclose_active")
self.add_rect(layer="{}implant".format(self.implant_type),
offset=implant_position,
width=implant_width,
height=implant_height)
well_position = self.first_layer_position - [drc("well_enclosure_active")] * 2
well_width = self.first_layer_width + 2 * drc("well_enclosure_active")
well_height = self.first_layer_height + 2 * drc("well_enclosure_active")
well_position = self.first_layer_position - [drc("well_enclose_active")] * 2
well_width = self.first_layer_width + 2 * drc("well_enclose_active")
well_height = self.first_layer_height + 2 * drc("well_enclose_active")
self.add_rect(layer="{}well".format(self.well_type),
offset=well_position,
width=well_width,
@@ -250,7 +250,7 @@ m1m2 = factory.create(module_type="contact",
m2m3 = factory.create(module_type="contact",
layer_stack=m2_stack,
directions=("V", "H"))
if "metal4" in layer.keys():
if "m4" in layer.keys():
m3m4 = factory.create(module_type="contact",
layer_stack=m3_stack,
directions=("H", "V"))
+57 -31
View File
@@ -8,7 +8,7 @@
from hierarchy_design import hierarchy_design
import contact
from globals import OPTS
import re
class design(hierarchy_design):
"""
@@ -32,7 +32,7 @@ class design(hierarchy_design):
self.m1_pitch = max(contact.m1m2.width, contact.m1m2.height) + max(self.m1_space, self.m2_space)
self.m2_pitch = max(contact.m2m3.width, contact.m2m3.height) + max(self.m2_space, self.m3_space)
if "metal4" in tech.layer:
if "m4" in tech.layer:
self.m3_pitch = max(contact.m3m4.width, contact.m3m4.height) + max(self.m3_space, self.m4_space)
else:
self.m3_pitch = self.m2_pitch
@@ -46,36 +46,62 @@ class design(hierarchy_design):
def setup_drc_constants(self):
""" These are some DRC constants used in many places in the compiler."""
from tech import drc, layer
self.well_width = drc("minwidth_well")
self.poly_width = drc("minwidth_poly")
self.poly_space = drc("poly_to_poly")
self.m1_width = drc("minwidth_metal1")
self.m1_space = drc("metal1_to_metal1")
self.m2_width = drc("minwidth_metal2")
self.m2_space = drc("metal2_to_metal2")
self.m3_width = drc("minwidth_metal3")
self.m3_space = drc("metal3_to_metal3")
if "metal4" in layer:
self.m4_width = drc("minwidth_metal4")
self.m4_space = drc("metal4_to_metal4")
self.active_width = drc("minwidth_active")
self.active_space = drc("active_to_body_active")
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")
if "contact" in layer:
self.poly_to_contact = drc("poly_to_contact")
else:
self.poly_to_contact = drc("poly_to_active_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")
# Make some local rules for convenience
for rule in drc.keys():
# Single layer width rules
match = re.search(r"minwidth_(.*)", rule)
if match:
if match.group(1)=="active_contact":
setattr(self, "contact_width", drc(match.group(0)))
else:
setattr(self, match.group(1)+"_width", drc(match.group(0)))
# Single layer area rules
match = re.search(r"minarea_(.*)", rule)
if match:
setattr(self, match.group(0), drc(match.group(0)))
# Single layer spacing rules
match = re.search(r"(.*)_to_(.*)", rule)
if match and match.group(1)==match.group(2):
setattr(self, match.group(1)+"_space", drc(match.group(0)))
elif match and match.group(1)!=match.group(2):
if match.group(2)=="poly_active":
setattr(self, match.group(1)+"_to_contact", drc(match.group(0)))
else:
setattr(self, match.group(0), drc(match.group(0)))
match = re.search(r"(.*)_enclose_(.*)", rule)
if match:
setattr(self, match.group(0), drc(match.group(0)))
match = re.search(r"(.*)_extend_(.*)", rule)
if match:
setattr(self, match.group(0), drc(match.group(0)))
# These are for debugging previous manual rules
# print("poly_width", self.poly_width)
# print("poly_space", self.poly_space)
# print("m1_width", self.m1_width)
# print("m1_space", self.m1_space)
# print("m2_width", self.m2_width)
# print("m2_space", self.m2_space)
# print("m3_width", self.m3_width)
# print("m3_space", self.m3_space)
# print("m4_width", self.m4_width)
# print("m4_space", self.m4_space)
# print("active_width", self.active_width)
# print("active_space", self.active_space)
# print("contact_width", self.contact_width)
# print("poly_to_active", self.poly_to_active)
# print("poly_extend_active", self.poly_extend_active)
# print("poly_to_contact", self.poly_to_contact)
# print("contact_to_gate", self.contact_to_gate)
# print("well_enclose_active", self.well_enclose_active)
# print("implant_enclose_active", self.implant_enclose_active)
# print("implant_space", self.implant_space)
def setup_multiport_constants(self):
"""
These are contants and lists that aid multiport design.
+27 -27
View File
@@ -61,7 +61,7 @@ class layout():
y_dir = 1
else:
# we lose a rail after every 2 gates
base_offset=vector(x_offset, (inv_num+1) * height - (inv_num%2)*drc["minwidth_metal1"])
base_offset=vector(x_offset, (inv_num+1) * height - (inv_num%2)*drc["minwidth_m1"])
y_dir = -1
return (base_offset,y_dir)
@@ -388,9 +388,9 @@ class layout():
def get_preferred_direction(self, layer):
""" Return the preferred routing directions """
if layer in ["metal1", "metal3", "metal5"]:
if layer in ["m1", "m3", "m5"]:
return "H"
elif layer in ["active", "poly", "metal2", "metal4"]:
elif layer in ["active", "poly", "m2", "m4"]:
return "V"
else:
return "N"
@@ -682,12 +682,12 @@ class layout():
return line_positions
def connect_horizontal_bus(self, mapping, inst, bus_offsets,
layer_stack=("metal1","via1","metal2")):
layer_stack=("m1", "via1", "m2")):
""" Horizontal version of connect_bus. """
self.connect_bus(mapping, inst, bus_offsets, layer_stack, True)
def connect_vertical_bus(self, mapping, inst, bus_offsets,
layer_stack=("metal1","via1","metal2")):
layer_stack=("m1", "via1", "m2")):
""" Vertical version of connect_bus. """
self.connect_bus(mapping, inst, bus_offsets, layer_stack, False)
@@ -734,15 +734,15 @@ class layout():
rotate=90)
def get_layer_pitch(self, layer):
""" Return the track pitch on a given layer """
if layer=="metal1":
if layer=="m1":
return (self.m1_pitch,self.m1_pitch-self.m1_space,self.m1_space)
elif layer=="metal2":
elif layer=="m2":
return (self.m2_pitch,self.m2_pitch-self.m2_space,self.m2_space)
elif layer=="metal3":
elif layer=="m3":
return (self.m3_pitch,self.m3_pitch-self.m3_space,self.m3_space)
elif layer=="metal4":
elif layer=="m4":
from tech import layer as tech_layer
if "metal4" in tech_layer:
if "m4" in tech_layer:
return (self.m3_pitch,self.m3_pitch-self.m4_space,self.m4_space)
else:
return (self.m3_pitch,self.m3_pitch-self.m3_space,self.m3_space)
@@ -1006,16 +1006,16 @@ class layout():
"""
pins=inst.get_pins(name)
for pin in pins:
if pin.layer=="metal3":
if pin.layer=="m3":
self.add_layout_pin(name, pin.layer, pin.ll(), pin.width(), pin.height())
elif pin.layer=="metal1":
elif pin.layer=="m1":
self.add_power_pin(name, pin.center())
else:
debug.warning("{0} pins of {1} should be on metal3 or metal1 for supply router.".format(name,inst.name))
def add_power_pin(self, name, loc, vertical=False, start_layer="metal1"):
def add_power_pin(self, name, loc, vertical=False, start_layer="m1"):
"""
Add a single power pin from M3 down to M1 at the given center location.
The starting layer is specified to determine which vias are needed.
@@ -1025,24 +1025,24 @@ class layout():
else:
direction=("H","H")
if start_layer=="metal1":
if start_layer=="m1":
self.add_via_center(layers=self.m1_stack,
offset=loc,
directions=direction)
if start_layer=="metal1" or start_layer=="metal2":
if start_layer=="m1" or start_layer=="m2":
via=self.add_via_center(layers=self.m2_stack,
offset=loc,
directions=direction)
if start_layer=="metal3":
if start_layer=="m3":
self.add_layout_pin_rect_center(text=name,
layer="metal3",
layer="m3",
offset=loc)
else:
self.add_layout_pin_rect_center(text=name,
layer="metal3",
layer="m3",
offset=loc,
width=via.width,
height=via.height)
@@ -1064,7 +1064,7 @@ class layout():
# LEFT vertical rails
offset = ll + vector(-2*self.supply_rail_pitch, -2*self.supply_rail_pitch)
left_gnd_pin=self.add_layout_pin(text="gnd",
layer="metal2",
layer="m2",
offset=offset,
width=self.supply_rail_width,
height=height)
@@ -1072,7 +1072,7 @@ class layout():
offset = ll + vector(-1*self.supply_rail_pitch, -1*self.supply_rail_pitch)
left_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal2",
layer="m2",
offset=offset,
width=self.supply_rail_width,
height=height)
@@ -1080,14 +1080,14 @@ class layout():
# RIGHT vertical rails
offset = vector(ur.x,ll.y) + vector(0,-2*self.supply_rail_pitch)
right_gnd_pin = self.add_layout_pin(text="gnd",
layer="metal2",
layer="m2",
offset=offset,
width=self.supply_rail_width,
height=height)
offset = vector(ur.x,ll.y) + vector(self.supply_rail_pitch,-1*self.supply_rail_pitch)
right_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal2",
layer="m2",
offset=offset,
width=self.supply_rail_width,
height=height)
@@ -1095,14 +1095,14 @@ class layout():
# BOTTOM horizontal rails
offset = ll + vector(-2*self.supply_rail_pitch, -2*self.supply_rail_pitch)
bottom_gnd_pin=self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=offset,
width=width,
height=self.supply_rail_width)
offset = ll + vector(-1*self.supply_rail_pitch, -1*self.supply_rail_pitch)
bottom_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=offset,
width=width,
height=self.supply_rail_width)
@@ -1110,14 +1110,14 @@ class layout():
# TOP horizontal rails
offset = vector(ll.x, ur.y) + vector(-2*self.supply_rail_pitch,0)
top_gnd_pin=self.add_layout_pin(text="gnd",
layer="metal1",
layer="m1",
offset=offset,
width=width,
height=self.supply_rail_width)
offset = vector(ll.x, ur.y) + vector(-1*self.supply_rail_pitch, self.supply_rail_pitch)
top_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal1",
layer="m1",
offset=offset,
width=width,
height=self.supply_rail_width)
@@ -1139,7 +1139,7 @@ class layout():
from sram_factory import factory
while True:
c=factory.create(module_type="contact",
layer_stack=("metal1","via1","metal2"),
layer_stack=self.m1_stack,
dimensions=(self.supply_vias, self.supply_vias))
if c.second_layer_width < self.supply_rail_width and c.second_layer_height < self.supply_rail_width:
self.supply_vias += 1