From 617bf302d18f1863da212073d8e80d71097d7dae Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 13 May 2020 14:46:42 -0700 Subject: [PATCH] Add option to remove wells. Save area in pgates with redundant wells. --- compiler/pgates/pand2.py | 13 ++++++++----- compiler/pgates/pand3.py | 15 ++++++++++----- compiler/pgates/pdriver.py | 8 ++++---- compiler/pgates/pgate.py | 17 +++++++++-------- compiler/pgates/pinv.py | 4 ++-- compiler/pgates/pnand2.py | 1 - compiler/pgates/single_level_column_mux.py | 4 ++-- compiler/tests/04_pnor2_test.py | 4 ---- .../04_single_level_column_mux_pbitcell_test.py | 0 compiler/tests/05_replica_bitcell_array_test.py | 0 ...ngle_level_column_mux_array_pbitcell_test.py | 0 .../tests/08_wordline_driver_pbitcell_test.py | 0 .../tests/09_sense_amp_array_test_pbitcell.py | 0 .../10_write_driver_array_pbitcell_test.py | 0 ...10_write_driver_array_wmask_pbitcell_test.py | 0 .../10_write_mask_and_array_pbitcell_test.py | 0 compiler/tests/19_bank_select_pbitcell_test.py | 0 17 files changed, 35 insertions(+), 31 deletions(-) mode change 100644 => 100755 compiler/tests/04_single_level_column_mux_pbitcell_test.py mode change 100644 => 100755 compiler/tests/05_replica_bitcell_array_test.py mode change 100644 => 100755 compiler/tests/07_single_level_column_mux_array_pbitcell_test.py mode change 100644 => 100755 compiler/tests/08_wordline_driver_pbitcell_test.py mode change 100644 => 100755 compiler/tests/09_sense_amp_array_test_pbitcell.py mode change 100644 => 100755 compiler/tests/10_write_driver_array_pbitcell_test.py mode change 100644 => 100755 compiler/tests/10_write_driver_array_wmask_pbitcell_test.py mode change 100644 => 100755 compiler/tests/10_write_mask_and_array_pbitcell_test.py mode change 100644 => 100755 compiler/tests/19_bank_select_pbitcell_test.py diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index 6df877fd..dfbdc3e7 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -15,14 +15,14 @@ class pand2(pgate.pgate): """ This is a simple buffer used for driving loads. """ - def __init__(self, name, size=1, height=None, vertical=False): + def __init__(self, name, size=1, height=None, vertical=False, add_wells=True): debug.info(1, "Creating pand2 {}".format(name)) self.add_comment("size: {}".format(size)) self.vertical = vertical self.size = size - pgate.pgate.__init__(self, name) + pgate.pgate.__init__(self, name, height, add_wells) def create_netlist(self): self.add_pins() @@ -31,12 +31,15 @@ class pand2(pgate.pgate): def create_modules(self): self.nand = factory.create(module_type="pnand2", - height=self.height) - self.add_mod(self.nand) + height=self.height, + add_wells=False) self.inv = factory.create(module_type="pdriver", size_list=[self.size], - height=self.height) + height=self.height, + add_wells=self.add_wells) + + self.add_mod(self.nand) self.add_mod(self.inv) def create_layout(self): diff --git a/compiler/pgates/pand3.py b/compiler/pgates/pand3.py index 5e2e83f8..d7f0b00e 100644 --- a/compiler/pgates/pand3.py +++ b/compiler/pgates/pand3.py @@ -15,7 +15,7 @@ class pand3(pgate.pgate): """ This is a simple buffer used for driving loads. """ - def __init__(self, name, size=1, height=None, vertical=False): + def __init__(self, name, size=1, height=None, vertical=False, add_wells=True): debug.info(1, "Creating pand3 {}".format(name)) self.add_comment("size: {}".format(size)) @@ -23,7 +23,7 @@ class pand3(pgate.pgate): self.size = size # Creates the netlist and layout - pgate.pgate.__init__(self, name, height) + pgate.pgate.__init__(self, name, height, add_wells) def create_netlist(self): self.add_pins() @@ -33,12 +33,17 @@ class pand3(pgate.pgate): def create_modules(self): # Shield the cap, but have at least a stage effort of 4 self.nand = factory.create(module_type="pnand3", - height=self.height) - self.add_mod(self.nand) + height=self.height, + add_wells=False) + # Add the well tap to the inverter because when stacked + # vertically it is sometimes narrower self.inv = factory.create(module_type="pdriver", size_list=[self.size], - height=self.height) + height=self.height, + add_wells=self.add_wells) + + self.add_mod(self.nand) self.add_mod(self.inv) def create_layout(self): diff --git a/compiler/pgates/pdriver.py b/compiler/pgates/pdriver.py index b36d3e95..266400c9 100644 --- a/compiler/pgates/pdriver.py +++ b/compiler/pgates/pdriver.py @@ -17,7 +17,7 @@ class pdriver(pgate.pgate): sized for driving a load. """ - def __init__(self, name, neg_polarity=False, fanout=0, size_list=None, height=None): + def __init__(self, name, neg_polarity=False, fanout=0, size_list=None, height=None, add_wells=True): debug.info(1, "creating pdriver {}".format(name)) @@ -35,7 +35,7 @@ class pdriver(pgate.pgate): debug.error("Cannot specify both size_list and neg_polarity.", -1) # Creates the netlist and layout - pgate.pgate.__init__(self, name, height) + pgate.pgate.__init__(self, name, height, add_wells) def compute_sizes(self): # size_list specified @@ -73,9 +73,9 @@ class pdriver(pgate.pgate): self.place_modules() self.route_wires() self.add_layout_pins() - self.width = self.inv_inst_list[-1].rx() self.height = self.inv_inst_list[0].height + self.extend_wells() self.route_supply_rails() self.add_boundary() @@ -87,7 +87,7 @@ class pdriver(pgate.pgate): def add_modules(self): self.inv_list = [] - add_well = True + add_well = self.add_wells for size in self.size_list: temp_inv = factory.create(module_type="pinv", size=size, diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index be317f48..cdb89fcb 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -162,12 +162,12 @@ class pgate(design.design): nwell_height = nwell_max_offset - self.nwell_y_offset self.add_rect(layer="nwell", offset=nwell_position, - width=self.well_width, + width=self.width + 2 * self.well_extend_active, height=nwell_height) if "vtg" in layer: self.add_rect(layer="vtg", offset=nwell_position, - width=self.well_width, + width=self.width + 2 * self.well_extend_active, height=nwell_height) # Start this half a rail width below the cell @@ -178,12 +178,12 @@ class pgate(design.design): pwell_height = self.nwell_y_offset - pwell_position.y self.add_rect(layer="pwell", offset=pwell_position, - width=self.well_width, + width=self.width + 2 * self.well_extend_active, height=pwell_height) if "vtg" in layer: self.add_rect(layer="vtg", offset=pwell_position, - width=self.well_width, + width=self.width + 2 * self.well_extend_active, height=pwell_height) def add_nwell_contact(self, pmos, pmos_pos): @@ -304,16 +304,17 @@ class pgate(design.design): def determine_width(self): """ Determine the width based on the well contacts (assumed to be on the right side) """ + # It was already set or is left as default (minimum) # Width is determined by well contact and spacing and allowing a supply via between each cell if self.add_wells: - self.width = max(self.nwell_contact.rx(), self.pwell_contact.rx()) + self.m1_space + 0.5 * contact.m1_via.width + width = max(self.nwell_contact.rx(), self.pwell_contact.rx()) + self.m1_space + 0.5 * contact.m1_via.width # Height is an input parameter, so it is not recomputed. else: max_active_xoffset = self.find_highest_layer_coords("active").x max_route_xoffset = self.find_highest_layer_coords(self.route_layer).x + 0.5 * self.m1_space - self.width = max(max_active_xoffset, max_route_xoffset) - - self.well_width = self.width + 2 * self.nwell_enclose_active + width = max(max_active_xoffset, max_route_xoffset) + + self.width = width @staticmethod def bin_width(tx_type, target_width): diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 214e66dc..465f7a58 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -60,14 +60,14 @@ class pinv(pgate.pgate): self.add_well_contacts() self.determine_width() self.extend_wells() - self.route_supply_rails() - self.connect_rails() self.route_input_gate(self.pmos_inst, self.nmos_inst, self.output_pos.y, "A", position="farleft") self.route_outputs() + self.route_supply_rails() + self.connect_rails() self.add_boundary() def add_pins(self): diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 59995133..51581e61 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -5,7 +5,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -import contact import pgate import debug from tech import drc, parameter, spice diff --git a/compiler/pgates/single_level_column_mux.py b/compiler/pgates/single_level_column_mux.py index 9e38287f..e1d19534 100644 --- a/compiler/pgates/single_level_column_mux.py +++ b/compiler/pgates/single_level_column_mux.py @@ -50,7 +50,7 @@ class single_level_column_mux(pgate.pgate): self.connect_poly() self.add_bitline_pins() self.connect_bitlines() - self.add_wells() + self.add_pn_wells() def add_modules(self): self.bitcell = factory.create(module_type="bitcell") @@ -218,7 +218,7 @@ class single_level_column_mux(pgate.pgate): self.add_path(self.col_mux_stack[2], [br_pin.bc(), mid1, mid2, nmos_lower_d_pin.center()]) - def add_wells(self): + def add_pn_wells(self): """ Add a well and implant over the whole cell. Also, add the pwell contact (if it exists) diff --git a/compiler/tests/04_pnor2_test.py b/compiler/tests/04_pnor2_test.py index 1e8abaa4..ea0d6dbc 100755 --- a/compiler/tests/04_pnor2_test.py +++ b/compiler/tests/04_pnor2_test.py @@ -25,10 +25,6 @@ class pnor2_test(openram_test): tx = factory.create(module_type="pnor2", size=1) self.local_check(tx) - debug.info(2, "Checking 2-input nor gate") - tx = factory.create(module_type="pnor2", size=1, add_wells=False) - self.local_drc_check(tx) - globals.end_openram() # run the test from the command line diff --git a/compiler/tests/04_single_level_column_mux_pbitcell_test.py b/compiler/tests/04_single_level_column_mux_pbitcell_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/05_replica_bitcell_array_test.py b/compiler/tests/05_replica_bitcell_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/07_single_level_column_mux_array_pbitcell_test.py b/compiler/tests/07_single_level_column_mux_array_pbitcell_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/08_wordline_driver_pbitcell_test.py b/compiler/tests/08_wordline_driver_pbitcell_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/09_sense_amp_array_test_pbitcell.py b/compiler/tests/09_sense_amp_array_test_pbitcell.py old mode 100644 new mode 100755 diff --git a/compiler/tests/10_write_driver_array_pbitcell_test.py b/compiler/tests/10_write_driver_array_pbitcell_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/10_write_driver_array_wmask_pbitcell_test.py b/compiler/tests/10_write_driver_array_wmask_pbitcell_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/10_write_mask_and_array_pbitcell_test.py b/compiler/tests/10_write_mask_and_array_pbitcell_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/19_bank_select_pbitcell_test.py b/compiler/tests/19_bank_select_pbitcell_test.py old mode 100644 new mode 100755