Getting single bank to work reliably. Removed tri_gate from bank

for now. Will add it in multibank arrays only. Not needed for
separate DIN and DOUT ports.
This commit is contained in:
Matt Guthaus
2018-07-13 14:45:46 -07:00
parent 834fbac8de
commit f3ae29fe0b
7 changed files with 181 additions and 97 deletions
+37 -22
View File
@@ -66,7 +66,8 @@ class bank(design.design):
# Can remove the following, but it helps for debug!
self.add_lvs_correspondence_points()
self.offset_all_coordinates()
# Remember the bank center for further placement
self.bank_center=self.offset_all_coordinates()
self.DRC_LVS()
@@ -75,7 +76,7 @@ class bank(design.design):
for i in range(self.word_size):
self.add_pin("DOUT[{0}]".format(i),"OUT")
for i in range(self.word_size):
self.add_pin("DIN[{0}]".format(i),"IN")
self.add_pin("BANK_DIN[{0}]".format(i),"IN")
for i in range(self.addr_size):
self.add_pin("A[{0}]".format(i),"INPUT")
@@ -95,8 +96,9 @@ class bank(design.design):
self.route_precharge_to_bitcell_array()
self.route_col_mux_to_bitcell_array()
self.route_sense_amp_to_col_mux_or_bitcell_array()
self.route_sense_amp_to_trigate()
self.route_tri_gate_out()
#self.route_sense_amp_to_trigate()
#self.route_tri_gate_out()
self.route_sense_amp_out()
self.route_wordline_driver()
self.route_write_driver()
self.route_row_decoder()
@@ -119,7 +121,8 @@ class bank(design.design):
self.add_column_mux_array()
self.add_sense_amp_array()
self.add_write_driver_array()
self.add_tri_gate_array()
# Not needed for single bank
#self.add_tri_gate_array()
# To the left of the bitcell array
self.add_row_decoder()
@@ -294,14 +297,15 @@ class bank(design.design):
def add_write_driver_array(self):
""" Adding Write Driver """
y_offset = self.sense_amp_array.height + self.column_mux_height + + self.m2_gap + self.write_driver_array.height
y_offset = self.sense_amp_array.height + self.column_mux_height \
+ self.m2_gap + self.write_driver_array.height
self.write_driver_array_inst=self.add_inst(name="write_driver_array",
mod=self.write_driver_array,
offset=vector(0,y_offset).scale(-1,-1))
temp = []
for i in range(self.word_size):
temp.append("DIN[{0}]".format(i))
temp.append("BANK_DIN[{0}]".format(i))
for i in range(self.word_size):
if (self.words_per_row == 1):
temp.append("bl[{0}]".format(i))
@@ -315,7 +319,7 @@ class bank(design.design):
def add_tri_gate_array(self):
""" data tri gate to drive the data bus """
y_offset = self.sense_amp_array.height+self.column_mux_height \
+ self.write_driver_array.height + self.m2_gap + self.tri_gate_array.height
+ self.m2_gap + self.tri_gate_array.height
self.tri_gate_array_inst=self.add_inst(name="tri_gate_array",
mod=self.tri_gate_array,
offset=vector(0,y_offset).scale(-1,-1))
@@ -443,7 +447,7 @@ class bank(design.design):
self.precharge_array_inst,
self.sense_amp_array_inst,
self.write_driver_array_inst,
self.tri_gate_array_inst,
# self.tri_gate_array_inst,
self.row_decoder_inst,
self.wordline_driver_inst]
# Add these if we use the part...
@@ -492,7 +496,8 @@ class bank(design.design):
#the column decoder (if there is one) or the tristate output
#driver.
# Leave room for the output below the tri gate.
tri_gate_min_y_offset = self.tri_gate_array_inst.by() - 3*self.m2_pitch
#tri_gate_min_y_offset = self.tri_gate_array_inst.by() - 3*self.m2_pitch
write_driver_min_y_offset = self.write_driver_array_inst.by() - 3*self.m2_pitch
row_decoder_min_y_offset = self.row_decoder_inst.by()
if self.col_addr_size > 0:
col_decoder_min_y_offset = self.col_decoder_inst.by()
@@ -502,10 +507,10 @@ class bank(design.design):
if self.num_banks>1:
# The control gating logic is below the decoder
# Min of the control gating logic and tri gate.
self.min_y_offset = min(col_decoder_min_y_offset - self.bank_select.height, tri_gate_min_y_offset)
self.min_y_offset = min(col_decoder_min_y_offset - self.bank_select.height, write_driver_min_y_offset)
else:
# Just the min of the decoder logic logic and tri gate.
self.min_y_offset = min(col_decoder_min_y_offset, tri_gate_min_y_offset)
self.min_y_offset = min(col_decoder_min_y_offset, write_driver_min_y_offset)
# The max point is always the top of the precharge bitlines
# Add a vdd and gnd power rail above the array
@@ -620,6 +625,16 @@ class bank(design.design):
offset=sa_data_out)
self.add_path("metal3",[sa_data_out,tri_gate_in])
def route_sense_amp_out(self):
""" Add pins for the sense amp output """
for i in range(self.word_size):
data_pin = self.sense_amp_array_inst.get_pin("data[{}]".format(i))
self.add_layout_pin_rect_center(text="DOUT[{}]".format(i),
layer="metal2",
offset=data_pin.center(),
height=data_pin.height(),
width=data_pin.width()),
def route_tri_gate_out(self):
""" Metal 3 routing of tri_gate output data """
for i in range(self.word_size):
@@ -647,7 +662,7 @@ class bank(design.design):
for i in range(self.word_size):
data_name = "data[{}]".format(i)
din_name = "DIN[{}]".format(i)
din_name = "BANK_DIN[{}]".format(i)
self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name)
@@ -749,13 +764,13 @@ class bank(design.design):
layer="metal2",
offset=br_pin.center())
# Add the data output names to the sense amp output
for i in range(self.word_size):
data_name = "data[{}]".format(i)
data_pin = self.sense_amp_array_inst.get_pin(data_name)
self.add_label(text="sa_out[{}]".format(i),
layer="metal2",
offset=data_pin.center())
# # Add the data output names to the sense amp output
# for i in range(self.word_size):
# data_name = "data[{}]".format(i)
# data_pin = self.sense_amp_array_inst.get_pin(data_name)
# self.add_label(text="sa_out[{}]".format(i),
# layer="metal2",
# offset=data_pin.center())
# Add labels on the decoder
for i in range(self.word_size):
@@ -775,8 +790,8 @@ class bank(design.design):
# Connection from the central bus to the main control block crosses
# pre-decoder and this connection is in metal3
connection = []
connection.append((self.prefix+"tri_en_bar", self.tri_gate_array_inst.get_pin("en_bar").lc()))
connection.append((self.prefix+"tri_en", self.tri_gate_array_inst.get_pin("en").lc()))
#connection.append((self.prefix+"tri_en_bar", self.tri_gate_array_inst.get_pin("en_bar").lc()))
#connection.append((self.prefix+"tri_en", self.tri_gate_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"clk_buf_bar", self.precharge_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"w_en", self.write_driver_array_inst.get_pin("en").lc()))
connection.append((self.prefix+"s_en", self.sense_amp_array_inst.get_pin("en").lc()))
+27 -28
View File
@@ -18,7 +18,7 @@ class dff_array(design.design):
if name=="":
name = "dff_array_{0}x{1}".format(rows, columns)
design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
debug.info(1, "Creating {0} rows={1} cols={2}".format(self.name, self.rows, self.columns))
from importlib import reload
c = reload(__import__(OPTS.dff))
@@ -38,33 +38,33 @@ class dff_array(design.design):
self.DRC_LVS()
def add_pins(self):
for y in range(self.rows):
for x in range(self.columns):
self.add_pin(self.get_din_name(y,x))
for y in range(self.rows):
for x in range(self.columns):
self.add_pin(self.get_dout_name(y,x))
for row in range(self.rows):
for col in range(self.columns):
self.add_pin(self.get_din_name(row,col))
for row in range(self.rows):
for col in range(self.columns):
self.add_pin(self.get_dout_name(row,col))
self.add_pin("clk")
self.add_pin("vdd")
self.add_pin("gnd")
def create_dff_array(self):
self.dff_insts={}
for y in range(self.rows):
for x in range(self.columns):
name = "Xdff_r{0}_c{1}".format(y,x)
if (y % 2 == 0):
base = vector(x*self.dff.width,y*self.dff.height)
for row in range(self.rows):
for col in range(self.columns):
name = "Xdff_r{0}_c{1}".format(row,col)
if (row % 2 == 0):
base = vector(col*self.dff.width,row*self.dff.height)
mirror = "R0"
else:
base = vector(x*self.dff.width,(y+1)*self.dff.height)
base = vector(col*self.dff.width,(row+1)*self.dff.height)
mirror = "MX"
self.dff_insts[x,y]=self.add_inst(name=name,
self.dff_insts[row,col]=self.add_inst(name=name,
mod=self.dff,
offset=base,
mirror=mirror)
self.connect_inst([self.get_din_name(y,x),
self.get_dout_name(y,x),
self.connect_inst([self.get_din_name(row,col),
self.get_dout_name(row,col),
"clk",
"vdd",
"gnd"])
@@ -91,10 +91,9 @@ class dff_array(design.design):
def add_layout_pins(self):
for y in range(self.rows):
for row in range(self.rows):
# Continous vdd rail along with label.
vdd_pin=self.dff_insts[0,y].get_pin("vdd")
vdd_pin=self.dff_insts[row,0].get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
offset=vdd_pin.ll(),
@@ -102,7 +101,7 @@ class dff_array(design.design):
height=self.m1_width)
# Continous gnd rail along with label.
gnd_pin=self.dff_insts[0,y].get_pin("gnd")
gnd_pin=self.dff_insts[row,0].get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
offset=gnd_pin.ll(),
@@ -110,19 +109,19 @@ class dff_array(design.design):
height=self.m1_width)
for y in range(self.rows):
for x in range(self.columns):
din_pin = self.dff_insts[x,y].get_pin("D")
for row in range(self.rows):
for col in range(self.columns):
din_pin = self.dff_insts[row,col].get_pin("D")
debug.check(din_pin.layer=="metal2","DFF D pin not on metal2")
self.add_layout_pin(text=self.get_din_name(y,x),
self.add_layout_pin(text=self.get_din_name(row,col),
layer=din_pin.layer,
offset=din_pin.ll(),
width=din_pin.width(),
height=din_pin.height())
dout_pin = self.dff_insts[x,y].get_pin("Q")
dout_pin = self.dff_insts[row,col].get_pin("Q")
debug.check(dout_pin.layer=="metal2","DFF Q pin not on metal2")
self.add_layout_pin(text=self.get_dout_name(y,x),
self.add_layout_pin(text=self.get_dout_name(row,col),
layer=dout_pin.layer,
offset=dout_pin.ll(),
width=dout_pin.width(),
@@ -145,8 +144,8 @@ class dff_array(design.design):
offset=vector(0,0),
width=self.width,
height=self.m3_width)
for x in range(self.columns):
clk_pin = self.dff_insts[x,0].get_pin("clk")
for col in range(self.columns):
clk_pin = self.dff_insts[0,col].get_pin("clk")
# Make a vertical strip for each column
self.add_layout_pin(text="clk",
layer="metal2",