From 69bb245f28eb5571889cd6a021fb24facd357b93 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 4 Dec 2019 16:12:53 -0800 Subject: [PATCH] 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. --- compiler/base/contact.py | 16 ++++---- compiler/base/design.py | 6 +-- compiler/base/geometry.py | 3 +- compiler/base/hierarchy_layout.py | 6 ++- compiler/base/pin_layout.py | 1 - compiler/bitcells/pbitcell.py | 8 ++-- compiler/gdsMill/gdsMill/gds2reader.py | 45 ++++++++++++++++++--- compiler/gdsMill/gdsMill/gds2writer.py | 24 ++++++------ compiler/gdsMill/gdsMill/gdsPrimitives.py | 9 ++--- compiler/gdsMill/gdsMill/vlsiLayout.py | 12 ++---- compiler/pgates/ptx.py | 8 ++-- technology/freepdk45/tech/tech.py | 44 +++++++++++++++------ technology/scn4m_subm/tech/tech.py | 48 ++++++++++++++++------- 13 files changed, 148 insertions(+), 82 deletions(-) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index 30f6870b..fb8ea0e8 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -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) diff --git a/compiler/base/design.py b/compiler/base/design.py index 33914358..c6385243 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -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") diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index cbc1d268..e5c86546 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -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) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 000e16ee..b6ca8f33 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -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) diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index f7427a9c..ea114ac6 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -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) diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index bbfdf942..0e0e1bf7 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -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, diff --git a/compiler/gdsMill/gdsMill/gds2reader.py b/compiler/gdsMill/gdsMill/gds2reader.py index f660fe3c..351df6a4 100644 --- a/compiler/gdsMill/gdsMill/gds2reader.py +++ b/compiler/gdsMill/gdsMill/gds2reader.py @@ -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 diff --git a/compiler/gdsMill/gdsMill/gds2writer.py b/compiler/gdsMill/gdsMill/gds2writer.py index 402416cd..3a319324 100644 --- a/compiler/gdsMill/gdsMill/gds2writer.py +++ b/compiler/gdsMill/gdsMill/gds2writer.py @@ -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' diff --git a/compiler/gdsMill/gdsMill/gdsPrimitives.py b/compiler/gdsMill/gdsMill/gdsPrimitives.py index dc43fea6..09bd85b4 100644 --- a/compiler/gdsMill/gdsMill/gdsPrimitives.py +++ b/compiler/gdsMill/gdsMill/gdsPrimitives.py @@ -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="" diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index eec1870c..412a430c 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -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 diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index f3180840..33098e7c 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -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, diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 13e7ccff..16c2b393 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -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 diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 2d1d5e15..deaab30c 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -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