From 266d68c3955046d811bb84c5a0cd1e3bd787c250 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 25 Feb 2020 17:09:07 +0000 Subject: [PATCH] Generalize pgate width based on nwell/pwell contacts --- compiler/pgates/pgate.py | 9 +++++++++ compiler/pgates/pinv.py | 17 +---------------- compiler/pgates/pnand2.py | 14 +++----------- compiler/pgates/pnand3.py | 17 +++++------------ compiler/pgates/pnor2.py | 5 +++-- 5 files changed, 21 insertions(+), 41 deletions(-) diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 8b9a1c66..59ec2448 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -264,3 +264,12 @@ class pgate(design.design): # offset=implant_offset, # width=implant_width, # height=implant_height) + + def determine_width(self): + """ Determine the width based on the well contacts (assumed to be on the right side) """ + # Width is determined by well contact and spacing + self.width = max(self.nwell_contact.rx(), self.pwell_contact.rx()) + self.m1_space + self.well_width = self.width + 2 * self.nwell_enclose_active + # Height is an input parameter, so it is not recomputed. + + diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index c0f1f955..3c2e41a2 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -51,9 +51,9 @@ class pinv(pgate.pgate): def create_layout(self): """ Calls all functions related to the generation of the layout """ - self.setup_layout_constants() self.place_ptx() self.add_well_contacts() + self.determine_width() self.extend_wells() self.route_supply_rails() self.connect_rails() @@ -147,21 +147,6 @@ class pinv(pgate.pgate): debug.check(self.pmos_width >= drc("minwidth_tx"), "Cannot finger PMOS transistors to fit cell height.") - def setup_layout_constants(self): - """ - Compute the width and height - """ - - # the width is determined the multi-finger PMOS device width plus - # the well contact width, spacing between them - # space is for power supply contact to nwell m1 spacing - self.width = self.pmos.active_offset.x + self.pmos.active_width \ - + self.active_space + contact.nwell_contact.width \ - + 0.5 * self.nwell_enclose_active \ - + self.m1_space - # 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): """ Create the PMOS and NMOS transistors. """ diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 7c40c7ab..05eabbe0 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -49,10 +49,11 @@ class pnand2(pgate.pgate): """ Calls all functions related to the generation of the layout """ self.setup_layout_constants() - self.route_supply_rails() self.place_ptx() - self.connect_rails() self.add_well_contacts() + self.determine_width() + self.route_supply_rails() + self.connect_rails() self.extend_wells() self.route_inputs() self.route_output() @@ -96,15 +97,6 @@ class pnand2(pgate.pgate): # source and drain pins self.overlap_offset = self.pmos.get_pin("D").ll() - self.pmos.get_pin("S").ll() - # Two PMOS devices and a well contact. Separation between each. - # Enclosure space on the sides. - self.width = 2 * self.pmos.active_width + contact.active_contact.width \ - + 2 * self.active_space \ - + 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 # to the active contacts extra_contact_space = max(-self.nmos.get_pin("D").by(), 0) diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 087cffd5..0a46b633 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -57,13 +57,15 @@ class pnand3(pgate.pgate): """ Calls all functions related to the generation of the layout """ self.setup_layout_constants() - self.route_supply_rails() self.place_ptx() - self.connect_rails() self.add_well_contacts() + self.determine_width() + self.route_supply_rails() + self.connect_rails() self.extend_wells() self.route_inputs() self.route_output() + def add_ptx(self): """ Create the PMOS and NMOS transistors. """ @@ -90,14 +92,6 @@ class pnand3(pgate.pgate): overlap_xoffset = self.pmos.get_pin("D").ll().x - self.pmos.get_pin("S").ll().x self.ptx_offset = vector(overlap_xoffset, 0) - # Two PMOS devices and a well contact. Separation between each. - # Enclosure space on the sides. - self.width = 3 * self.pmos.active_width + self.pmos.active_contact.width \ - + 2 * self.active_space + 0.5 * self.nwell_enclose_active \ - - self.ptx_offset.x - 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 # to the active contacts nmos = factory.create(module_type="ptx", tx_type="nmos") @@ -164,7 +158,6 @@ class pnand3(pgate.pgate): self.pmos3_pos = pmos2_pos + self.ptx_offset self.pmos3_inst.place(self.pmos3_pos) - nmos1_pos = vector(self.pmos.active_offset.x, self.top_bottom_space) self.nmos1_inst.place(nmos1_pos) @@ -189,7 +182,7 @@ class pnand3(pgate.pgate): self.connect_pin_to_rail(self.nmos1_inst, "S", "gnd") - self.connect_pin_to_rail(self.pmos1_inst, "S", "vdd") + self.connect_pin_to_rail(self.pmos1_inst, "S", "vdd") self.connect_pin_to_rail(self.pmos2_inst, "D", "vdd") diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index d6605d68..3d998d25 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -48,10 +48,11 @@ class pnor2(pgate.pgate): """ Calls all functions related to the generation of the layout """ self.setup_layout_constants() - self.route_supply_rails() self.place_ptx() - self.connect_rails() self.add_well_contacts() + self.determine_width() + self.route_supply_rails() + self.connect_rails() self.extend_wells() self.route_inputs() self.route_output()