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. # Module does not have pins, but has empty pin list.
self.pins = [] self.pins = []
self.create_layout() self.create_layout()
self.add_boundary()
def create_layout(self): def create_layout(self):
self.setup_layers() self.setup_layers()
@ -71,14 +72,11 @@ class contact(hierarchy_design.hierarchy_design):
(first_layer, via_layer, second_layer) = self.layer_stack (first_layer, via_layer, second_layer) = self.layer_stack
self.first_layer_name = first_layer self.first_layer_name = first_layer
self.via_layer_name = via_layer # Contacts will have unique per first layer
# Some technologies have a separate active if via_layer == "contact":
# contact from the poly contact self.via_layer_name = first_layer + "_" + via_layer
# 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
else: else:
self.via_layer_name_expanded = via_layer self.via_layer_name = via_layer
self.second_layer_name = second_layer self.second_layer_name = second_layer
def setup_layout_constants(self): def setup_layout_constants(self):
@ -144,7 +142,7 @@ class contact(hierarchy_design.hierarchy_design):
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_expanded, self.add_rect(layer=self.via_layer_name,
offset=offset, offset=offset,
width=self.contact_width, width=self.contact_width,
height=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.m4_space = drc("metal4_to_metal4")
self.active_width = drc("minwidth_active") self.active_width = drc("minwidth_active")
self.active_space = drc("active_to_body_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_to_active = drc("poly_to_active")
self.poly_extend_active = drc("poly_extend_active") self.poly_extend_active = drc("poly_extend_active")
self.poly_to_polycontact = drc("poly_to_polycontact") self.poly_to_poly_contact = drc("poly_to_poly_contact")
self.contact_to_gate = drc("contact_to_gate") self.active_contact_to_gate = drc("active_contact_to_gate")
self.well_enclose_active = drc("well_enclosure_active") self.well_enclose_active = drc("well_enclosure_active")
self.implant_enclose_active = drc("implant_enclosure_active") self.implant_enclose_active = drc("implant_enclosure_active")
self.implant_space = drc("implant_to_implant") self.implant_space = drc("implant_to_implant")

View File

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

View File

@ -939,7 +939,11 @@ class layout():
def add_boundary(self, offset=vector(0,0)): def add_boundary(self, offset=vector(0,0)):
""" Add boundary for debugging dimensions """ """ 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, offset=offset,
height=self.height, height=self.height,
width=self.width) width=self.width)

View File

@ -344,7 +344,6 @@ class pin_layout:
# imported into Magic. # imported into Magic.
newLayout.addText(text=self.name, newLayout.addText(text=self.name,
layerNumber=layer_num, layerNumber=layer_num,
purposeNumber=purpose,
offsetInMicrons=self.center(), offsetInMicrons=self.center(),
magnification=GDS["zoom"], magnification=GDS["zoom"],
rotate=None) 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_nmos.active_contact.height - self.inverter_nmos.active_height)
self.inverter_gap = max(self.poly_to_active, self.inverter_gap = max(self.poly_to_active,
self.m1_space + inverter_nmos_contact_extension) \ 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.m1_space + inverter_pmos_contact_extension
self.cross_couple_lower_ypos = self.inverter_nmos_ypos \ self.cross_couple_lower_ypos = self.inverter_nmos_ypos \
+ self.inverter_nmos.active_height \ + self.inverter_nmos.active_height \
@ -254,7 +254,7 @@ class pbitcell(bitcell_base.bitcell_base):
+ self.inverter_nmos.active_height \ + self.inverter_nmos.active_height \
+ max(self.poly_to_active, + max(self.poly_to_active,
self.m1_space + inverter_nmos_contact_extension) \ self.m1_space + inverter_nmos_contact_extension) \
+ self.poly_to_polycontact \ + self.poly_to_poly_contact \
+ 1.5 * contact.poly.width + 1.5 * contact.poly.width
# spacing between wordlines (and gnd) # 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 # add poly to metal1 contacts for gates of the inverters
left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x \ 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.cross_couple_upper_ypos)
self.add_via_center(layers=("poly", "contact", "metal1"), self.add_via_center(layers=("poly", "contact", "metal1"),
offset=left_storage_contact, offset=left_storage_contact,
directions=("H", "H")) directions=("H", "H"))
right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x \ 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.cross_couple_upper_ypos)
self.add_via_center(layers=("poly", "contact", "metal1"), self.add_via_center(layers=("poly", "contact", "metal1"),
offset=right_storage_contact, offset=right_storage_contact,

View File

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

View File

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

View File

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

View File

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

View File

@ -124,18 +124,18 @@ class ptx(design.design):
# The contacted poly pitch (or uncontacted in an odd technology) # 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) self.poly_space)
# The contacted poly pitch (or uncontacted in an odd technology) # 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. # 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) (self.active_width - self.contact_width) / 2)
# This is the distance from the edge of poly to the contacted end of active # 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, # 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["vth"] = (7, 0)
layer["thkox"] = (8, 0) layer["thkox"] = (8, 0)
layer["poly"] = (9, 0) layer["poly"] = (9, 0)
layer["contact"] = (10, 0)
layer["active_contact"] = (10, 0) layer["active_contact"] = (10, 0)
layer["poly_contact"] = None layer["poly_contact"] = (10, 0)
layer["metal1"] = (11, 0) layer["metal1"] = (11, 0)
layer["via1"] = (12, 0) layer["via1"] = (12, 0)
layer["metal2"] = (13, 0) layer["metal2"] = (13, 0)
@ -117,7 +116,7 @@ drc["poly_to_poly"] = 0.14
# POLY.3 Minimum poly extension beyond active # POLY.3 Minimum poly extension beyond active
drc["poly_extend_active"] = 0.055 drc["poly_extend_active"] = 0.055
# Not a rule # Not a rule
drc["poly_to_polycontact"] = 0.075 drc["poly_to_poly_contact"] = 0.075
# POLY.4 Minimum enclosure of active around gate # POLY.4 Minimum enclosure of active around gate
drc["active_enclosure_gate"] = 0.07 drc["active_enclosure_gate"] = 0.07
# POLY.5 Minimum spacing of field poly to active # POLY.5 Minimum spacing of field poly to active
@ -154,30 +153,51 @@ drc["implant_to_implant"] = 0.045
drc["minwidth_implant"] = 0.045 drc["minwidth_implant"] = 0.045
# CONTACT.1 Minimum width of contact # CONTACT.1 Minimum width of contact
drc["minwidth_contact"] = 0.065 drc["minwidth_active_contact"] = 0.065
# CONTACT.2 Minimum spacing of contact # 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 # 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 # Reserved for asymmetric enclosures
drc["active_extend_contact"] = 0.005 drc["active_extend_contact"] = 0.005
# CONTACT.5 Minimum enclosure of poly around contact # 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 # 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 # 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 # 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 # METAL1.1 Minimum width of metal1
drc["minwidth_metal1"] = 0.065 drc["minwidth_metal1"] = 0.065
# METAL1.2 Minimum spacing of metal1 # METAL1.2 Minimum spacing of metal1
drc["metal1_to_metal1"] = 0.065 drc["metal1_to_metal1"] = 0.065
# METAL1.3 Minimum enclosure around contact on two opposite sides # 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 # 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 # METAL1.4 inimum enclosure around via1 on two opposite sides
drc["metal1_extend_via1"] = 0.035 drc["metal1_extend_via1"] = 0.035
# Reserved for asymmetric enclosures # Reserved for asymmetric enclosures

View File

@ -43,9 +43,8 @@ layer["active"] = (43, 0)
layer["pimplant"] = (44, 0) layer["pimplant"] = (44, 0)
layer["nimplant"] = (45, 0) layer["nimplant"] = (45, 0)
layer["poly"] = (46, 0) layer["poly"] = (46, 0)
layer["poly_contact"] = None
layer["contact"] = (47, 0)
layer["active_contact"] = (48, 0) layer["active_contact"] = (48, 0)
layer["poly_contact"] = (47, 0)
layer["metal1"] = (49, 0) layer["metal1"] = (49, 0)
layer["via1"] = (50, 0) layer["via1"] = (50, 0)
layer["metal2"] = (51, 0) layer["metal2"] = (51, 0)
@ -105,7 +104,7 @@ drc["poly_to_poly"] = 3*_lambda_
# 3.3 Minimum gate extension of active # 3.3 Minimum gate extension of active
drc["poly_extend_active"] = 2*_lambda_ drc["poly_extend_active"] = 2*_lambda_
# 5.5.b Minimum spacing between poly contact and other poly (alternative rules) # 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 drc["active_enclosure_gate"] = 0.0
# 3.5 Minimum field poly to active # 3.5 Minimum field poly to active
@ -142,30 +141,51 @@ drc["implant_to_implant"] = 0
drc["minwidth_implant"] = 0 drc["minwidth_implant"] = 0
# 6.1 Exact contact size # 6.1 Exact contact size
drc["minwidth_contact"] = 2*_lambda_ drc["minwidth_active_contact"] = 2*_lambda_
# 5.3 Minimum contact spacing # 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 # 6.2.b Minimum active overlap
drc["active_enclosure_contact"] = _lambda_ drc["active_enclosure_active_contact"] = _lambda_
# Reserved for asymmetric enclosure # Reserved for asymmetric enclosure
drc["active_extend_contact"] = _lambda_ drc["active_extend_active_contact"] = _lambda_
# 5.2.b Minimum poly overlap # 5.2.b Minimum poly overlap
drc["poly_enclosure_contact"] = _lambda_ drc["poly_enclosure_active_contact"] = _lambda_
# Reserved for asymmetric enclosures # Reserved for asymmetric enclosures
drc["poly_extend_contact"] = _lambda_ drc["poly_extend_active_contact"] = _lambda_
# Reserved for other technologies # 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 # 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 # 7.1 Minimum width
drc["minwidth_metal1"] = 3*_lambda_ drc["minwidth_metal1"] = 3*_lambda_
# 7.2 Minimum spacing # 7.2 Minimum spacing
drc["metal1_to_metal1"] = 3*_lambda_ drc["metal1_to_metal1"] = 3*_lambda_
# 7.3 Minimum overlap of any contact # 7.3 Minimum overlap of any contact
drc["metal1_enclosure_contact"] = _lambda_ drc["metal1_enclosure_active_contact"] = _lambda_
# Reserved for asymmetric enclosure # 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 # 8.3 Minimum overlap by metal1
drc["metal1_enclosure_via1"] = _lambda_ drc["metal1_enclosure_via1"] = _lambda_
# Reserve for asymmetric enclosures # Reserve for asymmetric enclosures