From ffcf58100ef6a1e33b82205c78312c9b3707cd43 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 2 Feb 2018 15:17:21 -0800 Subject: [PATCH] Clean up column mux by moving pins to own function. Adjust spacing between column mux and bitcell to prevent DRCs. Fix up find lowest/highest functions when no objects or instances in a module. --- compiler/bank.py | 4 +- compiler/hierarchy_layout.py | 45 ++++++++++++---- compiler/single_level_column_mux.py | 17 +++---- compiler/single_level_column_mux_array.py | 62 +++++++++++++---------- 4 files changed, 78 insertions(+), 50 deletions(-) diff --git a/compiler/bank.py b/compiler/bank.py index c792ee23..f57cce99 100644 --- a/compiler/bank.py +++ b/compiler/bank.py @@ -99,8 +99,8 @@ class bank(design.design): self.add_precharge_array() if self.col_addr_size > 0: + self.column_mux_height = self.column_mux_array.height + 0.5*self.m2_width self.add_column_mux_array() - self.column_mux_height = self.column_mux_array.height else: self.column_mux_height = 0 if self.col_addr_size > 1: # size 1 is from addr FF @@ -249,7 +249,7 @@ class bank(design.design): def add_column_mux_array(self): """ Adding Column Mux when words_per_row > 1 . """ - y_offset = self.column_mux_array.height + y_offset = self.column_mux_height self.col_mux_array_inst=self.add_inst(name="column_mux_array", mod=self.column_mux_array, offset=vector(0,y_offset).scale(-1,-1)) diff --git a/compiler/hierarchy_layout.py b/compiler/hierarchy_layout.py index dc923d44..60a9b24a 100644 --- a/compiler/hierarchy_layout.py +++ b/compiler/hierarchy_layout.py @@ -60,21 +60,44 @@ class layout(lef.lef): def find_lowest_coords(self): """Finds the lowest set of 2d cartesian coordinates within this layout""" - - lowestx1 = min(obj.lx() for obj in self.objs if obj.name!="label") - lowesty1 = min(obj.by() for obj in self.objs if obj.name!="label") - lowestx2 = min(inst.lx() for inst in self.insts) - lowesty2 = min(inst.by() for inst in self.insts) - return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2)) + + if len(self.objs)>0: + lowestx1 = min(obj.lx() for obj in self.objs if obj.name!="label") + lowesty1 = min(obj.by() for obj in self.objs if obj.name!="label") + else: + lowestx1=lowesty1=None + if len(self.insts)>0: + lowestx2 = min(inst.lx() for inst in self.insts) + lowesty2 = min(inst.by() for inst in self.insts) + else: + lowestx2=lowesty2=None + if lowestx1==None: + return vector(lowestx2,lowesty2) + elif lowestx2==None: + return vector(lowestx1,lowesty1) + else: + return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2)) def find_highest_coords(self): """Finds the highest set of 2d cartesian coordinates within this layout""" - highestx1 = min(obj.rx() for obj in self.objs if obj.name!="label") - highesty1 = min(obj.uy() for obj in self.objs if obj.name!="label") - highestx2 = min(inst.rx() for inst in self.insts) - highesty2 = min(inst.uy() for inst in self.insts) - return vector(min(highestx1, highestx2), min(highesty1, highesty2)) + + if len(self.objs)>0: + highestx1 = max(obj.rx() for obj in self.objs if obj.name!="label") + highesty1 = max(obj.uy() for obj in self.objs if obj.name!="label") + else: + highestx1=highesty1=None + if len(self.insts)>0: + highestx2 = max(inst.rx() for inst in self.insts) + highesty2 = max(inst.uy() for inst in self.insts) + else: + highestx2=highesty2=None + if highestx1==None: + return vector(highestx2,highesty2) + elif highestx2==None: + return vector(highestx1,highesty1) + else: + return vector(max(highestx1, highestx2), max(highesty1, highesty2)) def translate_all(self, offset): diff --git a/compiler/single_level_column_mux.py b/compiler/single_level_column_mux.py index 3358190e..8b8fd994 100644 --- a/compiler/single_level_column_mux.py +++ b/compiler/single_level_column_mux.py @@ -28,9 +28,9 @@ class single_level_column_mux(design.design): def create_layout(self): self.add_ptx() - + self.pin_height = 2*self.m2_width self.width = self.bitcell.width - self.height = self.nmos2.uy() + self.height = self.nmos2.uy() + self.pin_height self.connect_poly() self.add_gnd_rail() self.add_bitline_pins() @@ -43,26 +43,25 @@ class single_level_column_mux(design.design): bl_pos = vector(self.bitcell.get_pin("BL").lx(), 0) br_pos = vector(self.bitcell.get_pin("BR").lx(), 0) - pin_height = 2*self.m2_width # bl and br self.add_layout_pin(text="bl", layer="metal2", - offset=bl_pos + vector(0,self.height - pin_height), - height=pin_height) + offset=bl_pos + vector(0,self.height - self.pin_height), + height=self.pin_height) self.add_layout_pin(text="br", layer="metal2", - offset=br_pos + vector(0,self.height - pin_height), - height=pin_height) + offset=br_pos + vector(0,self.height - self.pin_height), + height=self.pin_height) # bl_out and br_out self.add_layout_pin(text="bl_out", layer="metal2", offset=bl_pos, - height=pin_height) + height=self.pin_height) self.add_layout_pin(text="br_out", layer="metal2", offset=br_pos, - height=pin_height) + height=self.pin_height) def add_ptx(self): diff --git a/compiler/single_level_column_mux_array.py b/compiler/single_level_column_mux_array.py index fcdbcbc4..61e2d533 100644 --- a/compiler/single_level_column_mux_array.py +++ b/compiler/single_level_column_mux_array.py @@ -40,8 +40,14 @@ class single_level_column_mux_array(design.design): self.setup_layout_constants() self.create_array() self.add_routing() + # Find the highest shapes to determine height before adding well + highest = self.find_highest_coords() + self.height = highest.y + self.add_layout_pins() self.add_enclosure(self.mux_inst, "pwell") + + def add_modules(self): # FIXME: Why is this 8x? self.mux = single_level_column_mux(tx_size=8) @@ -51,16 +57,11 @@ class single_level_column_mux_array(design.design): def setup_layout_constants(self): self.column_addr_size = num_of_inputs = int(self.words_per_row / 2) self.width = self.columns * self.mux.width - self.m1_pitch = contact.m1m2.width + max(drc["metal1_to_metal1"],drc["metal2_to_metal2"]) - # To correct the offset between M1 and M2 via enclosures - self.offset_fix = vector(0,0.5*(drc["minwidth_metal2"]-drc["minwidth_metal1"])) # one set of metal1 routes for select signals and a pair to interconnect the mux outputs bl/br # one extra route pitch is to space from the sense amp self.route_height = (self.words_per_row + 3)*self.m1_pitch - # mux height plus routing signal height plus well spacing at the top - self.height = self.mux.height + self.route_height + drc["pwell_to_nwell"] def create_array(self): @@ -73,28 +74,6 @@ class single_level_column_mux_array(design.design): self.mux_inst.append(self.add_inst(name=name, mod=self.mux, offset=x_off)) - - offset = self.mux_inst[-1].get_pin("bl").ll() - self.add_layout_pin(text="bl[{}]".format(col_num), - layer="metal2", - offset=offset, - height=self.height-offset.y) - - offset = self.mux_inst[-1].get_pin("br").ll() - self.add_layout_pin(text="br[{}]".format(col_num), - layer="metal2", - offset=offset, - height=self.height-offset.y) - - gnd_pins = self.mux_inst[-1].get_pins("gnd") - for gnd_pin in gnd_pins: - # only do even colums to avoid duplicates - offset = gnd_pin.ll() - if col_num % 2 == 0: - self.add_layout_pin(text="gnd", - layer="metal2", - offset=offset.scale(1,0), - height=self.height) self.connect_inst(["bl[{}]".format(col_num), "br[{}]".format(col_num), @@ -103,7 +82,34 @@ class single_level_column_mux_array(design.design): "sel[{}]".format(col_num % self.words_per_row), "gnd"]) - + + def add_layout_pins(self): + """ Add the pins after we determine the height. """ + # For every column, add a pass gate + for col_num in range(self.columns): + mux_inst = self.mux_inst[col_num] + offset = mux_inst.get_pin("bl").ll() + self.add_layout_pin(text="bl[{}]".format(col_num), + layer="metal2", + offset=offset, + height=self.height-offset.y) + + offset = mux_inst.get_pin("br").ll() + self.add_layout_pin(text="br[{}]".format(col_num), + layer="metal2", + offset=offset, + height=self.height-offset.y) + + gnd_pins = mux_inst.get_pins("gnd") + for gnd_pin in gnd_pins: + # only do even colums to avoid duplicates + offset = gnd_pin.ll() + if col_num % 2 == 0: + self.add_layout_pin(text="gnd", + layer="metal2", + offset=offset.scale(1,0), + height=self.height) + def add_routing(self): self.add_horizontal_input_rail()