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,6 +48,7 @@ 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):
|
||||||
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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=""
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue