mirror of https://github.com/VLSIDA/OpenRAM.git
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:
parent
0d35941241
commit
69bb245f28
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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=""
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue