mirror of https://github.com/VLSIDA/OpenRAM.git
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:
parent
9d043b904e
commit
ffcf58100e
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue