mirror of https://github.com/VLSIDA/OpenRAM.git
Altered bank to accommodate multiport. Single port still works, though some of the control signal names have been changes to have a following 0 (e.g. s_en to s_en0). Multiport does not pass drc yet, but can generate an accurate spice netlist.
This commit is contained in:
parent
a5af4a2b9c
commit
e592d95146
|
|
@ -43,6 +43,10 @@ class bank(design.design):
|
||||||
self.words_per_row = words_per_row
|
self.words_per_row = words_per_row
|
||||||
self.num_banks = num_banks
|
self.num_banks = num_banks
|
||||||
|
|
||||||
|
self.total_write = OPTS.rw_ports + OPTS.w_ports
|
||||||
|
self.total_read = OPTS.rw_ports + OPTS.r_ports
|
||||||
|
self.total_ports = OPTS.rw_ports + OPTS.w_ports + OPTS.r_ports
|
||||||
|
|
||||||
# The local control signals are gated when we have bank select logic,
|
# The local control signals are gated when we have bank select logic,
|
||||||
# so this prefix will be added to all of the input signals to create
|
# so this prefix will be added to all of the input signals to create
|
||||||
# the internal gated signals.
|
# the internal gated signals.
|
||||||
|
|
@ -64,7 +68,7 @@ class bank(design.design):
|
||||||
|
|
||||||
|
|
||||||
# Can remove the following, but it helps for debug!
|
# Can remove the following, but it helps for debug!
|
||||||
self.add_lvs_correspondence_points()
|
#self.add_lvs_correspondence_points()
|
||||||
|
|
||||||
# Remember the bank center for further placement
|
# Remember the bank center for further placement
|
||||||
self.bank_center=self.offset_all_coordinates().scale(-1,-1)
|
self.bank_center=self.offset_all_coordinates().scale(-1,-1)
|
||||||
|
|
@ -73,18 +77,25 @@ class bank(design.design):
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
""" Adding pins for Bank module"""
|
""" Adding pins for Bank module"""
|
||||||
|
for k in range(self.total_read):
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
self.add_pin("dout[{0}]".format(i),"OUT")
|
self.add_pin("dout{0}[{1}]".format(k,i),"OUT")
|
||||||
|
for k in range(self.total_write):
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
self.add_pin("din[{0}]".format(i),"IN")
|
self.add_pin("din{0}[{1}]".format(k,i),"IN")
|
||||||
|
for k in range(self.total_ports):
|
||||||
for i in range(self.addr_size):
|
for i in range(self.addr_size):
|
||||||
self.add_pin("addr[{0}]".format(i),"INPUT")
|
self.add_pin("addr{0}[{1}]".format(k,i),"INPUT")
|
||||||
|
|
||||||
# For more than one bank, we have a bank select and name
|
# For more than one bank, we have a bank select and name
|
||||||
# the signals gated_*.
|
# the signals gated_*.
|
||||||
if self.num_banks > 1:
|
if self.num_banks > 1:
|
||||||
self.add_pin("bank_sel","INPUT")
|
self.add_pin("bank_sel","INPUT")
|
||||||
for pin in ["s_en","w_en","tri_en_bar","tri_en",
|
for k in range(self.total_read):
|
||||||
|
self.add_pin("s_en{0}".format(k), "INPUT")
|
||||||
|
for k in range(self.total_write):
|
||||||
|
self.add_pin("w_en{0}".format(k), "INPUT")
|
||||||
|
for pin in ["tri_en_bar","tri_en",
|
||||||
"clk_buf_bar","clk_buf"]:
|
"clk_buf_bar","clk_buf"]:
|
||||||
self.add_pin(pin,"INPUT")
|
self.add_pin(pin,"INPUT")
|
||||||
self.add_pin("vdd","POWER")
|
self.add_pin("vdd","POWER")
|
||||||
|
|
@ -152,7 +163,7 @@ class bank(design.design):
|
||||||
# Number of control lines in the bus
|
# Number of control lines in the bus
|
||||||
self.num_control_lines = 6
|
self.num_control_lines = 6
|
||||||
# The order of the control signals on the control bus:
|
# The order of the control signals on the control bus:
|
||||||
self.input_control_signals = ["clk_buf", "tri_en_bar", "tri_en", "clk_buf_bar", "w_en", "s_en"]
|
self.input_control_signals = ["clk_buf", "tri_en_bar", "tri_en", "clk_buf_bar", "w_en0", "s_en0"]
|
||||||
# These will be outputs of the gaters if this is multibank, if not, normal signals.
|
# These will be outputs of the gaters if this is multibank, if not, normal signals.
|
||||||
if self.num_banks > 1:
|
if self.num_banks > 1:
|
||||||
self.control_signals = ["gated_"+str for str in self.input_control_signals]
|
self.control_signals = ["gated_"+str for str in self.input_control_signals]
|
||||||
|
|
@ -173,7 +184,6 @@ class bank(design.design):
|
||||||
2*self.m2_pitch)
|
2*self.m2_pitch)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
""" Create all the modules using the class loader """
|
""" Create all the modules using the class loader """
|
||||||
self.tri = self.mod_tri_gate()
|
self.tri = self.mod_tri_gate()
|
||||||
|
|
@ -183,8 +193,22 @@ class bank(design.design):
|
||||||
rows=self.num_rows)
|
rows=self.num_rows)
|
||||||
self.add_mod(self.bitcell_array)
|
self.add_mod(self.bitcell_array)
|
||||||
|
|
||||||
self.precharge_array = self.mod_precharge_array(columns=self.num_cols)
|
# create arrays of bitline and bitline_bar names for read, write, or all ports
|
||||||
self.add_mod(self.precharge_array)
|
self.read_bl_list = self.bitcell.list_read_column_pins()
|
||||||
|
self.read_br_list = self.bitcell.list_read_bar_column_pins()
|
||||||
|
|
||||||
|
self.write_bl_list = self.bitcell.list_write_column_pins()
|
||||||
|
self.write_br_list = self.bitcell.list_write_bar_column_pins()
|
||||||
|
|
||||||
|
self.total_bl_list = self.bitcell.list_column_pins()
|
||||||
|
self.total_br_list = self.bitcell.list_column_bar_pins()
|
||||||
|
|
||||||
|
self.total_wl_list = self.bitcell.list_row_pins()
|
||||||
|
|
||||||
|
self.precharge_array = [None] * self.total_read
|
||||||
|
for k in range(self.total_read):
|
||||||
|
self.precharge_array[k] = self.mod_precharge_array(columns=self.num_cols, BL=self.read_bl_list[k], BR=self.read_br_list[k])
|
||||||
|
self.add_mod(self.precharge_array[k])
|
||||||
|
|
||||||
if self.col_addr_size > 0:
|
if self.col_addr_size > 0:
|
||||||
self.column_mux_array = self.mod_column_mux_array(columns=self.num_cols,
|
self.column_mux_array = self.mod_column_mux_array(columns=self.num_cols,
|
||||||
|
|
@ -224,96 +248,114 @@ class bank(design.design):
|
||||||
self.bitcell_array_inst=self.add_inst(name="bitcell_array",
|
self.bitcell_array_inst=self.add_inst(name="bitcell_array",
|
||||||
mod=self.bitcell_array,
|
mod=self.bitcell_array,
|
||||||
offset=vector(0,0))
|
offset=vector(0,0))
|
||||||
|
|
||||||
temp = []
|
temp = []
|
||||||
for i in range(self.num_cols):
|
bl_list = self.bitcell.list_all_column_pins()
|
||||||
temp.append("bl[{0}]".format(i))
|
wl_list = self.bitcell.list_row_pins()
|
||||||
temp.append("br[{0}]".format(i))
|
for col in range(self.num_cols):
|
||||||
for j in range(self.num_rows):
|
for bitline in bl_list:
|
||||||
temp.append("wl[{0}]".format(j))
|
temp.append(bitline+"[{0}]".format(col))
|
||||||
temp.extend(["vdd", "gnd"])
|
for row in range(self.num_rows):
|
||||||
|
for wordline in wl_list:
|
||||||
|
temp.append(wordline+"[{0}]".format(row))
|
||||||
|
temp.append("vdd")
|
||||||
|
temp.append("gnd")
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
|
|
||||||
def add_precharge_array(self):
|
def add_precharge_array(self):
|
||||||
""" Adding Precharge """
|
""" Adding Precharge """
|
||||||
|
|
||||||
|
self.precharge_array_inst = [None] * self.total_read
|
||||||
|
|
||||||
|
for k in range(self.total_read):
|
||||||
# The wells must be far enough apart
|
# The wells must be far enough apart
|
||||||
# The enclosure is for the well and the spacing is to the bitcell wells
|
# The enclosure is for the well and the spacing is to the bitcell wells
|
||||||
y_offset = self.bitcell_array.height + self.m2_gap
|
y_offset = self.bitcell_array.height + self.m2_gap
|
||||||
self.precharge_array_inst=self.add_inst(name="precharge_array",
|
self.precharge_array_inst[k]=self.add_inst(name="precharge_array{}".format(k),
|
||||||
mod=self.precharge_array,
|
mod=self.precharge_array[k],
|
||||||
offset=vector(0,y_offset))
|
offset=vector(0,y_offset))
|
||||||
temp = []
|
temp = []
|
||||||
for i in range(self.num_cols):
|
for i in range(self.num_cols):
|
||||||
temp.append("bl[{0}]".format(i))
|
temp.append(self.read_bl_list[k]+"[{0}]".format(i))
|
||||||
temp.append("br[{0}]".format(i))
|
temp.append(self.read_br_list[k]+"[{0}]".format(i))
|
||||||
temp.extend([self.prefix+"clk_buf_bar", "vdd"])
|
temp.extend([self.prefix+"clk_buf_bar", "vdd"])
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
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 . """
|
||||||
|
|
||||||
if self.col_addr_size > 0:
|
if self.col_addr_size > 0:
|
||||||
self.column_mux_height = self.column_mux_array.height + self.m2_gap
|
self.column_mux_height = self.column_mux_array.height + self.m2_gap
|
||||||
else:
|
else:
|
||||||
self.column_mux_height = 0
|
self.column_mux_height = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.col_mux_array_inst = [None] * self.total_ports
|
||||||
|
|
||||||
|
for k in range(self.total_ports):
|
||||||
y_offset = self.column_mux_height
|
y_offset = self.column_mux_height
|
||||||
self.col_mux_array_inst=self.add_inst(name="column_mux_array",
|
self.col_mux_array_inst[k]=self.add_inst(name="column_mux_array{}".format(k),
|
||||||
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))
|
||||||
temp = []
|
temp = []
|
||||||
for i in range(self.num_cols):
|
for i in range(self.num_cols):
|
||||||
temp.append("bl[{0}]".format(i))
|
temp.append(self.total_bl_list[k]+"[{0}]".format(i))
|
||||||
temp.append("br[{0}]".format(i))
|
temp.append(self.total_br_list[k]+"[{0}]".format(i))
|
||||||
for k in range(self.words_per_row):
|
for h in range(self.words_per_row):
|
||||||
temp.append("sel[{0}]".format(k))
|
temp.append("sel{0}[{1}]".format(k,h))
|
||||||
for j in range(self.word_size):
|
for j in range(self.word_size):
|
||||||
temp.append("bl_out[{0}]".format(j))
|
temp.append(self.total_bl_list[k]+"_out[{0}]".format(j))
|
||||||
temp.append("br_out[{0}]".format(j))
|
temp.append(self.total_br_list[k]+"_out[{0}]".format(j))
|
||||||
temp.append("gnd")
|
temp.append("gnd")
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
def add_sense_amp_array(self):
|
def add_sense_amp_array(self):
|
||||||
""" Adding Sense amp """
|
""" Adding Sense amp """
|
||||||
|
|
||||||
|
self.sense_amp_array_inst = [None] * self.total_read
|
||||||
|
|
||||||
|
for k in range(self.total_read):
|
||||||
y_offset = self.column_mux_height + self.sense_amp_array.height + self.m2_gap
|
y_offset = self.column_mux_height + self.sense_amp_array.height + self.m2_gap
|
||||||
self.sense_amp_array_inst=self.add_inst(name="sense_amp_array",
|
self.sense_amp_array_inst[k]=self.add_inst(name="sense_amp_array{}".format(k),
|
||||||
mod=self.sense_amp_array,
|
mod=self.sense_amp_array,
|
||||||
offset=vector(0,y_offset).scale(-1,-1))
|
offset=vector(0,y_offset).scale(-1,-1))
|
||||||
temp = []
|
temp = []
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
temp.append("dout[{0}]".format(i))
|
temp.append("dout{0}[{1}]".format(k,i))
|
||||||
if self.words_per_row == 1:
|
if self.words_per_row == 1:
|
||||||
temp.append("bl[{0}]".format(i))
|
temp.append(self.read_bl_list[k]+"[{0}]".format(i))
|
||||||
temp.append("br[{0}]".format(i))
|
temp.append(self.read_br_list[k]+"[{0}]".format(i))
|
||||||
else:
|
else:
|
||||||
temp.append("bl_out[{0}]".format(i))
|
temp.append(self.read_bl_list[k]+"_out[{0}]".format(i))
|
||||||
temp.append("br_out[{0}]".format(i))
|
temp.append(self.read_br_list[k]+"_out[{0}]".format(i))
|
||||||
|
|
||||||
temp.extend([self.prefix+"s_en", "vdd", "gnd"])
|
temp.extend([self.prefix+"s_en{0}".format(k), "vdd", "gnd"])
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
def add_write_driver_array(self):
|
def add_write_driver_array(self):
|
||||||
""" Adding Write Driver """
|
""" Adding Write Driver """
|
||||||
|
|
||||||
|
self.write_driver_array_inst = [None] * self.total_write
|
||||||
|
|
||||||
|
for k in range(self.total_write):
|
||||||
y_offset = self.sense_amp_array.height + self.column_mux_height \
|
y_offset = self.sense_amp_array.height + self.column_mux_height \
|
||||||
+ self.m2_gap + self.write_driver_array.height
|
+ self.m2_gap + self.write_driver_array.height
|
||||||
self.write_driver_array_inst=self.add_inst(name="write_driver_array",
|
self.write_driver_array_inst[k]=self.add_inst(name="write_driver_array{}".format(k),
|
||||||
mod=self.write_driver_array,
|
mod=self.write_driver_array,
|
||||||
offset=vector(0,y_offset).scale(-1,-1))
|
offset=vector(0,y_offset).scale(-1,-1))
|
||||||
|
|
||||||
temp = []
|
temp = []
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
temp.append("din[{0}]".format(i))
|
temp.append("din{0}[{1}]".format(k,i))
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
if (self.words_per_row == 1):
|
if (self.words_per_row == 1):
|
||||||
temp.append("bl[{0}]".format(i))
|
temp.append(self.write_bl_list[k]+"[{0}]".format(i))
|
||||||
temp.append("br[{0}]".format(i))
|
temp.append(self.write_br_list[k]+"[{0}]".format(i))
|
||||||
else:
|
else:
|
||||||
temp.append("bl_out[{0}]".format(i))
|
temp.append(self.write_bl_list[k]+"_out[{0}]".format(i))
|
||||||
temp.append("br_out[{0}]".format(i))
|
temp.append(self.write_br_list[k]+"_out[{0}]".format(i))
|
||||||
temp.extend([self.prefix+"w_en", "vdd", "gnd"])
|
temp.extend([self.prefix+"w_en{0}".format(k), "vdd", "gnd"])
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
def add_tri_gate_array(self):
|
def add_tri_gate_array(self):
|
||||||
|
|
@ -328,47 +370,52 @@ class bank(design.design):
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
temp.append("sa_out[{0}]".format(i))
|
temp.append("sa_out[{0}]".format(i))
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
temp.append("dout[{0}]".format(i))
|
temp.append("dout0[{0}]".format(i))
|
||||||
temp.extend([self.prefix+"tri_en", self.prefix+"tri_en_bar", "vdd", "gnd"])
|
temp.extend([self.prefix+"tri_en", self.prefix+"tri_en_bar", "vdd", "gnd"])
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
def add_row_decoder(self):
|
def add_row_decoder(self):
|
||||||
""" Add the hierarchical row decoder """
|
""" Add the hierarchical row decoder """
|
||||||
|
|
||||||
|
|
||||||
# The address and control bus will be in between decoder and the main memory array
|
# The address and control bus will be in between decoder and the main memory array
|
||||||
# This bus will route address bits to the decoder input and column mux inputs.
|
# This bus will route address bits to the decoder input and column mux inputs.
|
||||||
# The wires are actually routed after we placed the stuff on both sides.
|
# The wires are actually routed after we placed the stuff on both sides.
|
||||||
# The predecoder is below the x-axis and the main decoder is above the x-axis
|
# The predecoder is below the x-axis and the main decoder is above the x-axis
|
||||||
# The address flop and decoder are aligned in the x coord.
|
# The address flop and decoder are aligned in the x coord.
|
||||||
|
|
||||||
|
self.row_decoder_inst = [None] * self.total_ports
|
||||||
|
|
||||||
|
for k in range(self.total_ports):
|
||||||
x_offset = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
|
x_offset = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
|
||||||
self.row_decoder_inst=self.add_inst(name="row_decoder",
|
self.row_decoder_inst[k]=self.add_inst(name="row_decoder{}".format(k),
|
||||||
mod=self.row_decoder,
|
mod=self.row_decoder,
|
||||||
offset=vector(x_offset,0))
|
offset=vector(x_offset,0))
|
||||||
|
|
||||||
temp = []
|
temp = []
|
||||||
for i in range(self.row_addr_size):
|
for i in range(self.row_addr_size):
|
||||||
temp.append("addr[{0}]".format(i+self.col_addr_size))
|
temp.append("addr{0}[{1}]".format(k,i+self.col_addr_size))
|
||||||
for j in range(self.num_rows):
|
for j in range(self.num_rows):
|
||||||
temp.append("dec_out[{0}]".format(j))
|
temp.append("dec_out{0}[{1}]".format(k,j))
|
||||||
temp.extend(["vdd", "gnd"])
|
temp.extend(["vdd", "gnd"])
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
def add_wordline_driver(self):
|
def add_wordline_driver(self):
|
||||||
""" Wordline Driver """
|
""" Wordline Driver """
|
||||||
|
|
||||||
|
self.wordline_driver_inst = [None] * self.total_ports
|
||||||
|
|
||||||
|
for k in range(self.total_ports):
|
||||||
# The wordline driver is placed to the right of the main decoder width.
|
# The wordline driver is placed to the right of the main decoder width.
|
||||||
x_offset = -(self.central_bus_width + self.wordline_driver.width) + self.m2_pitch
|
x_offset = -(self.central_bus_width + self.wordline_driver.width) + self.m2_pitch
|
||||||
self.wordline_driver_inst=self.add_inst(name="wordline_driver",
|
self.wordline_driver_inst[k]=self.add_inst(name="wordline_driver{}".format(k),
|
||||||
mod=self.wordline_driver,
|
mod=self.wordline_driver,
|
||||||
offset=vector(x_offset,0))
|
offset=vector(x_offset,0))
|
||||||
|
|
||||||
temp = []
|
temp = []
|
||||||
for i in range(self.num_rows):
|
for i in range(self.num_rows):
|
||||||
temp.append("dec_out[{0}]".format(i))
|
temp.append("dec_out{0}[{1}]".format(k,i))
|
||||||
for i in range(self.num_rows):
|
for i in range(self.num_rows):
|
||||||
temp.append("wl[{0}]".format(i))
|
temp.append(self.total_wl_list[k]+"[{0}]".format(i))
|
||||||
temp.append(self.prefix+"clk_buf")
|
temp.append(self.prefix+"clk_buf")
|
||||||
temp.append("vdd")
|
temp.append("vdd")
|
||||||
temp.append("gnd")
|
temp.append("gnd")
|
||||||
|
|
@ -379,18 +426,22 @@ class bank(design.design):
|
||||||
"""
|
"""
|
||||||
Create a 2:4 or 3:8 column address decoder.
|
Create a 2:4 or 3:8 column address decoder.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
self.col_decoder_inst = [None] * self.total_ports
|
||||||
|
|
||||||
|
for k in range(self.total_ports):
|
||||||
# Place the col decoder right aligned with row decoder
|
# Place the col decoder right aligned with row decoder
|
||||||
x_off = -(self.central_bus_width + self.wordline_driver.width + self.col_decoder.width)
|
x_off = -(self.central_bus_width + self.wordline_driver.width + self.col_decoder.width)
|
||||||
y_off = -(self.col_decoder.height + 2*drc["well_to_well"])
|
y_off = -(self.col_decoder.height + 2*drc["well_to_well"])
|
||||||
self.col_decoder_inst=self.add_inst(name="col_address_decoder",
|
self.col_decoder_inst[k]=self.add_inst(name="col_address_decoder{}".format(k),
|
||||||
mod=self.col_decoder,
|
mod=self.col_decoder,
|
||||||
offset=vector(x_off,y_off))
|
offset=vector(x_off,y_off))
|
||||||
|
|
||||||
temp = []
|
temp = []
|
||||||
for i in range(self.col_addr_size):
|
for i in range(self.col_addr_size):
|
||||||
temp.append("addr[{0}]".format(i))
|
temp.append("addr{0}[{1}]".format(k,i))
|
||||||
for j in range(self.num_col_addr_lines):
|
for j in range(self.num_col_addr_lines):
|
||||||
temp.append("sel[{0}]".format(j))
|
temp.append("sel{0}[{1}]".format(k,j))
|
||||||
temp.extend(["vdd", "gnd"])
|
temp.extend(["vdd", "gnd"])
|
||||||
self.connect_inst(temp)
|
self.connect_inst(temp)
|
||||||
|
|
||||||
|
|
@ -423,9 +474,9 @@ class bank(design.design):
|
||||||
|
|
||||||
x_off = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
|
x_off = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
|
||||||
if self.col_addr_size > 0:
|
if self.col_addr_size > 0:
|
||||||
y_off = min(self.col_decoder_inst.by(), self.col_mux_array_inst.by())
|
y_off = min(self.col_decoder_inst[0].by(), self.col_mux_array_inst[0].by())
|
||||||
else:
|
else:
|
||||||
y_off = self.row_decoder_inst.by()
|
y_off = self.row_decoder_inst[0].by()
|
||||||
y_off -= (self.bank_select.height + drc["well_to_well"])
|
y_off -= (self.bank_select.height + drc["well_to_well"])
|
||||||
self.bank_select_pos = vector(x_off,y_off)
|
self.bank_select_pos = vector(x_off,y_off)
|
||||||
self.bank_select_inst = self.add_inst(name="bank_select",
|
self.bank_select_inst = self.add_inst(name="bank_select",
|
||||||
|
|
@ -444,16 +495,16 @@ class bank(design.design):
|
||||||
|
|
||||||
# These are the instances that every bank has
|
# These are the instances that every bank has
|
||||||
top_instances = [self.bitcell_array_inst,
|
top_instances = [self.bitcell_array_inst,
|
||||||
self.precharge_array_inst,
|
self.precharge_array_inst[0],
|
||||||
self.sense_amp_array_inst,
|
self.sense_amp_array_inst[0],
|
||||||
self.write_driver_array_inst,
|
self.write_driver_array_inst[0],
|
||||||
# self.tri_gate_array_inst,
|
# self.tri_gate_array_inst,
|
||||||
self.row_decoder_inst,
|
self.row_decoder_inst[0],
|
||||||
self.wordline_driver_inst]
|
self.wordline_driver_inst[0]]
|
||||||
# Add these if we use the part...
|
# Add these if we use the part...
|
||||||
if self.col_addr_size > 0:
|
if self.col_addr_size > 0:
|
||||||
top_instances.append(self.col_decoder_inst)
|
top_instances.append(self.col_decoder_inst[0])
|
||||||
top_instances.append(self.col_mux_array_inst)
|
top_instances.append(self.col_mux_array_inst[0])
|
||||||
|
|
||||||
if self.num_banks > 1:
|
if self.num_banks > 1:
|
||||||
top_instances.append(self.bank_select_inst)
|
top_instances.append(self.bank_select_inst)
|
||||||
|
|
@ -461,10 +512,10 @@ class bank(design.design):
|
||||||
|
|
||||||
for inst in top_instances:
|
for inst in top_instances:
|
||||||
# Column mux has no vdd
|
# Column mux has no vdd
|
||||||
if self.col_addr_size==0 or (self.col_addr_size>0 and inst != self.col_mux_array_inst):
|
if self.col_addr_size==0 or (self.col_addr_size>0 and inst != self.col_mux_array_inst[0]):
|
||||||
self.copy_layout_pin(inst, "vdd")
|
self.copy_layout_pin(inst, "vdd")
|
||||||
# Precharge has no gnd
|
# Precharge has no gnd
|
||||||
if inst != self.precharge_array_inst:
|
if inst != self.precharge_array_inst[0]:
|
||||||
self.copy_layout_pin(inst, "gnd")
|
self.copy_layout_pin(inst, "gnd")
|
||||||
|
|
||||||
def route_bank_select(self):
|
def route_bank_select(self):
|
||||||
|
|
@ -497,10 +548,10 @@ class bank(design.design):
|
||||||
#driver.
|
#driver.
|
||||||
# Leave room for the output below the tri gate.
|
# 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
|
write_driver_min_y_offset = self.write_driver_array_inst[0].by() - 3*self.m2_pitch
|
||||||
row_decoder_min_y_offset = self.row_decoder_inst.by()
|
row_decoder_min_y_offset = self.row_decoder_inst[0].by()
|
||||||
if self.col_addr_size > 0:
|
if self.col_addr_size > 0:
|
||||||
col_decoder_min_y_offset = self.col_decoder_inst.by()
|
col_decoder_min_y_offset = self.col_decoder_inst[0].by()
|
||||||
else:
|
else:
|
||||||
col_decoder_min_y_offset = row_decoder_min_y_offset
|
col_decoder_min_y_offset = row_decoder_min_y_offset
|
||||||
|
|
||||||
|
|
@ -514,9 +565,9 @@ class bank(design.design):
|
||||||
|
|
||||||
# The max point is always the top of the precharge bitlines
|
# The max point is always the top of the precharge bitlines
|
||||||
# Add a vdd and gnd power rail above the array
|
# Add a vdd and gnd power rail above the array
|
||||||
self.max_y_offset = self.precharge_array_inst.uy() + 3*self.m1_width
|
self.max_y_offset = self.precharge_array_inst[0].uy() + 3*self.m1_width
|
||||||
self.max_x_offset = self.bitcell_array_inst.ur().x + 3*self.m1_width
|
self.max_x_offset = self.bitcell_array_inst.ur().x + 3*self.m1_width
|
||||||
self.min_x_offset = self.row_decoder_inst.lx()
|
self.min_x_offset = self.row_decoder_inst[0].lx()
|
||||||
|
|
||||||
# # Create the core bbox for the power rings
|
# # Create the core bbox for the power rings
|
||||||
ur = vector(self.max_x_offset, self.max_y_offset)
|
ur = vector(self.max_x_offset, self.max_y_offset)
|
||||||
|
|
@ -548,11 +599,12 @@ class bank(design.design):
|
||||||
def route_precharge_to_bitcell_array(self):
|
def route_precharge_to_bitcell_array(self):
|
||||||
""" Routing of BL and BR between pre-charge and bitcell array """
|
""" Routing of BL and BR between pre-charge and bitcell array """
|
||||||
|
|
||||||
|
for k in range(self.total_read):
|
||||||
for i in range(self.num_cols):
|
for i in range(self.num_cols):
|
||||||
precharge_bl = self.precharge_array_inst.get_pin("bl[{}]".format(i)).bc()
|
precharge_bl = self.precharge_array_inst[k].get_pin(self.read_bl_list[k]+"[{}]".format(i)).bc()
|
||||||
precharge_br = self.precharge_array_inst.get_pin("br[{}]".format(i)).bc()
|
precharge_br = self.precharge_array_inst[k].get_pin(self.read_br_list[k]+"[{}]".format(i)).bc()
|
||||||
bitcell_bl = self.bitcell_array_inst.get_pin("bl[{}]".format(i)).uc()
|
bitcell_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[k]+"[{}]".format(i)).uc()
|
||||||
bitcell_br = self.bitcell_array_inst.get_pin("br[{}]".format(i)).uc()
|
bitcell_br = self.bitcell_array_inst.get_pin(self.read_br_list[k]+"[{}]".format(i)).uc()
|
||||||
|
|
||||||
yoffset = 0.5*(precharge_bl.y+bitcell_bl.y)
|
yoffset = 0.5*(precharge_bl.y+bitcell_bl.y)
|
||||||
self.add_path("metal2",[precharge_bl, vector(precharge_bl.x,yoffset),
|
self.add_path("metal2",[precharge_bl, vector(precharge_bl.x,yoffset),
|
||||||
|
|
@ -568,11 +620,12 @@ class bank(design.design):
|
||||||
if self.col_addr_size==0:
|
if self.col_addr_size==0:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
for k in range(self.total_ports):
|
||||||
for i in range(self.num_cols):
|
for i in range(self.num_cols):
|
||||||
col_mux_bl = self.col_mux_array_inst.get_pin("bl[{}]".format(i)).uc()
|
col_mux_bl = self.col_mux_array_inst[k].get_pin("bl[{}]".format(i)).uc()
|
||||||
col_mux_br = self.col_mux_array_inst.get_pin("br[{}]".format(i)).uc()
|
col_mux_br = self.col_mux_array_inst[k].get_pin("br[{}]".format(i)).uc()
|
||||||
bitcell_bl = self.bitcell_array_inst.get_pin("bl[{}]".format(i)).bc()
|
bitcell_bl = self.bitcell_array_inst.get_pin(self.total_bl_list[k]+"[{}]".format(i)).bc()
|
||||||
bitcell_br = self.bitcell_array_inst.get_pin("br[{}]".format(i)).bc()
|
bitcell_br = self.bitcell_array_inst.get_pin(self.total_br_list[k]+"[{}]".format(i)).bc()
|
||||||
|
|
||||||
yoffset = 0.5*(col_mux_bl.y+bitcell_bl.y)
|
yoffset = 0.5*(col_mux_bl.y+bitcell_bl.y)
|
||||||
self.add_path("metal2",[col_mux_bl, vector(col_mux_bl.x,yoffset),
|
self.add_path("metal2",[col_mux_bl, vector(col_mux_bl.x,yoffset),
|
||||||
|
|
@ -583,18 +636,19 @@ class bank(design.design):
|
||||||
def route_sense_amp_to_col_mux_or_bitcell_array(self):
|
def route_sense_amp_to_col_mux_or_bitcell_array(self):
|
||||||
""" Routing of BL and BR between sense_amp and column mux or bitcell array """
|
""" Routing of BL and BR between sense_amp and column mux or bitcell array """
|
||||||
|
|
||||||
|
for k in range(self.total_read):
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
sense_amp_bl = self.sense_amp_array_inst.get_pin("bl[{}]".format(i)).uc()
|
sense_amp_bl = self.sense_amp_array_inst[k].get_pin("bl[{}]".format(i)).uc()
|
||||||
sense_amp_br = self.sense_amp_array_inst.get_pin("br[{}]".format(i)).uc()
|
sense_amp_br = self.sense_amp_array_inst[k].get_pin("br[{}]".format(i)).uc()
|
||||||
|
|
||||||
if self.col_addr_size>0:
|
if self.col_addr_size>0:
|
||||||
# Sense amp is connected to the col mux
|
# Sense amp is connected to the col mux
|
||||||
connect_bl = self.col_mux_array_inst.get_pin("bl_out[{}]".format(i)).bc()
|
connect_bl = self.col_mux_array_inst[k].get_pin("bl_out[{}]".format(i)).bc()
|
||||||
connect_br = self.col_mux_array_inst.get_pin("br_out[{}]".format(i)).bc()
|
connect_br = self.col_mux_array_inst[k].get_pin("br_out[{}]".format(i)).bc()
|
||||||
else:
|
else:
|
||||||
# Sense amp is directly connected to the bitcell array
|
# Sense amp is directly connected to the bitcell array
|
||||||
connect_bl = self.bitcell_array_inst.get_pin("bl[{}]".format(i)).bc()
|
connect_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[k]+"[{}]".format(i)).bc()
|
||||||
connect_br = self.bitcell_array_inst.get_pin("br[{}]".format(i)).bc()
|
connect_br = self.bitcell_array_inst.get_pin(self.read_br_list[k]+"[{}]".format(i)).bc()
|
||||||
|
|
||||||
|
|
||||||
yoffset = 0.5*(sense_amp_bl.y+connect_bl.y)
|
yoffset = 0.5*(sense_amp_bl.y+connect_bl.y)
|
||||||
|
|
@ -609,7 +663,7 @@ class bank(design.design):
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
# Connection of data_out of sense amp to data_in
|
# Connection of data_out of sense amp to data_in
|
||||||
tri_gate_in = self.tri_gate_array_inst.get_pin("in[{}]".format(i)).lc()
|
tri_gate_in = self.tri_gate_array_inst.get_pin("in[{}]".format(i)).lc()
|
||||||
sa_data_out = self.sense_amp_array_inst.get_pin("data[{}]".format(i)).bc()
|
sa_data_out = self.sense_amp_array_inst[0].get_pin("data[{}]".format(i)).bc()
|
||||||
|
|
||||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||||
offset=tri_gate_in)
|
offset=tri_gate_in)
|
||||||
|
|
@ -620,8 +674,8 @@ class bank(design.design):
|
||||||
def route_sense_amp_out(self):
|
def route_sense_amp_out(self):
|
||||||
""" Add pins for the sense amp output """
|
""" Add pins for the sense amp output """
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
data_pin = self.sense_amp_array_inst.get_pin("data[{}]".format(i))
|
data_pin = self.sense_amp_array_inst[0].get_pin("data[{}]".format(i))
|
||||||
self.add_layout_pin_rect_center(text="dout[{}]".format(i),
|
self.add_layout_pin_rect_center(text="dout0[{}]".format(i),
|
||||||
layer=data_pin.layer,
|
layer=data_pin.layer,
|
||||||
offset=data_pin.center(),
|
offset=data_pin.center(),
|
||||||
height=data_pin.height(),
|
height=data_pin.height(),
|
||||||
|
|
@ -631,7 +685,7 @@ class bank(design.design):
|
||||||
""" Metal 3 routing of tri_gate output data """
|
""" Metal 3 routing of tri_gate output data """
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
data_pin = self.tri_gate_array_inst.get_pin("out[{}]".format(i))
|
data_pin = self.tri_gate_array_inst.get_pin("out[{}]".format(i))
|
||||||
self.add_layout_pin_rect_center(text="dout[{}]".format(i),
|
self.add_layout_pin_rect_center(text="dout0[{}]".format(i),
|
||||||
layer=data_pin.layer,
|
layer=data_pin.layer,
|
||||||
offset=data_pin.center(),
|
offset=data_pin.center(),
|
||||||
height=data_pin.height(),
|
height=data_pin.height(),
|
||||||
|
|
@ -645,8 +699,8 @@ class bank(design.design):
|
||||||
for i in range(self.row_addr_size):
|
for i in range(self.row_addr_size):
|
||||||
addr_idx = i + self.col_addr_size
|
addr_idx = i + self.col_addr_size
|
||||||
decoder_name = "addr[{}]".format(i)
|
decoder_name = "addr[{}]".format(i)
|
||||||
addr_name = "addr[{}]".format(addr_idx)
|
addr_name = "addr0[{}]".format(addr_idx)
|
||||||
self.copy_layout_pin(self.row_decoder_inst, decoder_name, addr_name)
|
self.copy_layout_pin(self.row_decoder_inst[0], decoder_name, addr_name)
|
||||||
|
|
||||||
|
|
||||||
def route_write_driver(self):
|
def route_write_driver(self):
|
||||||
|
|
@ -654,26 +708,27 @@ class bank(design.design):
|
||||||
|
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
data_name = "data[{}]".format(i)
|
data_name = "data[{}]".format(i)
|
||||||
din_name = "din[{}]".format(i)
|
din_name = "din0[{}]".format(i)
|
||||||
self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name)
|
self.copy_layout_pin(self.write_driver_array_inst[0], data_name, din_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route_wordline_driver(self):
|
def route_wordline_driver(self):
|
||||||
""" Connecting Wordline driver output to Bitcell WL connection """
|
""" Connecting Wordline driver output to Bitcell WL connection """
|
||||||
|
|
||||||
|
for k in range(self.total_read):
|
||||||
# we don't care about bends after connecting to the input pin, so let the path code decide.
|
# we don't care about bends after connecting to the input pin, so let the path code decide.
|
||||||
for i in range(self.num_rows):
|
for i in range(self.num_rows):
|
||||||
# The pre/post is to access the pin from "outside" the cell to avoid DRCs
|
# The pre/post is to access the pin from "outside" the cell to avoid DRCs
|
||||||
decoder_out_pos = self.row_decoder_inst.get_pin("decode[{}]".format(i)).rc()
|
decoder_out_pos = self.row_decoder_inst[k].get_pin("decode[{}]".format(i)).rc()
|
||||||
driver_in_pos = self.wordline_driver_inst.get_pin("in[{}]".format(i)).lc()
|
driver_in_pos = self.wordline_driver_inst[k].get_pin("in[{}]".format(i)).lc()
|
||||||
mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0)
|
mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0)
|
||||||
mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1)
|
mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1)
|
||||||
self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos])
|
self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos])
|
||||||
|
|
||||||
# The mid guarantees we exit the input cell to the right.
|
# The mid guarantees we exit the input cell to the right.
|
||||||
driver_wl_pos = self.wordline_driver_inst.get_pin("wl[{}]".format(i)).rc()
|
driver_wl_pos = self.wordline_driver_inst[k].get_pin("wl[{}]".format(i)).rc()
|
||||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin("wl[{}]".format(i)).lc()
|
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.total_wl_list[k]+"[{}]".format(i)).lc()
|
||||||
mid1 = driver_wl_pos.scale(0.5,1)+bitcell_wl_pos.scale(0.5,0)
|
mid1 = driver_wl_pos.scale(0.5,1)+bitcell_wl_pos.scale(0.5,0)
|
||||||
mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1)
|
mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1)
|
||||||
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||||
|
|
@ -693,7 +748,7 @@ class bank(design.design):
|
||||||
decode_names = ["Zb", "Z"]
|
decode_names = ["Zb", "Z"]
|
||||||
|
|
||||||
# The Address LSB
|
# The Address LSB
|
||||||
self.copy_layout_pin(self.col_decoder_inst, "A", "addr[0]")
|
self.copy_layout_pin(self.col_decoder_inst[0], "A", "addr0[0]")
|
||||||
|
|
||||||
elif self.col_addr_size > 1:
|
elif self.col_addr_size > 1:
|
||||||
decode_names = []
|
decode_names = []
|
||||||
|
|
@ -702,22 +757,22 @@ class bank(design.design):
|
||||||
|
|
||||||
for i in range(self.col_addr_size):
|
for i in range(self.col_addr_size):
|
||||||
decoder_name = "in[{}]".format(i)
|
decoder_name = "in[{}]".format(i)
|
||||||
addr_name = "addr[{}]".format(i)
|
addr_name = "addr0[{}]".format(i)
|
||||||
self.copy_layout_pin(self.col_decoder_inst, decoder_name, addr_name)
|
self.copy_layout_pin(self.col_decoder_inst[0], decoder_name, addr_name)
|
||||||
|
|
||||||
|
|
||||||
# This will do a quick "river route" on two layers.
|
# This will do a quick "river route" on two layers.
|
||||||
# When above the top select line it will offset "inward" again to prevent conflicts.
|
# When above the top select line it will offset "inward" again to prevent conflicts.
|
||||||
# This could be done on a single layer, but we follow preferred direction rules for later routing.
|
# This could be done on a single layer, but we follow preferred direction rules for later routing.
|
||||||
top_y_offset = self.col_mux_array_inst.get_pin("sel[{}]".format(self.num_col_addr_lines-1)).cy()
|
top_y_offset = self.col_mux_array_inst[0].get_pin("sel[{}]".format(self.num_col_addr_lines-1)).cy()
|
||||||
for (decode_name,i) in zip(decode_names,range(self.num_col_addr_lines)):
|
for (decode_name,i) in zip(decode_names,range(self.num_col_addr_lines)):
|
||||||
mux_name = "sel[{}]".format(i)
|
mux_name = "sel[{}]".format(i)
|
||||||
mux_addr_pos = self.col_mux_array_inst.get_pin(mux_name).lc()
|
mux_addr_pos = self.col_mux_array_inst[0].get_pin(mux_name).lc()
|
||||||
|
|
||||||
decode_out_pos = self.col_decoder_inst.get_pin(decode_name).center()
|
decode_out_pos = self.col_decoder_inst[0].get_pin(decode_name).center()
|
||||||
|
|
||||||
# To get to the edge of the decoder and one track out
|
# To get to the edge of the decoder and one track out
|
||||||
delta_offset = self.col_decoder_inst.rx() - decode_out_pos.x + self.m2_pitch
|
delta_offset = self.col_decoder_inst[0].rx() - decode_out_pos.x + self.m2_pitch
|
||||||
if decode_out_pos.y > top_y_offset:
|
if decode_out_pos.y > top_y_offset:
|
||||||
mid1_pos = vector(decode_out_pos.x + delta_offset + i*self.m2_pitch,decode_out_pos.y)
|
mid1_pos = vector(decode_out_pos.x + delta_offset + i*self.m2_pitch,decode_out_pos.y)
|
||||||
else:
|
else:
|
||||||
|
|
@ -768,7 +823,7 @@ class bank(design.design):
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
data_name = "dec_out[{}]".format(i)
|
data_name = "dec_out[{}]".format(i)
|
||||||
pin_name = "in[{}]".format(i)
|
pin_name = "in[{}]".format(i)
|
||||||
data_pin = self.wordline_driver_inst.get_pin(pin_name)
|
data_pin = self.wordline_driver_inst[0].get_pin(pin_name)
|
||||||
self.add_label(text=data_name,
|
self.add_label(text=data_name,
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
offset=data_pin.center())
|
offset=data_pin.center())
|
||||||
|
|
@ -784,9 +839,9 @@ class bank(design.design):
|
||||||
connection = []
|
connection = []
|
||||||
#connection.append((self.prefix+"tri_en_bar", self.tri_gate_array_inst.get_pin("en_bar").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+"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+"clk_buf_bar", self.precharge_array_inst[0].get_pin("en").lc()))
|
||||||
connection.append((self.prefix+"w_en", self.write_driver_array_inst.get_pin("en").lc()))
|
connection.append((self.prefix+"w_en0", self.write_driver_array_inst[0].get_pin("en").lc()))
|
||||||
connection.append((self.prefix+"s_en", self.sense_amp_array_inst.get_pin("en").lc()))
|
connection.append((self.prefix+"s_en0", self.sense_amp_array_inst[0].get_pin("en").lc()))
|
||||||
|
|
||||||
for (control_signal, pin_pos) in connection:
|
for (control_signal, pin_pos) in connection:
|
||||||
control_pos = vector(self.bus_xoffset[control_signal].x ,pin_pos.y)
|
control_pos = vector(self.bus_xoffset[control_signal].x ,pin_pos.y)
|
||||||
|
|
@ -797,7 +852,7 @@ class bank(design.design):
|
||||||
|
|
||||||
# clk to wordline_driver
|
# clk to wordline_driver
|
||||||
control_signal = self.prefix+"clk_buf"
|
control_signal = self.prefix+"clk_buf"
|
||||||
pin_pos = self.wordline_driver_inst.get_pin("en").uc()
|
pin_pos = self.wordline_driver_inst[0].get_pin("en").uc()
|
||||||
mid_pos = pin_pos + vector(0,self.m1_pitch)
|
mid_pos = pin_pos + vector(0,self.m1_pitch)
|
||||||
control_x_offset = self.bus_xoffset[control_signal].x
|
control_x_offset = self.bus_xoffset[control_signal].x
|
||||||
control_pos = vector(control_x_offset + self.m1_width, mid_pos.y)
|
control_pos = vector(control_x_offset + self.m1_width, mid_pos.y)
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class precharge_test(openram_test):
|
||||||
pc = precharge_array.precharge_array(columns=3, BL="rbl0", BR="rbl_bar0")
|
pc = precharge_array.precharge_array(columns=3, BL="rbl0", BR="rbl_bar0")
|
||||||
self.local_check(pc)
|
self.local_check(pc)
|
||||||
|
|
||||||
#globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
||||||
|
|
||||||
# instantiate a copy of the class to actually run the test
|
# instantiate a copy of the class to actually run the test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue