From 0214cfb48e335e77684b37eec536002772d71b10 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 30 Nov 2017 11:56:40 -0800 Subject: [PATCH] Fix single finger ptx bugs. --- compiler/bank.py | 4 +- compiler/geometry.py | 2 +- compiler/hierarchy_layout.py | 4 +- compiler/pinv.py | 31 ++++++++------- compiler/ptx.py | 73 +++++++++++++----------------------- compiler/wordline_driver.py | 4 +- 6 files changed, 49 insertions(+), 69 deletions(-) diff --git a/compiler/bank.py b/compiler/bank.py index 19c1f77b..c1828352 100644 --- a/compiler/bank.py +++ b/compiler/bank.py @@ -512,7 +512,7 @@ class bank(design.design): bank_sel_line_pos = vector(xoffset_bank_sel + 0.5*self.m2_width, self.min_point) bank_sel_pin_pos=vector(self.left_vdd_x_offset, self.min_point) - self.add_center_layout_pin_segment(text="bank_sel", + self.add_layout_pin_center_segment(text="bank_sel", layer="metal3", start=bank_sel_pin_pos, end=bank_sel_line_pos) @@ -629,7 +629,7 @@ class bank(design.design): offset=logic_pos, rotate=90) - self.add_center_layout_pin_segment(text=input_name, + self.add_layout_pin_center_segment(text=input_name, layer="metal3", start=input_pos, end=logic_pos) diff --git a/compiler/geometry.py b/compiler/geometry.py index c00f04fd..eb5188aa 100644 --- a/compiler/geometry.py +++ b/compiler/geometry.py @@ -148,7 +148,7 @@ class instance(geometry): def __str__(self): """ override print function output """ - return "inst: " + self.name + " mod=" + self.mod.name + return "inst: " + self.name + " mod=" + self.mod.name def __repr__(self): """ override print function output """ diff --git a/compiler/hierarchy_layout.py b/compiler/hierarchy_layout.py index 3a817116..53c53ee2 100644 --- a/compiler/hierarchy_layout.py +++ b/compiler/hierarchy_layout.py @@ -174,7 +174,7 @@ class layout: new_name = pin.name self.add_layout_pin(new_name, pin.layer, pin.ll(), pin.width(), pin.height()) - def add_center_layout_pin_segment(self, text, layer, start, end): + def add_layout_pin_center_segment(self, text, layer, start, end): """ Creates a path like pin with center-line convention """ debug.check(start.x==end.x or start.y==end.y,"Cannot have a non-manhatten layout pin.") @@ -198,7 +198,7 @@ class layout: return self.add_layout_pin(text, layer, ll_offset, width, height) - def add_center_layout_pin_rect(self, text, layer, offset, width=None, height=None): + def add_layout_pin_center_rect(self, text, layer, offset, width=None, height=None): """ Creates a path like pin with center-line convention """ if width==None: width=drc["minwidth_{0}".format(layer)] diff --git a/compiler/pinv.py b/compiler/pinv.py index 4509a634..82fb3812 100644 --- a/compiler/pinv.py +++ b/compiler/pinv.py @@ -142,6 +142,7 @@ class pinv(design.design): connect_poly=True, connect_active=True) self.add_mod(self.nmos) + self.pmos = ptx(width=self.pmos_width, mults=self.tx_mults, tx_type="pmos", @@ -151,12 +152,12 @@ class pinv(design.design): def add_supply_rails(self): """ Add vdd/gnd rails to the top and bottom. """ - self.add_center_layout_pin_rect(text="gnd", + self.add_layout_pin_center_rect(text="gnd", layer="metal1", offset=vector(0.5*self.width,0), width=self.width) - self.add_center_layout_pin_rect(text="vdd", + self.add_layout_pin_center_rect(text="vdd", layer="metal1", offset=vector(0.5*self.width,self.height), width=self.width) @@ -168,7 +169,6 @@ class pinv(design.design): """ # place PMOS so it is half a poly spacing down from the top - # Source should overlap rail if it is fingered! pmos_position = vector(0,self.height-self.pmos.height-0.5*drc["poly_to_poly"]) self.pmos_inst=self.add_inst(name="pinv_pmos", mod=self.pmos, @@ -176,7 +176,6 @@ class pinv(design.design): self.connect_inst(["Z", "A", "vdd", "vdd"]) # place NMOS so that it is half a poly spacing up from the bottom - # Source should overlap rail if it is fingered! nmos_position = vector(0,self.nmos.height+0.5*drc["poly_to_poly"]) self.nmos_inst=self.add_inst(name="pinv_nmos", mod=self.nmos, @@ -256,28 +255,28 @@ class pinv(design.design): nmos_gate_pin = self.nmos_inst.get_pin("G") pmos_gate_pin = self.pmos_inst.get_pin("G") - # Pick point in center of NMOS and connect down to PMOS + # Pick point on the left of NMOS and connect down to PMOS nmos_gate_pos = nmos_gate_pin.ll() + vector(0.5*drc["minwidth_poly"],0) pmos_gate_pos = vector(nmos_gate_pos.x,pmos_gate_pin.bc().y) self.add_path("poly",[nmos_gate_pos,pmos_gate_pos]) - # The midpoint of the vertical poly gate - mid_gate_offset = vector(nmos_gate_pos.x,self.middle_position.y) - contact_offset = mid_gate_offset - vector(0.5*self.poly_contact.height,0) + # Add the via to the cell midpoint along the gate + left_gate_offset = vector(nmos_gate_pin.lx(),self.middle_position.y) + contact_offset = left_gate_offset - vector(0.5*self.poly_contact.height,0) self.add_center_contact(layers=("poly", "contact", "metal1"), offset=contact_offset, rotate=90) - self.add_center_layout_pin_segment(text="A", + self.add_layout_pin_center_segment(text="A", layer="metal1", - start=mid_gate_offset.scale(0,1), - end=mid_gate_offset) + start=left_gate_offset.scale(0,1), + end=left_gate_offset) # This is to ensure that the contact is connected to the gate - mid_point = contact_offset.scale(0.5,1)+mid_gate_offset.scale(0.5,0) + mid_point = contact_offset.scale(0.5,1)+left_gate_offset.scale(0.5,0) self.add_center_rect(layer="poly", offset=mid_point, height=self.poly_contact.first_layer_width, - width=mid_gate_offset.x-contact_offset.x) + width=left_gate_offset.x-contact_offset.x) def route_output_drain(self): @@ -299,7 +298,7 @@ class pinv(design.design): if self.route_output == True: # This extends the output to the edge of the cell output_offset = mid_drain_offset.scale(0,1) + vector(self.width,0) - self.add_center_layout_pin_segment(text="Z", + self.add_layout_pin_center_segment(text="Z", layer="metal1", start=mid_drain_offset, end=output_offset) @@ -375,8 +374,8 @@ class pinv(design.design): # Only if they don't overlap already if gnd_pin.uy() < nmos_source_pin.by(): self.add_rect(layer="metal1", - offset=nmos__pin.ll(), - height=nmos_source_pin.by()-gnd_pin.uy(), + offset=nmos_source_pin.ll(), + height=-1*nmos_source_pin.by(), width=nmos_source_pin.width()) pmos_source_pin = self.pmos_inst.get_pin("S") diff --git a/compiler/ptx.py b/compiler/ptx.py index d1db37d8..76d9f16b 100644 --- a/compiler/ptx.py +++ b/compiler/ptx.py @@ -47,9 +47,6 @@ class ptx(design.design): # but this may be uncommented for debug purposes #self.DRC() - def add_pins(self): - """Adds pins for spice netlist""" - self.add_pin_list(["D", "G", "S", "B"]) def create_layout(self): """Calls all functions related to the generation of the layout""" @@ -60,7 +57,7 @@ class ptx(design.design): self.add_active_contacts() def create_spice(self): - self.add_pins() + self.add_pin_list(["D", "G", "S", "B"]) self.spice.append("\n.SUBCKT {0} {1}".format(self.name, " ".join(self.pins))) @@ -160,7 +157,7 @@ class ptx(design.design): and we will add a single horizontal connection. """ # Nothing to do if there's one poly gate - if len(poly_positions) == 1: + if len(poly_positions)<2: return # The width of the poly is from the left-most to right-most poly gate @@ -189,25 +186,25 @@ class ptx(design.design): + drc["metal1_to_metal1"] + 0.5*drc["minwidth_metal1"]) # This is the width of a contact to extend the ends of the pin end_offset = vector(self.active_contact.second_layer_width/2,0) - - if source_positions: # if not an empty set + + if len(source_positions)>1: self.remove_layout_pin("S") # remove the individual connections # Add each vertical segment for a in source_positions: self.add_path(("metal1"), [a,a+pin_offset]) # Add a single horizontal pin - self.add_center_layout_pin_segment(text="S", + self.add_layout_pin_center_segment(text="S", layer="metal1", start=source_positions[0]+pin_offset-end_offset, end=source_positions[-1]+pin_offset+end_offset) - if drain_positions: # if not an empty set + if len(drain_positions)>1: self.remove_layout_pin("D") # remove the individual connections # Add each vertical segment for a in drain_positions: self.add_path(("metal1"), [a,a-pin_offset]) # Add a single horizontal pin - self.add_center_layout_pin_segment(text="D", + self.add_layout_pin_center_segment(text="D", layer="metal1", start=drain_positions[0]-pin_offset-end_offset, end=drain_positions[-1]-pin_offset+end_offset) @@ -223,18 +220,16 @@ class ptx(design.design): poly_positions = [] for i in range(0, self.mults): - if self.connect_poly: - # Add the rectangle in case we remove the pin when joining fingers - self.add_center_rect(layer="poly", - offset=poly_offset, - height=self.poly_height, - width=self.poly_width) - else: - self.add_center_layout_pin_rect(text="G", - layer="poly", - offset=poly_offset, - height=self.poly_height, - width=self.poly_width) + # Add this duplicate rectangle in case we remove the pin when joining fingers + self.add_center_rect(layer="poly", + offset=poly_offset, + height=self.poly_height, + width=self.poly_width) + self.add_layout_pin_center_rect(text="G", + layer="poly", + offset=poly_offset, + height=self.poly_height, + width=self.poly_width) poly_positions.append(poly_offset) poly_offset = poly_offset + vector(self.poly_pitch,0) @@ -306,36 +301,22 @@ class ptx(design.design): contact=self.add_center_contact(layers=("active", "contact", "metal1"), offset=pos, size=(1, self.num_contacts)) - if self.connect_active: - # Add this in case the pins get removed when fingers joined - self.add_center_rect(layer="metal1", - offset=pos, - width=contact.second_layer_width, - height=contact.second_layer_height) - else: - self.add_center_layout_pin_rect(text="S", - layer="metal1", - offset=pos, - width=contact.second_layer_width, - height=contact.second_layer_height) + self.add_layout_pin_center_rect(text="S", + layer="metal1", + offset=pos, + width=contact.second_layer_width, + height=contact.second_layer_height) for pos in drain_positions: contact=self.add_center_contact(layers=("active", "contact", "metal1"), offset=pos, size=(1, self.num_contacts)) - if self.connect_active: - # Add this in case the pins get removed when fingers joined - self.add_center_rect(layer="metal1", - offset=pos, - width=contact.second_layer_width, - height=contact.second_layer_height) - else: - self.add_center_layout_pin_rect(text="D", - layer="metal1", - offset=pos, - width=contact.second_layer_width, - height=contact.second_layer_height) + self.add_layout_pin_center_rect(text="D", + layer="metal1", + offset=pos, + width=contact.second_layer_width, + height=contact.second_layer_height) if self.connect_active: self.connect_fingered_active(drain_positions, source_positions) diff --git a/compiler/wordline_driver.py b/compiler/wordline_driver.py index 892f705d..4a6ba21f 100644 --- a/compiler/wordline_driver.py +++ b/compiler/wordline_driver.py @@ -167,7 +167,7 @@ class wordline_driver(design.design): input_offset = vector(0,a_pos.y) mid_via_offset = vector(clk_offset.x,a_pos.y) + vector(0.5*drc["minwidth_metal2"]+drc["metal2_to_metal2"]+0.5*m1m2_via.width,0) # must under the clk line in M1 - self.add_center_layout_pin_segment(text="in[{0}]".format(row), + self.add_layout_pin_center_segment(text="in[{0}]".format(row), layer="metal1", start=input_offset, end=mid_via_offset) @@ -185,7 +185,7 @@ class wordline_driver(design.design): # output each WL on the right wl_offset = inv2_inst.get_pin("Z").rc() - self.add_center_layout_pin_segment(text="wl[{0}]".format(row), + self.add_layout_pin_center_segment(text="wl[{0}]".format(row), layer="metal1", start=wl_offset, end=wl_offset-vector(drc["minwidth_metal1"],0))