This commit is contained in:
Matthew Guthaus 2019-12-17 23:07:01 +00:00
parent 449b0a7c28
commit fc4685c7f7
3 changed files with 57 additions and 41 deletions

View File

@ -7,8 +7,10 @@
#
import hierarchy_design
import debug
from tech import *
from tech import drc
import tech
from vector import vector
from sram_factory import factory
class contact(hierarchy_design.hierarchy_design):
@ -65,7 +67,8 @@ class contact(hierarchy_design.hierarchy_design):
if self.implant_type and self.well_type:
self.create_implant_well_enclosures()
elif self.implant_type or self.well_type:
debug.error(-1, "Must define both implant and well type or none at all.")
debug.error(-1,
"Must define both implant and well type or none.")
def setup_layers(self):
""" Locally assign the layer names. """
@ -75,7 +78,7 @@ class contact(hierarchy_design.hierarchy_design):
self.second_layer_name = second_layer
# Contacts will have unique per first layer
if via_layer in layer.keys():
if via_layer in tech.layer.keys():
self.via_layer_name = via_layer
elif via_layer == "contact":
if first_layer in ("active", "poly"):
@ -86,8 +89,6 @@ class contact(hierarchy_design.hierarchy_design):
debug.error("Invalid via layer {}".format(via_layer), -1)
else:
debug.error("Invalid via layer {}".format(via_layer), -1)
def setup_layout_constants(self):
""" Determine the design rules for the enclosure layers """
@ -127,7 +128,9 @@ class contact(hierarchy_design.hierarchy_design):
else:
debug.error("Invalid first layer direction.", -1)
# In some technologies, the minimum width may be larger than the overlap requirement around the via, so
# In some technologies,
# the minimum width may be larger than
# the overlap requirement around the via, so
# check this for each dimension.
if self.directions[1] == "V":
self.second_layer_horizontal_enclosure = max(second_layer_enclosure,
@ -146,11 +149,14 @@ class contact(hierarchy_design.hierarchy_design):
""" Create the contact array at the origin"""
# offset for the via array
self.via_layer_position = vector(
max(self.first_layer_horizontal_enclosure, self.second_layer_horizontal_enclosure),
max(self.first_layer_vertical_enclosure, self.second_layer_vertical_enclosure))
max(self.first_layer_horizontal_enclosure,
self.second_layer_horizontal_enclosure),
max(self.first_layer_vertical_enclosure,
self.second_layer_vertical_enclosure))
for i in range(self.dimensions[1]):
offset = self.via_layer_position + vector(0, self.contact_pitch * i)
offset = self.via_layer_position + vector(0,
self.contact_pitch * i)
for j in range(self.dimensions[0]):
self.add_rect(layer=self.via_layer_name,
offset=offset,
@ -161,7 +167,7 @@ class contact(hierarchy_design.hierarchy_design):
def create_nitride_cut_enclosure(self):
""" Special layer that encloses poly contacts in some processes """
# Check if there is a special poly nitride cut layer
if "npc" not in layer.keys():
if "npc" not in tech.layer.keys():
return
# Only add for poly layers
@ -175,7 +181,6 @@ class contact(hierarchy_design.hierarchy_design):
offset=self.second_layer_position,
width=self.second_layer_width,
height=self.second_layer_height)
def create_first_layer_enclosure(self):
# this is if the first and second layers are different
@ -224,35 +229,33 @@ class contact(hierarchy_design.hierarchy_design):
return self.return_power()
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_stack,
layer_stack=tech.active_stack,
directions=("H", "V"))
active = factory.create(module_type="contact",
layer_stack=active_stack,
layer_stack=tech.active_stack,
directions=("H", "V"))
poly = factory.create(module_type="contact",
layer_stack=poly_stack,
layer_stack=tech.poly_stack,
directions=("V", "H"))
if "li" in layer.keys():
if "li" in tech.layer.keys():
lim1 = factory.create(module_type="contact",
layer_stack=li_stack,
layer_stack=tech.li_stack,
directions=("V", "H"))
else:
lim1 = None
m1m2 = factory.create(module_type="contact",
layer_stack=m1_stack,
layer_stack=tech.m1_stack,
directions=("H", "V"))
m2m3 = factory.create(module_type="contact",
layer_stack=m2_stack,
layer_stack=tech.m2_stack,
directions=("V", "H"))
if "m4" in layer.keys():
if "m4" in tech.layer.keys():
m3m4 = factory.create(module_type="contact",
layer_stack=m3_stack,
layer_stack=tech.m3_stack,
directions=("H", "V"))
else:
m3m4 = None

View File

@ -10,6 +10,7 @@ import contact
from globals import OPTS
import re
class design(hierarchy_design):
"""
This is the same as the hierarchy_design class except it contains
@ -24,16 +25,23 @@ class design(hierarchy_design):
self.setup_layer_constants()
self.setup_multiport_constants()
def setup_layer_constants(self):
""" These are some layer constants used in many places in the compiler."""
"""
These are some layer constants used
in many places in the compiler.
"""
import tech
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)
# This is contact direction independent pitch,
# i.e. we take the maximum contact dimension
max_m1m2_contact = max(contact.m1m2.width, contact.m1m2.height)
self.m1_pitch = max_m1m2_contact + max(self.m1_space, self.m2_space)
max_m2m3_contact = max(contact.m2m3.width, contact.m2m3.height)
self.m2_pitch = max_m2m3_contact + max(self.m2_space, self.m3_space)
if "m4" in tech.layer:
self.m3_pitch = max(contact.m3m4.width, contact.m3m4.height) + max(self.m3_space, self.m4_space)
max_m3m4_contact = max(contact.m3m4.width, contact.m3m4.height)
self.m3_pitch = max_m3m4_contact + max(self.m3_space, self.m4_space)
else:
self.m3_pitch = self.m2_pitch
@ -44,15 +52,17 @@ class design(hierarchy_design):
self.m3_stack = tech.m3_stack
def setup_drc_constants(self):
""" These are some DRC constants used in many places in the compiler."""
from tech import drc, layer
"""
These are some DRC constants used in many places
in the compiler.
"""
# Make some local rules for convenience
from tech import drc
for rule in drc.keys():
# Single layer width rules
match = re.search(r"minwidth_(.*)", rule)
if match:
if match.group(1)=="active_contact":
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)))
@ -64,11 +74,12 @@ class design(hierarchy_design):
# Single layer spacing rules
match = re.search(r"(.*)_to_(.*)", rule)
if match and match.group(1)==match.group(2):
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)))
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)))
@ -102,7 +113,8 @@ class design(hierarchy_design):
print("well_enclose_active", self.well_enclose_active)
print("implant_enclose_active", self.implant_enclose_active)
print("implant_space", self.implant_space)
import sys; sys.exit(1)
import sys
sys.exit(1)
def setup_multiport_constants(self):
"""

View File

@ -8,11 +8,11 @@
#
import unittest
from testutils import *
import sys,os
import sys
import os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
import debug
class wire_test(openram_test):
@ -31,7 +31,8 @@ class wire_test(openram_test):
layer_stack = stack[::-1]
else:
layer_stack = stack
# Just make a conservative spacing. Make it wire pitch instead?
min_space = 2 * (tech.drc["minwidth_{}".format(layer_stack[0])] +
tech.drc["minwidth_{}".format(layer_stack[2])])