Add design rules classes for complex design rules

This commit is contained in:
Matt Guthaus 2018-10-12 09:44:36 -07:00
parent 1333329dd4
commit 4932d83afc
12 changed files with 150 additions and 35 deletions

View File

@ -33,7 +33,7 @@ class design(hierarchy_design):
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.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"]

View File

@ -0,0 +1,35 @@
from drc_value import *
from drc_lut import *
class design_rules():
"""
This is a class that implements the design rules structures.
"""
def __init__(self, name):
self.tech_name = name
self.rules = {}
def add(self, name, value):
self.rules[name] = value
def __call__(self, name, *args):
return self.rules[name](args)
def __setitem__(self, b, c):
"""
For backward compatibility with existing rules.
"""
self.rules[b] = c
def __getitem__(self, b):
"""
For backward compatibility with existing rules.
"""
rule = self.rules[b]
if callable(rule):
return rule()
else:
return rule

40
compiler/drc/drc_lut.py Normal file
View File

@ -0,0 +1,40 @@
class drc_lut():
"""
Implement a lookup table of rules.
Each element is a tuple with the last value being the rule.
It searches through backwards until all of the key values are
met and returns the rule value.
For exampe, the key values can be width and length,
and it would return the rule for a wire of a given width and length.
A key can be not compared by passing a None.
"""
def __init__(self, table):
self.table = table
def __call__(self, *args):
"""
Lookup a given tuple in the table.
"""
key_tuple = args
if not key_tuple:
key_size = len(list(self.table.keys())[0])
key_tuple = tuple(0 for i in range(key_size))
for key in sorted(self.table.keys(), reverse=True):
if self.match(key_tuple, key):
return self.table[key]
def match(self, t1, t2):
"""
Determine if t1>t2 for each tuple pair.
"""
# If any one pair is less than, return False
for i in range(len(t1)):
if t1[i] < t2[i]:
return False
return True

17
compiler/drc/drc_value.py Normal file
View File

@ -0,0 +1,17 @@
class drc_value():
"""
A single DRC value.
"""
def __init__(self, value):
self.value = value
def __call__(self, *args):
"""
Return the value.
"""
return self.value

View File

@ -287,7 +287,8 @@ def setup_paths():
# Add all of the subdirs to the python path
# These subdirs are modules and don't need to be added: characterizer, verify
for subdir in ["gdsMill", "tests", "modules", "base", "pgates", "bitcells", "router"]:
subdirlist = [ item for item in os.listdir(OPENRAM_HOME) if os.path.isdir(os.path.join(OPENRAM_HOME, item)) ]
for subdir in subdirlist:
full_path = "{0}/{1}".format(OPENRAM_HOME,subdir)
debug.check(os.path.isdir(full_path),
"$OPENRAM_HOME/{0} does not exist: {1}".format(subdir,full_path))

View File

@ -1,7 +1,7 @@
import contact
import design
import debug
from tech import drc, parameter, spice, info
from tech import drc, parameter, spice
from ptx import ptx
from vector import vector
from globals import OPTS
@ -110,7 +110,7 @@ class pgate(design.design):
max_y_offset = self.height + 0.5*self.m1_width
self.nwell_position = middle_position
nwell_height = max_y_offset - middle_position.y
if info["has_nwell"]:
if drc["has_nwell"]:
self.add_rect(layer="nwell",
offset=middle_position,
width=self.well_width,
@ -122,7 +122,7 @@ class pgate(design.design):
pwell_position = vector(0,-0.5*self.m1_width)
pwell_height = middle_position.y-pwell_position.y
if info["has_pwell"]:
if drc["has_pwell"]:
self.add_rect(layer="pwell",
offset=pwell_position,
width=self.well_width,

View File

@ -1,7 +1,7 @@
import contact
import pgate
import debug
from tech import drc, parameter, spice, info
from tech import drc, parameter, spice
from ptx import ptx
from vector import vector
from math import ceil

View File

@ -1,6 +1,6 @@
import design
import debug
from tech import drc, info, spice
from tech import drc, spice
from vector import vector
from contact import contact
from globals import OPTS
@ -129,7 +129,7 @@ class ptx(design.design):
self.active_offset = vector([self.well_enclose_active]*2)
# Well enclosure of active, ensure minwidth as well
if info["has_{}well".format(self.well_type)]:
if drc["has_{}well".format(self.well_type)]:
self.cell_well_width = max(self.active_width + 2*self.well_enclose_active,
self.well_width)
self.cell_well_height = max(self.tx_width + 2*self.well_enclose_active,
@ -280,7 +280,7 @@ class ptx(design.design):
"""
Add an (optional) well and implant for the type of transistor.
"""
if info["has_{}well".format(self.well_type)]:
if drc["has_{}well".format(self.well_type)]:
self.add_rect(layer="{}well".format(self.well_type),
offset=(0,0),
width=self.cell_well_width,

View File

@ -1,6 +1,6 @@
import design
import debug
from tech import drc, info
from tech import drc
from vector import vector
import contact
from ptx import ptx

View File

@ -1,15 +1,10 @@
import os
from design_rules import *
"""
File containing the process technology parameters for FreePDK 45nm.
"""
info = {}
info["name"] = "freepdk45"
info["body_tie_down"] = 0
info["has_pwell"] = True
info["has_nwell"] = True
#GDS file info
GDS = {}
# gds units
@ -72,7 +67,13 @@ parameter["min_tx_size"] = 0.09
parameter["beta"] = 3
drclvs_home=os.environ.get("DRCLVS_HOME")
drc={}
drc = design_rules("freepdk45")
drc["body_tie_down"] = 0
drc["has_pwell"] = True
drc["has_nwell"] = True
#grid size
drc["grid"] = 0.0025
@ -83,7 +84,7 @@ drc["xrc_rules"]=drclvs_home+"/calibrexRC.rul"
drc["layer_map"]=os.environ.get("OPENRAM_TECH")+"/freepdk45/layers.map"
# minwidth_tx with contact (no dog bone transistors)
drc["minwidth_tx"]=0.09
drc["minwidth_tx"] = 0.09
drc["minlength_channel"] = 0.05
# WELL.2 Minimum spacing of nwell/pwell at different potential
@ -196,7 +197,18 @@ drc["via2_to_via2"] = 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
#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})
# METALINT.3 Minimum enclosure around via1 on two opposite sides
drc["metal3_extend_via2"] = 0.035
# Reserved for asymmetric enclosures
@ -216,7 +228,16 @@ drc["via3_to_via3"] = 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
#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})
# METALSMG.3 Minimum enclosure around via[3-6] on two opposite sides
drc["metal4_extend_via3"] = 0.0025
# Reserved for asymmetric enclosure

View File

@ -1,15 +1,10 @@
import os
from design_rules import *
"""
File containing the process technology parameters for SCMOS 3me, subm, 180nm.
"""
info={}
info["name"]="scn3me_subm"
info["body_tie_down"] = 0
info["has_pwell"] = True
info["has_nwell"] = True
#GDS file info
GDS={}
# gds units
@ -59,7 +54,13 @@ parameter["beta"] = 2
drclvs_home=os.environ.get("DRCLVS_HOME")
drc={}
drc = design_rules("scn3me_subm")
drc["body_tie_down"] = 0
drc["has_pwell"] = True
drc["has_nwell"] = True
#grid size is 1/2 a lambda
drc["grid"]=0.5*_lambda_
#DRC/LVS test set_up

View File

@ -1,15 +1,10 @@
import os
from design_rules import *
"""
File containing the process technology parameters for SCMOS 3me, subm, 180nm.
"""
info={}
info["name"]="scn3me_subm"
info["body_tie_down"] = 0
info["has_pwell"] = True
info["has_nwell"] = True
#GDS file info
GDS={}
# gds units
@ -61,14 +56,19 @@ parameter["beta"] = 2
drclvs_home=os.environ.get("DRCLVS_HOME")
drc={}
drc = design_rules("scn4me_sub")
drc["body_tie_down"] = 0
drc["has_pwell"] = True
drc["has_nwell"] = True
#grid size is 1/2 a lambda
drc["grid"]=0.5*_lambda_
#DRC/LVS test set_up
drc["drc_rules"]=drclvs_home+"/calibreDRC_scn3me_subm.rul"
drc["lvs_rules"]=drclvs_home+"/calibreLVS_scn3me_subm.rul"
drc["layer_map"]=os.environ.get("OPENRAM_TECH")+"/scn3me_subm/layers.map"
# minwidth_tx with contact (no dog bone transistors)
drc["minwidth_tx"] = 4*_lambda_