mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-08-30 01:48:33 +02:00
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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user