From f0ecf385e883420ddea567543f308de041e9a4c0 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 6 Feb 2020 16:20:09 +0000 Subject: [PATCH] Nwell fixes in pgates. Fix minor PEP8 format fixes. Fix nwell to be 55% of cell height. Move contact in hierarchical decoder for DRC error. --- compiler/modules/hierarchical_decoder.py | 14 +++----------- compiler/modules/hierarchical_predecode.py | 10 ++++------ compiler/pgates/pgate.py | 18 ++++++++++-------- compiler/pgates/pinv.py | 10 +++++----- compiler/pgates/pnand2.py | 7 ++----- compiler/pgates/pnand3.py | 11 +++-------- compiler/pgates/pnor2.py | 5 +---- compiler/pgates/precharge.py | 2 +- compiler/pgates/pwrite_driver.py | 5 ++--- 9 files changed, 31 insertions(+), 51 deletions(-) diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index f83035ce..242ef476 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -5,18 +5,14 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -from tech import drc import debug import design -from math import log -from math import sqrt -from math import ceil import math -import contact from sram_factory import factory from vector import vector from globals import OPTS + class hierarchical_decoder(design.design): """ Dynamically generated hierarchical decoder. @@ -34,13 +30,12 @@ class hierarchical_decoder(design.design): self.cell_height = b.height self.rows = rows self.num_inputs = math.ceil(math.log(self.rows, 2)) - (self.no_of_pre2x4,self.no_of_pre3x8)=self.determine_predecodes(self.num_inputs) + (self.no_of_pre2x4, self.no_of_pre3x8)=self.determine_predecodes(self.num_inputs) self.create_netlist() if not OPTS.netlist_only: self.create_layout() - def create_netlist(self): self.add_modules() self.setup_netlist_constants() @@ -308,7 +303,6 @@ class hierarchical_decoder(design.design): base= vector(-self.pre2_4.width, num * self.pre2_4.height) self.pre2x4_inst[num].place(base) - def place_pre3x8(self,num): """ Place 3x8 predecoder to the left of the origin and above any 2x4 decoders """ @@ -321,7 +315,6 @@ class hierarchical_decoder(design.design): self.pre3x8_inst[num].place(offset) - def create_row_decoder(self): """ Create the row-decoder by placing NAND2/NAND3 and Inverters and add the primary decoder output pins. """ @@ -329,7 +322,6 @@ class hierarchical_decoder(design.design): self.create_decoder_nand_array() self.create_decoder_inv_array() - def create_decoder_nand_array(self): """ Add a column of NAND gates for final decode """ @@ -556,7 +548,7 @@ class hierarchical_decoder(design.design): """ Add a pin for each row of vdd/gnd which are must-connects next level up. """ # The vias will be placed in the center and right of the cells, respectively. - xoffset = self.nand_inst[0].cx() + xoffset = self.nand_inst[0].rx() for num in range(0,self.rows): for pin_name in ["vdd", "gnd"]: # The nand and inv are the same height rows... diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index 78e9af7f..88bae534 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -8,12 +8,11 @@ import debug import design import math -from tech import drc import contact from vector import vector -from globals import OPTS from sram_factory import factory + class hierarchical_predecode(design.design): """ Pre 2x4 and 3x8 decoder shared code. @@ -42,7 +41,7 @@ class hierarchical_predecode(design.design): self.add_nand(self.number_of_inputs) self.add_mod(self.nand) - def add_nand(self,inputs): + def add_nand(self, inputs): """ Create the NAND for the predecode input stage """ if inputs==2: self.nand = factory.create(module_type="pnand2", @@ -51,7 +50,7 @@ class hierarchical_predecode(design.design): self.nand = factory.create(module_type="pnand3", height=self.cell_height) else: - debug.error("Invalid number of predecode inputs: {}".format(inputs),-1) + debug.error("Invalid number of predecode inputs: {}".format(inputs), -1) def setup_layout_constraints(self): @@ -89,7 +88,6 @@ class hierarchical_predecode(design.design): names=decode_names, length=self.height - 2*self.m1_width) - def create_input_inverters(self): """ Create the input inverters to invert input signals for the decode stage. """ self.in_inst = [] @@ -266,7 +264,7 @@ class hierarchical_predecode(design.design): """ Add a pin for each row of vdd/gnd which are must-connects next level up. """ # Find the x offsets for where the vias/pins should be placed - in_xoffset = self.in_inst[0].rx() + in_xoffset = self.in_inst[0].rx() + self.m1_space out_xoffset = self.inv_inst[0].lx() - self.m1_space for num in range(0,self.number_of_outputs): # this will result in duplicate polygons for rails, but who cares diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index c13939f1..e0401726 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -11,7 +11,6 @@ import debug from tech import layer from vector import vector from globals import OPTS -from sram_factory import factory class pgate(design.design): @@ -29,7 +28,7 @@ class pgate(design.design): elif not height: # By default, we make it 8 M1 pitch tall self.height = 8*self.m1_pitch - + self.create_netlist() if not OPTS.netlist_only: self.create_layout() @@ -125,17 +124,20 @@ class pgate(design.design): height=contact.poly_contact.first_layer_width, width=left_gate_offset.x - contact_offset.x) - def extend_wells(self, middle_position): + def extend_wells(self): """ Extend the n/p wells to cover whole cell """ + # This should match the cells in the cell library + nwell_y_offset = 0.48 * self.height + full_height = self.height + 0.5*self.m1_width + # FIXME: float rounding problem - middle_position = middle_position.snap_to_grid() if "nwell" in layer: # 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 - vector(self.well_extend_active, 0) - nwell_height = nwell_max_offset - middle_position.y + full_height) + nwell_position = vector(0, nwell_y_offset) - vector(self.well_extend_active, 0) + nwell_height = nwell_max_offset - nwell_y_offset self.add_rect(layer="nwell", offset=nwell_position, width=self.well_width, @@ -151,7 +153,7 @@ class pgate(design.design): pwell_min_offset = min(self.find_lowest_layer_coords("pwell").y, -0.5 * self.m1_width) pwell_position = vector(-self.well_extend_active, pwell_min_offset) - pwell_height = middle_position.y - pwell_position.y + pwell_height = nwell_y_offset - pwell_position.y self.add_rect(layer="pwell", offset=pwell_position, width=self.well_width, diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index c0336956..c0f1f955 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -54,7 +54,7 @@ class pinv(pgate.pgate): self.setup_layout_constants() self.place_ptx() self.add_well_contacts() - self.extend_wells(self.well_pos) + self.extend_wells() self.route_supply_rails() self.connect_rails() self.route_input_gate(self.pmos_inst, @@ -154,8 +154,11 @@ class pinv(pgate.pgate): # 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 \ - + contact.nwell_contact.width + self.active_space + 0.5 * self.nwell_enclose_active + + 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. @@ -225,9 +228,6 @@ class pinv(pgate.pgate): nmos_drain_pos = self.nmos_inst.get_pin("D").ul() self.output_pos = vector(0, 0.5 * (pmos_drain_pos.y + nmos_drain_pos.y)) - # This will help with the wells - self.well_pos = self.output_pos - def route_outputs(self): """ Route the output (drains) together. diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 2f539c16..8d3e0582 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -53,7 +53,7 @@ class pnand2(pgate.pgate): self.place_ptx() self.connect_rails() self.add_well_contacts() - self.extend_wells(self.well_pos) + self.extend_wells() self.route_inputs() self.route_output() @@ -110,7 +110,7 @@ class pnand2(pgate.pgate): extra_contact_space = max(-self.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) def route_supply_rails(self): """ Add vdd/gnd rails to the top and bottom. """ @@ -170,9 +170,6 @@ class pnand2(pgate.pgate): self.output_pos = vector(0, 0.5 * (pmos1_pos.y + nmos1_pos.y + self.nmos.active_height)) - # This will help with the wells - self.well_pos = self.output_pos - def add_well_contacts(self): """ Add n/p well taps to the layout and connect to supplies diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index d5b07069..88b02d92 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -61,7 +61,7 @@ class pnand3(pgate.pgate): self.place_ptx() self.connect_rails() self.add_well_contacts() - self.extend_wells(self.well_pos) + self.extend_wells() self.route_inputs() self.route_output() @@ -102,10 +102,8 @@ class pnand3(pgate.pgate): nmos = factory.create(module_type="ptx", tx_type="nmos") 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.top_bottom_space = max(0.5 * self.m1_width + self.m1_space + extra_contact_space, + self.poly_extend_active + self.poly_space) def route_supply_rails(self): """ Add vdd/gnd rails to the top and bottom. """ @@ -179,9 +177,6 @@ class pnand3(pgate.pgate): # This will help with the wells and the input/output placement self.output_pos = vector(0, 0.5*self.height) - # This should be placed at the top of the NMOS well - self.well_pos = self.output_pos - def add_well_contacts(self): """ Add n/p well taps to the layout and connect to supplies """ diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index 7ceab71a..d6605d68 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -52,7 +52,7 @@ class pnor2(pgate.pgate): self.place_ptx() self.connect_rails() self.add_well_contacts() - self.extend_wells(self.well_pos) + self.extend_wells() self.route_inputs() self.route_output() @@ -168,9 +168,6 @@ class pnor2(pgate.pgate): self.output_pos = vector(0, 0.5 * (pmos1_pos.y + nmos1_pos.y + self.nmos.active_height)) - # This will help with the wells - self.well_pos = self.output_pos - def add_well_contacts(self): """ Add n/p well taps to the layout and connect to supplies """ diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index 888304ce..28b4d85a 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -8,7 +8,7 @@ import contact import design import debug -from tech import drc, parameter +from tech import parameter from vector import vector from globals import OPTS from sram_factory import factory diff --git a/compiler/pgates/pwrite_driver.py b/compiler/pgates/pwrite_driver.py index ed970f9b..16830e62 100644 --- a/compiler/pgates/pwrite_driver.py +++ b/compiler/pgates/pwrite_driver.py @@ -6,14 +6,13 @@ #All rights reserved. # import design -from tech import drc, parameter, spice +from tech import parameter import debug -import math -from tech import drc from vector import vector from globals import OPTS from sram_factory import factory + class pwrite_driver(design.design): """ The pwrite_driver is two tristate inverters that drive the bitlines.