From 596302d9a927743ba929b358cecdf8f32b0deb09 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 5 Feb 2020 18:22:45 +0000 Subject: [PATCH] Update pgate well and well contacts. Extend well left and right past a cell boundary. Use asymmetric well contacts. --- compiler/pgates/pgate.py | 8 +++----- compiler/pgates/pinv.py | 18 ++++++++++-------- compiler/pgates/pnand2.py | 6 +++--- compiler/pgates/pnand3.py | 10 +++++----- compiler/pgates/pnor2.py | 8 ++++---- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index ab30a0d0..c13939f1 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -134,10 +134,10 @@ class pgate(design.design): # Add a rail width to extend the well to the top of the rail nwell_max_offset = max(self.find_highest_layer_coords("nwell").y, self.height + 0.5 * self.m1_width) - nwell_position = middle_position + nwell_position = middle_position - vector(self.well_extend_active, 0) nwell_height = nwell_max_offset - middle_position.y self.add_rect(layer="nwell", - offset=middle_position, + offset=nwell_position, width=self.well_width, height=nwell_height) if "vtg" in layer: @@ -150,7 +150,7 @@ class pgate(design.design): if "pwell" in layer: pwell_min_offset = min(self.find_lowest_layer_coords("pwell").y, -0.5 * self.m1_width) - pwell_position = vector(0, pwell_min_offset) + pwell_position = vector(-self.well_extend_active, pwell_min_offset) pwell_height = middle_position.y - pwell_position.y self.add_rect(layer="pwell", offset=pwell_position, @@ -183,7 +183,6 @@ class pgate(design.design): 0.5 * pmos.active_contact.first_layer_height) self.nwell_contact = self.add_via_center(layers=layer_stack, offset=contact_offset, - directions=("H", "V"), implant_type="n", well_type="n") self.add_rect_center(layer="m1", @@ -237,7 +236,6 @@ class pgate(design.design): 0.5 * nmos.active_contact.first_layer_height) self.pwell_contact= self.add_via_center(layers=layer_stack, offset=contact_offset, - directions=("H", "V"), implant_type="p", well_type="p") self.add_rect_center(layer="m1", diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 8da648b0..c0336956 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -52,10 +52,10 @@ class pinv(pgate.pgate): def create_layout(self): """ Calls all functions related to the generation of the layout """ self.setup_layout_constants() - self.route_supply_rails() self.place_ptx() self.add_well_contacts() self.extend_wells(self.well_pos) + self.route_supply_rails() self.connect_rails() self.route_input_gate(self.pmos_inst, self.nmos_inst, @@ -104,8 +104,9 @@ class pinv(pgate.pgate): extra_contact_space = max(-nmos.get_pin("D").by(), 0) # This is a poly-to-poly of a flipped cell self.top_bottom_space = max(0.5*self.m1_width + self.m1_space + extra_contact_space, - self.poly_extend_active, self.poly_space) + self.poly_extend_active + self.poly_space) total_height = tx_height + min_channel + 2 * self.top_bottom_space + debug.check(self.height > total_height, "Cell height {0} too small for simple min height {1}.".format(self.height, total_height)) @@ -148,14 +149,15 @@ class pinv(pgate.pgate): def setup_layout_constants(self): """ - Pre-compute some handy layout parameters. + Compute the width and height """ - # the well width is determined the multi-finger PMOS device width plus - # the well contact width and half well enclosure on both sides - self.well_width = self.pmos.active_width + self.pmos.active_contact.width \ - + self.active_space + 2*self.nwell_enclose_active - self.width = self.well_width + # the width is determined the multi-finger PMOS device width plus + # the well contact width, spacing between them + self.width = self.pmos.active_offset.x + self.pmos.active_width \ + + contact.nwell_contact.width + self.active_space + 0.5 * self.nwell_enclose_active + # This includes full enclosures on each end + self.well_width = self.width + 2*self.nwell_enclose_active # Height is an input parameter, so it is not recomputed. def add_ptx(self): diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index f5abdaaa..2f539c16 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -98,11 +98,11 @@ class pnand2(pgate.pgate): # Two PMOS devices and a well contact. Separation between each. # Enclosure space on the sides. - self.well_width = 2 * self.pmos.active_width + contact.active_contact.width \ + self.width = 2 * self.pmos.active_width + contact.active_contact.width \ + 2 * self.active_space \ - + 2 * self.nwell_enclose_active + + 0.5 * self.nwell_enclose_active - self.width = self.well_width + self.well_width = self.width + 2 * self.nwell_enclose_active # Height is an input parameter, so it is not recomputed. # This is the extra space needed to ensure DRC rules diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 5c1e0db5..d5b07069 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -91,10 +91,10 @@ class pnand3(pgate.pgate): # Two PMOS devices and a well contact. Separation between each. # Enclosure space on the sides. - self.well_width = 3 * self.pmos.active_width + self.pmos.active_contact.width \ - + 2 * self.active_space + 2 * self.nwell_enclose_active \ + self.width = 3 * self.pmos.active_width + self.pmos.active_contact.width \ + + 2 * self.active_space + 0.5 * self.nwell_enclose_active \ - self.overlap_offset.x - self.width = self.well_width + self.well_width = self.width + 2 * self.nwell_enclose_active # Height is an input parameter, so it is not recomputed. # This is the extra space needed to ensure DRC rules @@ -245,10 +245,10 @@ class pnand3(pgate.pgate): offset=nmos3_pin.center()) # PMOS3 and NMOS3 are drain aligned - self.add_path("m2", [pmos3_pin.bc(), nmos3_pin.uc()]) + self.add_path("m2", [pmos3_pin.center(), nmos3_pin.uc()]) # Route in the A input track (top track) mid_offset = vector(nmos3_pin.center().x, self.inputA_yoffset) - self.add_path("m2", [pmos1_pin.bc(), mid_offset, nmos3_pin.uc()]) + self.add_path("m2", [pmos1_pin.center(), mid_offset, nmos3_pin.uc()]) # This extends the output to the edge of the cell self.add_via_center(layers=self.m1_stack, diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index e28b6fc8..7ceab71a 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -95,11 +95,11 @@ class pnor2(pgate.pgate): # Two PMOS devices and a well contact. Separation between each. # Enclosure space on the sides. - self.well_width = 2 * self.pmos.active_width \ + self.width = 2 * self.pmos.active_width \ + self.pmos.active_contact.width \ + 2 * self.active_space \ - + 2 * self.nwell_enclose_active - self.width = self.well_width + + 0.5 * self.nwell_enclose_active + self.well_width = self.width + 2 * self.nwell_enclose_active # Height is an input parameter, so it is not recomputed. # This is the extra space needed to ensure DRC rules @@ -225,7 +225,7 @@ class pnor2(pgate.pgate): # PMOS1 to mid-drain to NMOS2 drain self.add_path("m2", - [pmos_pin.bc(), mid2_offset, mid3_offset]) + [pmos_pin.center(), mid2_offset, mid3_offset]) self.add_path("m2", [nmos_pin.rc(), mid1_offset, mid2_offset]) # This extends the output to the edge of the cell