Updates to gdsMill/tech layers

Create active and poly contact types.
Define standard cell boundary option.
DataType and PurposeLayer are the same. Text must have type 0.
Remove vector from vlsiLayout. More debug in reader.
This commit is contained in:
Matt Guthaus 2019-12-04 16:12:53 -08:00
parent 0d35941241
commit 69bb245f28
13 changed files with 148 additions and 82 deletions

View File

@ -48,7 +48,8 @@ class contact(hierarchy_design.hierarchy_design):
# Module does not have pins, but has empty pin list.
self.pins = []
self.create_layout()
self.add_boundary()
def create_layout(self):
self.setup_layers()
@ -71,14 +72,11 @@ class contact(hierarchy_design.hierarchy_design):
(first_layer, via_layer, second_layer) = self.layer_stack
self.first_layer_name = first_layer
self.via_layer_name = via_layer
# Some technologies have a separate active
# contact from the poly contact
# We will use contact for DRC, but active_contact for output
if first_layer == "active" or second_layer == "active":
self.via_layer_name_expanded = "active_" + via_layer
# Contacts will have unique per first layer
if via_layer == "contact":
self.via_layer_name = first_layer + "_" + via_layer
else:
self.via_layer_name_expanded = via_layer
self.via_layer_name = via_layer
self.second_layer_name = second_layer
def setup_layout_constants(self):
@ -144,7 +142,7 @@ class contact(hierarchy_design.hierarchy_design):
for i in range(self.dimensions[1]):
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_expanded,
self.add_rect(layer=self.via_layer_name,
offset=offset,
width=self.contact_width,
height=self.contact_width)

View File

@ -48,12 +48,12 @@ class design(hierarchy_design):
self.m4_space = drc("metal4_to_metal4")
self.active_width = drc("minwidth_active")
self.active_space = drc("active_to_body_active")
self.contact_width = drc("minwidth_contact")
self.contact_width = drc("minwidth_active_contact")
self.poly_to_active = drc("poly_to_active")
self.poly_extend_active = drc("poly_extend_active")
self.poly_to_polycontact = drc("poly_to_polycontact")
self.contact_to_gate = drc("contact_to_gate")
self.poly_to_poly_contact = drc("poly_to_poly_contact")
self.active_contact_to_gate = drc("active_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")

View File

@ -193,7 +193,7 @@ class instance(geometry):
blockages = []
blockages = self.mod.gds.getBlockages(lpp)
for b in blockages:
new_blockages.append(self.transform_coords(b,self.offset, mirr, angle))
new_blockages.append(self.transform_coords(vector(b),self.offset, mirr, angle))
else:
blockages = self.mod.get_blockages(lpp)
for b in blockages:
@ -327,7 +327,6 @@ class label(geometry):
debug.info(4, "writing label (" + str(self.layerNumber) + "): " + self.text)
new_layout.addText(text=self.text,
layerNumber=self.layerNumber,
purposeNumber=self.layerPurpose,
offsetInMicrons=self.offset,
magnification=self.zoom,
rotate=None)

View File

@ -939,7 +939,11 @@ class layout():
def add_boundary(self, offset=vector(0,0)):
""" Add boundary for debugging dimensions """
self.add_rect(layer="boundary",
if "stdc" in techlayer.keys():
boundary_layer = "stdc"
else:
boundary_layer = "boundary"
self.add_rect(layer=boundary_layer,
offset=offset,
height=self.height,
width=self.width)

View File

@ -344,7 +344,6 @@ class pin_layout:
# imported into Magic.
newLayout.addText(text=self.name,
layerNumber=layer_num,
purposeNumber=purpose,
offsetInMicrons=self.center(),
magnification=GDS["zoom"],
rotate=None)

View File

@ -243,7 +243,7 @@ class pbitcell(bitcell_base.bitcell_base):
(self.inverter_nmos.active_contact.height - self.inverter_nmos.active_height)
self.inverter_gap = max(self.poly_to_active,
self.m1_space + inverter_nmos_contact_extension) \
+ self.poly_to_polycontact + 2 * contact.poly.width \
+ self.poly_to_poly_contact + 2 * contact.poly.width \
+ self.m1_space + inverter_pmos_contact_extension
self.cross_couple_lower_ypos = self.inverter_nmos_ypos \
+ self.inverter_nmos.active_height \
@ -254,7 +254,7 @@ class pbitcell(bitcell_base.bitcell_base):
+ self.inverter_nmos.active_height \
+ max(self.poly_to_active,
self.m1_space + inverter_nmos_contact_extension) \
+ self.poly_to_polycontact \
+ self.poly_to_poly_contact \
+ 1.5 * contact.poly.width
# spacing between wordlines (and gnd)
@ -926,14 +926,14 @@ class pbitcell(bitcell_base.bitcell_base):
"""
# add poly to metal1 contacts for gates of the inverters
left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x \
- self.poly_to_polycontact - 0.5*contact.poly.width,
- self.poly_to_poly_contact - 0.5*contact.poly.width,
self.cross_couple_upper_ypos)
self.add_via_center(layers=("poly", "contact", "metal1"),
offset=left_storage_contact,
directions=("H", "H"))
right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x \
+ self.poly_to_polycontact + 0.5*contact.poly.width,
+ self.poly_to_poly_contact + 0.5*contact.poly.width,
self.cross_couple_upper_ypos)
self.add_via_center(layers=("poly", "contact", "metal1"),
offset=right_storage_contact,

View File

@ -175,6 +175,8 @@ class Gds2reader:
def readBoundary(self):
##reads in a boundary type structure = a filled polygon
if(self.debugToTerminal==1):
print("\t\t\tBeginBoundary")
thisBoundary=GdsBoundary()
while 1:
record = self.readNextRecord()
@ -201,11 +203,6 @@ class Gds2reader:
thisBoundary.purposeLayer=purposeLayer
if(self.debugToTerminal==1):
print("\t\tPurpose Layer: "+str(purposeLayer))
elif(idBits==b'\x0E\x02'): #DataType
dataType = struct.unpack(">h",record[2:4])[0]
thisBoundary.dataType=dataType
if(self.debugToTerminal==1):
print("\t\t\tData Type: "+str(dataType))
elif(idBits==b'\x10\x03'): #XY Data Points
numDataPoints = len(record)-2 #packed as XY coordinates 4 bytes each
thisBoundary.coordinates=[]
@ -216,10 +213,15 @@ class Gds2reader:
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndBoundary")
break;
return thisBoundary
def readPath(self): #reads in a path structure
if(self.debugToTerminal==1):
print("\t\t\tBeginPath")
thisPath=GdsPath()
while 1:
record = self.readNextRecord()
@ -266,10 +268,15 @@ class Gds2reader:
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndPath")
break;
return thisPath
def readSref(self): #reads in a reference to another structure
if(self.debugToTerminal==1):
print("\t\t\tBeginSref")
thisSref=GdsSref()
while 1:
record = self.readNextRecord()
@ -317,10 +324,15 @@ class Gds2reader:
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndSref")
break;
return thisSref
def readAref(self): #an array of references
if(self.debugToTerminal==1):
print("\t\t\tBeginAref")
thisAref = GdsAref()
while 1:
record = self.readNextRecord()
@ -372,11 +384,15 @@ class Gds2reader:
print("\t\t\t\tArray Width: "+str(rightMostX-topLeftX))
print("\t\t\t\tArray Height: "+str(topLeftY-bottomMostY))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndAref")
break;
return thisAref
def readText(self):
##reads in a text structure
if(self.debugToTerminal==1):
print("\t\t\tBeginText")
thisText=GdsText()
while 1:
record = self.readNextRecord()
@ -472,10 +488,15 @@ class Gds2reader:
if(self.debugToTerminal==1):
print("\t\t\tText String: "+textString)
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndText")
break;
return thisText
def readNode(self):
if(self.debugToTerminal==1):
print("\t\t\tBeginNode")
##reads in a node type structure = an electrical net
thisNode = GdsNode()
while 1:
@ -513,10 +534,15 @@ class Gds2reader:
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndNode")
break;
return thisNode
def readBox(self):
if(self.debugToTerminal==1):
print("\t\t\tBeginBox")
##reads in a gds BOX structure
thisBox = GdsBox()
while 1:
@ -559,6 +585,8 @@ class Gds2reader:
if(self.debugToTerminal==1):
print("\t\t\tXY Point: "+str(x)+","+str(y))
elif(idBits==b'\x11\x00'): #End Of Element
if(self.debugToTerminal==1):
print("\t\t\tEndBox")
break;
return thisBox
@ -566,6 +594,7 @@ class Gds2reader:
thisStructure = GdsStructure()
record = self.readNextRecord()
idBits = record[0:2]
# Begin structure
if(idBits==b'\x05\x02' and len(record)==26):
createYear = struct.unpack(">h",record[2:4])[0]
createMonth = struct.unpack(">h",record[4:6])[0]
@ -581,6 +610,10 @@ class Gds2reader:
modSecond = struct.unpack(">h",record[24:26])[0]
thisStructure.createDate=(createYear,createMonth,createDay,createHour,createMinute,createSecond)
thisStructure.modDate=(modYear,modMonth,modDay,modHour,modMinute,modSecond)
if(self.debugToTerminal==1):
print("Date Created:"+str(createYear)+","+str(createMonth)+","+str(createDay)+\
","+str(createHour)+","+str(createMinute)+","+str(createSecond))
print("Date Modified:"+str(modYear)+","+str(modMonth)+","+str(modDay)+","+str(modHour)+","+str(modMinute)+","+str(modSecond))
else:
#means we have hit the last structure, so return the record
#to whoever called us to do something with it

View File

@ -187,27 +187,25 @@ class Gds2writer:
idBits=b'\x08\x00' #record Type
self.writeRecord(idBits)
if(thisBoundary.elementFlags!=""):
idBits=b'\x26\x01' #ELFLAGS
idBits=b'\x26\x01' # ELFLAGS
elementFlags = struct.pack(">h",thisBoundary.elementFlags)
self.writeRecord(idBits+elementFlags)
if(thisBoundary.plex!=""):
idBits=b'\x2F\x03' #PLEX
idBits=b'\x2F\x03' # PLEX
plex = struct.pack(">i",thisBoundary.plex)
self.writeRecord(idBits+plex)
if(thisBoundary.drawingLayer!=""):
idBits=b'\x0D\x02' #drawig layer
idBits=b'\x0D\x02' # drawing layer
drawingLayer = struct.pack(">h",thisBoundary.drawingLayer)
self.writeRecord(idBits+drawingLayer)
if(thisBoundary.purposeLayer):
idBits=b'\x16\x02' #purpose layer
purposeLayer = struct.pack(">h",thisBoundary.purposeLayer)
self.writeRecord(idBits+purposeLayer)
if(thisBoundary.dataType!=""):
idBits=b'\x0E\x02'#DataType
dataType = struct.pack(">h",thisBoundary.dataType)
if(thisBoundary.purposeLayer!=""):
idBits=b'\x0E\x02' # DataType
if type(thisBoundary.purposeLayer)!=int:
import pdb; pdb.set_trace()
dataType = struct.pack(">h",thisBoundary.purposeLayer)
self.writeRecord(idBits+dataType)
if(thisBoundary.coordinates!=""):
idBits=b'\x10\x03' #XY Data Points
idBits=b'\x10\x03' # XY Data Points
coordinateRecord = idBits
for coordinate in thisBoundary.coordinates:
x=struct.pack(">i",int(coordinate[0]))
@ -377,9 +375,9 @@ class Gds2writer:
idBits=b'\x0D\x02' #drawing layer
drawingLayer = struct.pack(">h",thisText.drawingLayer)
self.writeRecord(idBits+drawingLayer)
#if(thisText.purposeLayer):
# TextType is always a 0 per GDS specification
idBits=b'\x16\x02' #purpose layer
purposeLayer = struct.pack(">h",thisText.purposeLayer)
purposeLayer = struct.pack(">h",0)
self.writeRecord(idBits+purposeLayer)
if(thisText.transFlags != ""):
idBits=b'\x1A\x01'

View File

@ -21,8 +21,7 @@ class GdsBoundary:
self.elementFlags=""
self.plex=""
self.drawingLayer=""
self.purposeLayer = None
self.dataType=""
self.purposeLayer=0
self.coordinates=""
class GdsPath:
@ -31,7 +30,7 @@ class GdsPath:
self.elementFlags=""
self.plex=""
self.drawingLayer=""
self.purposeLayer = None
self.purposeLayer=0
self.pathType=""
self.pathWidth=""
self.coordinates=""
@ -140,7 +139,7 @@ class GdsText:
self.elementFlags=""
self.plex=""
self.drawingLayer=""
self.purposeLayer = None
self.purposeLayer=0
self.transFlags=[0,0,0]
self.magFactor=""
self.rotateAngle=""
@ -165,6 +164,6 @@ class GdsBox:
self.elementFlags=""
self.plex=""
self.drawingLayer=""
self.purposeLayer = None
self.purposeLayer=0
self.boxValue=""
self.coordinates=""

View File

@ -2,7 +2,6 @@ from .gdsPrimitives import *
from datetime import *
#from mpmath import matrix
#from numpy import matrix
from vector import vector
import numpy as np
#import gdsPrimitives
import debug
@ -358,7 +357,7 @@ class VlsiLayout:
#add the sref to the root structure
self.structures[self.rootStructureName].srefs.append(layoutToAddSref)
def addBox(self,layerNumber=0, purposeNumber=None, offsetInMicrons=(0,0), width=1.0, height=1.0,center=False):
def addBox(self,layerNumber=0, purposeNumber=0, offsetInMicrons=(0,0), width=1.0, height=1.0,center=False):
"""
Method to add a box to a layout
"""
@ -383,13 +382,12 @@ class VlsiLayout:
boundaryToAdd = GdsBoundary()
boundaryToAdd.drawingLayer = layerNumber
boundaryToAdd.dataType = 0
boundaryToAdd.coordinates = coordinates
boundaryToAdd.purposeLayer = purposeNumber
#add the sref to the root structure
self.structures[self.rootStructureName].boundaries.append(boundaryToAdd)
def addPath(self, layerNumber=0, purposeNumber=None, coordinates=[(0,0)], width=1.0):
def addPath(self, layerNumber=0, purposeNumber=0, coordinates=[(0,0)], width=1.0):
"""
Method to add a path to a layout
"""
@ -408,12 +406,10 @@ class VlsiLayout:
#add the sref to the root structure
self.structures[self.rootStructureName].paths.append(pathToAdd)
def addText(self, text, layerNumber=0, purposeNumber=None, offsetInMicrons=(0,0), magnification=0.1, rotate = None):
def addText(self, text, layerNumber=0, offsetInMicrons=(0,0), magnification=0.1, rotate = None):
offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1]))
textToAdd = GdsText()
textToAdd.drawingLayer = layerNumber
textToAdd.purposeLayer = purposeNumber
textToAdd.dataType = 0
textToAdd.coordinates = [offsetInLayoutUnits]
textToAdd.transFlags = [0,0,0]
textToAdd.textString = self.padText(text)
@ -757,7 +753,7 @@ class VlsiLayout:
for boundary in shapes:
vectors = []
for i in range(0, len(boundary), 2):
vectors.append(vector(boundary[i], boundary[i+1]))
vectors.append((boundary[i], boundary[i+1]))
blockages.append(vectors)
return blockages

View File

@ -124,18 +124,18 @@ class ptx(design.design):
# The contacted poly pitch (or uncontacted in an odd technology)
self.poly_pitch = max(2 * self.contact_to_gate + self.contact_width + self.poly_width,
self.poly_pitch = max(2 * self.active_contact_to_gate + self.contact_width + self.poly_width,
self.poly_space)
# The contacted poly pitch (or uncontacted in an odd technology)
self.contact_pitch = 2 * self.contact_to_gate + self.contact_width + self.poly_width
self.contact_pitch = 2 * self.active_contact_to_gate + self.contact_width + self.poly_width
# The enclosure of an active contact. Not sure about second term.
active_enclose_contact = max(drc("active_enclosure_contact"),
active_enclose_contact = max(drc("active_enclosure_active_contact"),
(self.active_width - self.contact_width) / 2)
# This is the distance from the edge of poly to the contacted end of active
self.end_to_poly = active_enclose_contact + self.contact_width + self.contact_to_gate
self.end_to_poly = active_enclose_contact + self.contact_width + self.active_contact_to_gate
# Active width is determined by enclosure on both ends and contacted pitch,

View File

@ -44,9 +44,8 @@ layer["vtg"] = (6, 0)
layer["vth"] = (7, 0)
layer["thkox"] = (8, 0)
layer["poly"] = (9, 0)
layer["contact"] = (10, 0)
layer["active_contact"] = (10, 0)
layer["poly_contact"] = None
layer["poly_contact"] = (10, 0)
layer["metal1"] = (11, 0)
layer["via1"] = (12, 0)
layer["metal2"] = (13, 0)
@ -117,7 +116,7 @@ drc["poly_to_poly"] = 0.14
# POLY.3 Minimum poly extension beyond active
drc["poly_extend_active"] = 0.055
# Not a rule
drc["poly_to_polycontact"] = 0.075
drc["poly_to_poly_contact"] = 0.075
# POLY.4 Minimum enclosure of active around gate
drc["active_enclosure_gate"] = 0.07
# POLY.5 Minimum spacing of field poly to active
@ -154,30 +153,51 @@ drc["implant_to_implant"] = 0.045
drc["minwidth_implant"] = 0.045
# CONTACT.1 Minimum width of contact
drc["minwidth_contact"] = 0.065
drc["minwidth_active_contact"] = 0.065
# CONTACT.2 Minimum spacing of contact
drc["contact_to_contact"] = 0.075
drc["active_contact_to_active_contact"] = 0.075
# CONTACT.4 Minimum enclosure of active around contact
drc["active_enclosure_contact"] = 0.005
drc["active_enclosure_active_contact"] = 0.005
# Reserved for asymmetric enclosures
drc["active_extend_active_contact"] = 0.005
# CONTACT.5 Minimum enclosure of poly around contact
drc["poly_enclosure_active_contact"] = 0.005
# Reserved for asymmetric enclosures
drc["poly_extend_active_contact"] = 0.005
# CONTACT.6 Minimum spacing of contact and gate
drc["active_contact_to_gate"] = 0.0375 #changed from 0.035
# CONTACT.7 Minimum spacing of contact and poly
drc["active_contact_to_poly"] = 0.090
# CONTACT.1 Minimum width of contact
drc["minwidth_poly_contact"] = 0.065
# CONTACT.2 Minimum spacing of contact
drc["poly_contact_to_poly_contact"] = 0.075
# CONTACT.4 Minimum enclosure of active around contact
drc["active_enclosure_poly_contact"] = 0.005
# Reserved for asymmetric enclosures
drc["active_extend_contact"] = 0.005
# CONTACT.5 Minimum enclosure of poly around contact
drc["poly_enclosure_contact"] = 0.005
drc["poly_enclosure_poly_contact"] = 0.005
# Reserved for asymmetric enclosures
drc["poly_extend_contact"] = 0.005
drc["poly_extend_poly_contact"] = 0.005
# CONTACT.6 Minimum spacing of contact and gate
drc["contact_to_gate"] = 0.0375 #changed from 0.035
drc["poly_contact_to_gate"] = 0.0375 #changed from 0.035
# CONTACT.7 Minimum spacing of contact and poly
drc["contact_to_poly"] = 0.090
drc["poly_contact_to_poly"] = 0.090
# METAL1.1 Minimum width of metal1
drc["minwidth_metal1"] = 0.065
# METAL1.2 Minimum spacing of metal1
drc["metal1_to_metal1"] = 0.065
# METAL1.3 Minimum enclosure around contact on two opposite sides
drc["metal1_enclosure_contact"] = 0
drc["metal1_enclosure_active_contact"] = 0
# Reserved for asymmetric enclosures
drc["metal1_extend_contact"] = 0.035
drc["metal1_extend_active_contact"] = 0.035
# METAL1.3 Minimum enclosure around contact on two opposite sides
drc["metal1_enclosure_poly_contact"] = 0
# Reserved for asymmetric enclosures
drc["metal1_extend_poly_contact"] = 0.035
# METAL1.4 inimum enclosure around via1 on two opposite sides
drc["metal1_extend_via1"] = 0.035
# Reserved for asymmetric enclosures

View File

@ -43,9 +43,8 @@ layer["active"] = (43, 0)
layer["pimplant"] = (44, 0)
layer["nimplant"] = (45, 0)
layer["poly"] = (46, 0)
layer["poly_contact"] = None
layer["contact"] = (47, 0)
layer["active_contact"] = (48, 0)
layer["poly_contact"] = (47, 0)
layer["metal1"] = (49, 0)
layer["via1"] = (50, 0)
layer["metal2"] = (51, 0)
@ -105,7 +104,7 @@ drc["poly_to_poly"] = 3*_lambda_
# 3.3 Minimum gate extension of active
drc["poly_extend_active"] = 2*_lambda_
# 5.5.b Minimum spacing between poly contact and other poly (alternative rules)
drc["poly_to_polycontact"] = 4*_lambda_
drc["poly_to_poly_contact"] = 4*_lambda_
# ??
drc["active_enclosure_gate"] = 0.0
# 3.5 Minimum field poly to active
@ -142,30 +141,51 @@ drc["implant_to_implant"] = 0
drc["minwidth_implant"] = 0
# 6.1 Exact contact size
drc["minwidth_contact"] = 2*_lambda_
drc["minwidth_active_contact"] = 2*_lambda_
# 5.3 Minimum contact spacing
drc["contact_to_contact"] = 3*_lambda_
drc["active_contact_to_active_contact"] = 3*_lambda_
# 6.2.b Minimum active overlap
drc["active_enclosure_contact"] = _lambda_
drc["active_enclosure_active_contact"] = _lambda_
# Reserved for asymmetric enclosure
drc["active_extend_contact"] = _lambda_
drc["active_extend_active_contact"] = _lambda_
# 5.2.b Minimum poly overlap
drc["poly_enclosure_contact"] = _lambda_
drc["poly_enclosure_active_contact"] = _lambda_
# Reserved for asymmetric enclosures
drc["poly_extend_contact"] = _lambda_
drc["poly_extend_active_contact"] = _lambda_
# Reserved for other technologies
drc["contact_to_gate"] = 2*_lambda_
drc["active_contact_to_gate"] = 2*_lambda_
# 5.4 Minimum spacing to gate of transistor
drc["contact_to_poly"] = 2*_lambda_
drc["active_contact_to_poly"] = 2*_lambda_
# 6.1 Exact contact size
drc["minwidth_poly_contact"] = 2*_lambda_
# 5.3 Minimum contact spacing
drc["poly_contact_to_poly_contact"] = 3*_lambda_
# 6.2.b Minimum active overlap
drc["active_enclosure_poly_contact"] = _lambda_
# Reserved for asymmetric enclosure
drc["active_extend_poly_contact"] = _lambda_
# 5.2.b Minimum poly overlap
drc["poly_enclosure_poly_contact"] = _lambda_
# Reserved for asymmetric enclosures
drc["poly_extend_poly_contact"] = _lambda_
# Reserved for other technologies
drc["poly_contact_to_gate"] = 2*_lambda_
# 5.4 Minimum spacing to gate of transistor
drc["poly_contact_to_poly"] = 2*_lambda_
# 7.1 Minimum width
drc["minwidth_metal1"] = 3*_lambda_
# 7.2 Minimum spacing
drc["metal1_to_metal1"] = 3*_lambda_
# 7.3 Minimum overlap of any contact
drc["metal1_enclosure_contact"] = _lambda_
drc["metal1_enclosure_active_contact"] = _lambda_
# Reserved for asymmetric enclosure
drc["metal1_extend_contact"] = _lambda_
drc["metal1_extend_active_contact"] = _lambda_
# 7.3 Minimum overlap of any contact
drc["metal1_enclosure_poly_contact"] = _lambda_
# Reserved for asymmetric enclosure
drc["metal1_extend_poly_contact"] = _lambda_
# 8.3 Minimum overlap by metal1
drc["metal1_enclosure_via1"] = _lambda_
# Reserve for asymmetric enclosures