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.

This commit is contained in:
Matt Guthaus 2018-02-02 15:17:21 -08:00
parent 9d043b904e
commit ffcf58100e
4 changed files with 78 additions and 50 deletions

View File

@ -99,8 +99,8 @@ class bank(design.design):
self.add_precharge_array() self.add_precharge_array()
if self.col_addr_size > 0: 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.add_column_mux_array()
self.column_mux_height = self.column_mux_array.height
else: else:
self.column_mux_height = 0 self.column_mux_height = 0
if self.col_addr_size > 1: # size 1 is from addr FF 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): def add_column_mux_array(self):
""" Adding Column Mux when words_per_row > 1 . """ """ 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", self.col_mux_array_inst=self.add_inst(name="column_mux_array",
mod=self.column_mux_array, mod=self.column_mux_array,
offset=vector(0,y_offset).scale(-1,-1)) offset=vector(0,y_offset).scale(-1,-1))

View File

@ -60,21 +60,44 @@ class layout(lef.lef):
def find_lowest_coords(self): def find_lowest_coords(self):
"""Finds the lowest set of 2d cartesian coordinates within """Finds the lowest set of 2d cartesian coordinates within
this layout""" this layout"""
lowestx1 = min(obj.lx() for obj in self.objs if obj.name!="label") if len(self.objs)>0:
lowesty1 = min(obj.by() for obj in self.objs if obj.name!="label") lowestx1 = min(obj.lx() for obj in self.objs if obj.name!="label")
lowestx2 = min(inst.lx() for inst in self.insts) lowesty1 = min(obj.by() for obj in self.objs if obj.name!="label")
lowesty2 = min(inst.by() for inst in self.insts) else:
return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2)) 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): def find_highest_coords(self):
"""Finds the highest set of 2d cartesian coordinates within """Finds the highest set of 2d cartesian coordinates within
this layout""" 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") if len(self.objs)>0:
highestx2 = min(inst.rx() for inst in self.insts) highestx1 = max(obj.rx() for obj in self.objs if obj.name!="label")
highesty2 = min(inst.uy() for inst in self.insts) highesty1 = max(obj.uy() for obj in self.objs if obj.name!="label")
return vector(min(highestx1, highestx2), min(highesty1, highesty2)) 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): def translate_all(self, offset):

View File

@ -28,9 +28,9 @@ class single_level_column_mux(design.design):
def create_layout(self): def create_layout(self):
self.add_ptx() self.add_ptx()
self.pin_height = 2*self.m2_width
self.width = self.bitcell.width self.width = self.bitcell.width
self.height = self.nmos2.uy() self.height = self.nmos2.uy() + self.pin_height
self.connect_poly() self.connect_poly()
self.add_gnd_rail() self.add_gnd_rail()
self.add_bitline_pins() 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) bl_pos = vector(self.bitcell.get_pin("BL").lx(), 0)
br_pos = vector(self.bitcell.get_pin("BR").lx(), 0) br_pos = vector(self.bitcell.get_pin("BR").lx(), 0)
pin_height = 2*self.m2_width
# bl and br # bl and br
self.add_layout_pin(text="bl", self.add_layout_pin(text="bl",
layer="metal2", layer="metal2",
offset=bl_pos + vector(0,self.height - pin_height), offset=bl_pos + vector(0,self.height - self.pin_height),
height=pin_height) height=self.pin_height)
self.add_layout_pin(text="br", self.add_layout_pin(text="br",
layer="metal2", layer="metal2",
offset=br_pos + vector(0,self.height - pin_height), offset=br_pos + vector(0,self.height - self.pin_height),
height=pin_height) height=self.pin_height)
# bl_out and br_out # bl_out and br_out
self.add_layout_pin(text="bl_out", self.add_layout_pin(text="bl_out",
layer="metal2", layer="metal2",
offset=bl_pos, offset=bl_pos,
height=pin_height) height=self.pin_height)
self.add_layout_pin(text="br_out", self.add_layout_pin(text="br_out",
layer="metal2", layer="metal2",
offset=br_pos, offset=br_pos,
height=pin_height) height=self.pin_height)
def add_ptx(self): def add_ptx(self):

View File

@ -40,8 +40,14 @@ class single_level_column_mux_array(design.design):
self.setup_layout_constants() self.setup_layout_constants()
self.create_array() self.create_array()
self.add_routing() 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") self.add_enclosure(self.mux_inst, "pwell")
def add_modules(self): def add_modules(self):
# FIXME: Why is this 8x? # FIXME: Why is this 8x?
self.mux = single_level_column_mux(tx_size=8) 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): def setup_layout_constants(self):
self.column_addr_size = num_of_inputs = int(self.words_per_row / 2) self.column_addr_size = num_of_inputs = int(self.words_per_row / 2)
self.width = self.columns * self.mux.width self.width = self.columns * self.mux.width
self.m1_pitch = contact.m1m2.width + max(drc["metal1_to_metal1"],drc["metal2_to_metal2"]) 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 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 # one extra route pitch is to space from the sense amp
self.route_height = (self.words_per_row + 3)*self.m1_pitch 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): 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, self.mux_inst.append(self.add_inst(name=name,
mod=self.mux, mod=self.mux,
offset=x_off)) 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), self.connect_inst(["bl[{}]".format(col_num),
"br[{}]".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), "sel[{}]".format(col_num % self.words_per_row),
"gnd"]) "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): def add_routing(self):
self.add_horizontal_input_rail() self.add_horizontal_input_rail()