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

View File

@ -10,6 +10,7 @@ import contact
from globals import OPTS from globals import OPTS
import re import re
class design(hierarchy_design): class design(hierarchy_design):
""" """
This is the same as the hierarchy_design class except it contains 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_layer_constants()
self.setup_multiport_constants() self.setup_multiport_constants()
def setup_layer_constants(self): 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 import tech
self.m1_pitch = max(contact.m1m2.width, contact.m1m2.height) + max(self.m1_space, self.m2_space) # This is contact direction independent pitch,
self.m2_pitch = max(contact.m2m3.width, contact.m2m3.height) + max(self.m2_space, self.m3_space) # 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: 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: else:
self.m3_pitch = self.m2_pitch self.m3_pitch = self.m2_pitch
@ -44,15 +52,17 @@ class design(hierarchy_design):
self.m3_stack = tech.m3_stack self.m3_stack = tech.m3_stack
def setup_drc_constants(self): 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 # Make some local rules for convenience
from tech import drc
for rule in drc.keys(): for rule in drc.keys():
# Single layer width rules # Single layer width rules
match = re.search(r"minwidth_(.*)", rule) match = re.search(r"minwidth_(.*)", rule)
if match: if match:
if match.group(1)=="active_contact": if match.group(1) == "active_contact":
setattr(self, "contact_width", drc(match.group(0))) setattr(self, "contact_width", drc(match.group(0)))
else: else:
setattr(self, match.group(1)+"_width", drc(match.group(0))) setattr(self, match.group(1)+"_width", drc(match.group(0)))
@ -64,11 +74,12 @@ class design(hierarchy_design):
# Single layer spacing rules # Single layer spacing rules
match = re.search(r"(.*)_to_(.*)", rule) 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))) setattr(self, match.group(1)+"_space", drc(match.group(0)))
elif match and match.group(1)!=match.group(2): elif match and match.group(1) != match.group(2):
if match.group(2)=="poly_active": if match.group(2) == "poly_active":
setattr(self, match.group(1)+"_to_contact", drc(match.group(0))) setattr(self, match.group(1)+"_to_contact",
drc(match.group(0)))
else: else:
setattr(self, match.group(0), drc(match.group(0))) 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("well_enclose_active", self.well_enclose_active)
print("implant_enclose_active", self.implant_enclose_active) print("implant_enclose_active", self.implant_enclose_active)
print("implant_space", self.implant_space) print("implant_space", self.implant_space)
import sys; sys.exit(1) import sys
sys.exit(1)
def setup_multiport_constants(self): def setup_multiport_constants(self):
""" """

View File

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