From 90d1fa7c4310175c69ef76d84c52f15fd473b91b Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 30 Nov 2018 12:32:13 -0800 Subject: [PATCH] Bitcell supply routing fixes. Flatten and simplify 1rw 1r bitcell. Move bitcell vias to M3 if rotation is limited. Simplify replica bitcell vdd routing. --- compiler/base/hierarchy_layout.py | 30 +++++++++++------- compiler/bitcells/pbitcell.py | 27 ++++++++-------- compiler/modules/bitcell_array.py | 3 +- compiler/modules/replica_bitline.py | 9 +----- technology/freepdk45/gds_lib/cell_1rw_1r.gds | Bin 16384 -> 16384 bytes .../freepdk45/gds_lib/replica_cell_1rw_1r.gds | Bin 16384 -> 16384 bytes 6 files changed, 36 insertions(+), 33 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index e3864b81..9843dcef 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -926,22 +926,30 @@ class layout(lef.lef): - def add_power_pin(self, name, loc, rotate=90, m1_too=True): + def add_power_pin(self, name, loc, rotate=90, start_layer="metal1"): """ - Add a single power pin from M3 down to M1 at the given center location + Add a single power pin from M3 down to M1 at the given center location. + The starting layer is specified to determine which vias are needed. """ - if m1_too: + + if start_layer=="metal1": self.add_via_center(layers=("metal1", "via1", "metal2"), offset=loc, rotate=float(rotate)) - via=self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=loc, - rotate=float(rotate)) - self.add_layout_pin_rect_center(text=name, - layer="metal3", - offset=loc, - width=via.width, - height=via.height) + if start_layer=="metal1" or start_layer=="metal2": + via=self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=loc, + rotate=float(rotate)) + if start_layer=="metal3": + self.add_layout_pin_rect_center(text=name, + layer="metal3", + offset=loc) + else: + self.add_layout_pin_rect_center(text=name, + layer="metal3", + offset=loc, + width=via.width, + height=via.height) def add_power_ring(self, bbox): """ diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index d858b609..d9d2ef7a 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -80,7 +80,7 @@ class pbitcell(design.design): self.offset_all_coordinates() gnd_overlap = vector(0, 0.5*contact.well.width) self.translate_all(gnd_overlap) - self.DRC_LVS() + def add_pins(self): """ add pins and set names for bitlines and wordlines """ @@ -323,20 +323,21 @@ class pbitcell(design.design): # Add rails for vdd and gnd gnd_ypos = self.rowline_offset - self.total_ports*self.rowline_spacing self.gnd_position = vector(0, gnd_ypos) - self.gnd = self.add_layout_pin_rect_center(text="gnd", - layer="metal1", - offset=self.gnd_position, - width=self.width, - height=self.m1_width) - + self.add_rect_center(layer="metal1", + offset=self.gnd_position, + width=self.width, + height=self.m1_width) + self.add_power_pin("gnd", vector(0,gnd_ypos)) + + vdd_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height + self.inverter_gap + self.inverter_pmos.active_height + self.vdd_offset self.vdd_position = vector(0, vdd_ypos) - self.vdd = self.add_layout_pin_rect_center(text="vdd", - layer="metal1", - offset=self.vdd_position, - width=self.width, - height=self.m1_width) - + self.add_rect_center(layer="metal1", + offset=self.vdd_position, + width=self.width, + height=self.m1_width) + self.add_power_pin("vdd", vector(0,vdd_ypos)) + def create_readwrite_ports(self): """ Creates read/write ports to the bit cell. A differential pair of transistor can both read and write, like in a 6T cell. diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index e9d9446d..792fd9ae 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -138,7 +138,8 @@ class bitcell_array(design.design): inst = self.cell_inst[row,col] for pin_name in ["vdd", "gnd"]: for pin in inst.get_pins(pin_name): - self.add_power_pin(pin_name, pin.center(), 0, pin.layer=="metal1") + self.add_power_pin(pin_name, pin.center(), 0, pin.layer) + def analytical_delay(self, slew, load=0): from tech import drc diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index e349fa89..dcbc53d4 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -265,15 +265,8 @@ class replica_bitline(design.design): pin = self.rbl_inv_inst.get_pin("vdd") self.add_power_pin("vdd", pin.lc()) - # Replica bitcell needs to be routed up to M3 pin=self.rbc_inst.get_pin("vdd") - # Don't rotate this via to vit in FreePDK45. In the custom cell, the pin cannot be placed - # directly on vdd or there will be a drc error with a wordline. Place the pin slightly farther - # away then route to it. A better solution would be to rotate the m1 in the via or move the pin - # a m1_pitch below the entire cell. - pin_extension = pin.center() - vector(0,self.m1_pitch) - self.add_power_pin("vdd", pin_extension, rotate=0) - self.add_path("metal1", [pin.center(), pin_extension]) + self.add_power_pin("vdd", pin.center(), 0, pin.layer) for pin in self.rbc_inst.get_pins("gnd"): self.add_power_pin("gnd", pin.center()) diff --git a/technology/freepdk45/gds_lib/cell_1rw_1r.gds b/technology/freepdk45/gds_lib/cell_1rw_1r.gds index fe12fc729b64479255fb28bbf2bad3acd31eec47..00dc1855dd663a1921d5fe9295b40a703c754ad7 100644 GIT binary patch literal 16384 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 YYtewxfsO|{9_Vfviw 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 literal 16384 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