diff --git a/compiler/base/contact.py b/compiler/base/contact.py index fb8ea0e8..e363a2fa 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -48,7 +48,6 @@ 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): diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index b6ca8f33..7dcb62f9 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -32,6 +32,7 @@ class layout(): self.name = name self.width = None self.height = None + self.boundary = None self.insts = [] # Holds module/cell layout instances self.objs = [] # Holds all other objects (labels, geometries, etc) self.pin_map = {} # Holds name->pin_layout map for all pins @@ -80,7 +81,10 @@ class layout(): lowesty2 = min(inst.by() for inst in self.insts) else: lowestx2=lowesty2=None - if lowestx1==None: + + if lowestx1==None and lowestx2==None: + return None + elif lowestx1==None: return vector(lowestx2,lowesty2) elif lowestx2==None: return vector(lowestx1,lowesty1) @@ -101,7 +105,9 @@ class layout(): highesty2 = max(inst.uy() for inst in self.insts) else: highestx2=highesty2=None - if highestx1==None: + if highestx1==None and highestx2==None: + return None + elif highestx1==None: return vector(highestx2,highesty2) elif highestx2==None: return vector(highestx1,highesty1) @@ -500,6 +506,33 @@ class layout(): for pin_name in self.pin_map.keys(): for pin in self.pin_map[pin_name]: pin.gds_write_file(gds_layout) + + # If it's not a premade cell + # and we didn't add our own boundary, + # we should add a boundary just for DRC in some technologies + if not self.is_library_cell and not self.boundary: + # If there is a boundary layer, and we didn't create one, add one. + if "stdc" in techlayer.keys(): + boundary_layer = "stdc" + elif "boundary" in techlayer.keys(): + boundary_layer = "boundary" + else: + boundary_layer = None + + if boundary_layer: + boundary = [self.find_lowest_coords(), self.find_highest_coords()] + height = boundary[1][1] - boundary[0][1] + width = boundary[1][0] - boundary[0][0] + (layer_number, layer_purpose) = techlayer[boundary_layer] + gds_layout.addBox(layerNumber=layer_number, + purposeNumber=layer_purpose, + offsetInMicrons=boundary[0], + width=width, + height=height, + center=False) + debug.info(0, "Adding {0} boundary {1}".format(self.name, boundary)) + + self.visited.append(self.name) def gds_write(self, gds_name): @@ -937,16 +970,22 @@ class layout(): """ self.create_channel_route(netlist, offset, layer_stack, vertical=False) - def add_boundary(self, offset=vector(0,0)): + def add_boundary(self, ll=vector(0,0), ur=None): """ Add boundary for debugging dimensions """ 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) + if ur == None: + self.boundary = self.add_rect(layer=boundary_layer, + offset=ll, + height=self.height, + width=self.width) + else: + self.boundary = self.add_rect(layer=boundary_layer, + offset=ll, + height=ur.y-ll.y, + width=ur.x-ll.x) def add_enclosure(self, insts, layer="nwell"): """ Add a layer that surrounds the given instances. Useful diff --git a/compiler/bitcells/dummy_pbitcell.py b/compiler/bitcells/dummy_pbitcell.py index ee15e03c..ead3d7f3 100644 --- a/compiler/bitcells/dummy_pbitcell.py +++ b/compiler/bitcells/dummy_pbitcell.py @@ -30,6 +30,7 @@ class dummy_pbitcell(design.design): self.create_netlist() self.create_layout() + self.add_boundary() def create_netlist(self): self.add_pins() diff --git a/compiler/bitcells/replica_pbitcell.py b/compiler/bitcells/replica_pbitcell.py index 4fcfb4c5..5a588c1e 100644 --- a/compiler/bitcells/replica_pbitcell.py +++ b/compiler/bitcells/replica_pbitcell.py @@ -30,6 +30,7 @@ class replica_pbitcell(design.design): self.create_netlist() self.create_layout() + self.add_boundary() def create_netlist(self): self.add_pins() @@ -84,4 +85,4 @@ class replica_pbitcell(design.design): self.copy_layout_pin(self.prbc_inst, "wl{}".format(port)) self.copy_layout_pin(self.prbc_inst, "vdd") self.copy_layout_pin(self.prbc_inst, "gnd") - \ No newline at end of file + diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index 33098e7c..3a7311ae 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -58,7 +58,14 @@ class ptx(design.design): # We must always create ptx layout for pbitcell # some transistor sizes in other netlist depend on pbitcell self.create_layout() - + + ll = self.find_lowest_coords() + ur = self.find_highest_coords() + self.add_boundary(ll, ur) + + # (0,0) will be the corner ofthe active area (not the larger well) + self.translate_all(self.active_offset) + def create_layout(self): """Calls all functions related to the generation of the layout""" self.setup_layout_constants() @@ -66,7 +73,6 @@ class ptx(design.design): self.add_well_implant() self.add_poly() self.add_active_contacts() - self.translate_all(self.active_offset) # for run-time, we won't check every transitor DRC independently # but this may be uncommented for debug purposes diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 16c2b393..31c712ec 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -160,10 +160,6 @@ drc["active_contact_to_active_contact"] = 0.075 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 @@ -171,10 +167,6 @@ 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 diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index deaab30c..8e189efd 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -148,10 +148,6 @@ drc["active_contact_to_active_contact"] = 3*_lambda_ drc["active_enclosure_active_contact"] = _lambda_ # Reserved for asymmetric enclosure drc["active_extend_active_contact"] = _lambda_ -# 5.2.b Minimum poly overlap -drc["poly_enclosure_active_contact"] = _lambda_ -# Reserved for asymmetric enclosures -drc["poly_extend_active_contact"] = _lambda_ # Reserved for other technologies drc["active_contact_to_gate"] = 2*_lambda_ # 5.4 Minimum spacing to gate of transistor @@ -161,10 +157,6 @@ drc["active_contact_to_poly"] = 2*_lambda_ 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