mirror of https://github.com/VLSIDA/OpenRAM.git
Add design rules classes for complex design rules
This commit is contained in:
parent
1333329dd4
commit
4932d83afc
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
Loading…
Reference in New Issue