mirror of https://github.com/VLSIDA/OpenRAM.git
Merging changes and updating multiport syntax across several tests
This commit is contained in:
commit
af0756382f
|
|
@ -204,26 +204,30 @@ def read_config(config_file, is_unit_test=True):
|
|||
# Note that if we re-read a config file, nothing will get read again!
|
||||
if not k in OPTS.__dict__ or k=="tech_name":
|
||||
OPTS.__dict__[k]=v
|
||||
|
||||
|
||||
# Massage the output path to be an absolute one
|
||||
if not OPTS.output_path.endswith('/'):
|
||||
OPTS.output_path += "/"
|
||||
if not OPTS.output_path.startswith('/'):
|
||||
OPTS.output_path = os.getcwd() + "/" + OPTS.output_path
|
||||
debug.info(1, "Output saved in " + OPTS.output_path)
|
||||
|
||||
# Remember if we are running unit tests to reduce output
|
||||
OPTS.is_unit_test=is_unit_test
|
||||
|
||||
# If we are only generating a netlist, we can't do DRC/LVS
|
||||
if OPTS.netlist_only:
|
||||
OPTS.check_lvsdrc=False
|
||||
|
||||
|
||||
# If config didn't set output name, make a reasonable default.
|
||||
if (OPTS.output_name == ""):
|
||||
OPTS.output_name = "sram_{0}rw_{1}b_{2}w_{3}bank_{4}".format(OPTS.rw_ports,
|
||||
OPTS.word_size,
|
||||
OPTS.num_words,
|
||||
OPTS.num_banks,
|
||||
OPTS.tech_name)
|
||||
OPTS.output_name = "sram_{0}b_{1}w_{2}bank_{3}rw_{4}w_{5}r_{6}".format(OPTS.word_size,
|
||||
OPTS.num_words,
|
||||
OPTS.num_banks,
|
||||
OPTS.num_rw_ports,
|
||||
OPTS.num_w_ports,
|
||||
OPTS.num_r_ports,
|
||||
OPTS.tech_name)
|
||||
|
||||
# Don't delete the output dir, it may have other files!
|
||||
# make the directory if it doesn't exist
|
||||
|
|
|
|||
|
|
@ -20,22 +20,16 @@ class bank(design.design):
|
|||
write driver and sense amplifiers.
|
||||
"""
|
||||
|
||||
def __init__(self, word_size, num_words, words_per_row, num_banks=1, name=""):
|
||||
def __init__(self, sram_config, name=""):
|
||||
|
||||
if name == "":
|
||||
name = "bank_{0}_{1}".format(word_size, num_words)
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "create sram of size {0} with {1} words".format(word_size,num_words))
|
||||
|
||||
self.word_size = word_size
|
||||
self.num_words = num_words
|
||||
self.words_per_row = words_per_row
|
||||
self.num_banks = num_banks
|
||||
sram_config.set_local_config(self)
|
||||
|
||||
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
|
||||
if name == "":
|
||||
name = "bank_{0}_{1}".format(self.word_size, self.num_words)
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words))
|
||||
|
||||
|
||||
# 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
|
||||
# the internal gated signals.
|
||||
|
|
@ -70,25 +64,25 @@ class bank(design.design):
|
|||
|
||||
def add_pins(self):
|
||||
""" Adding pins for Bank module"""
|
||||
for k in range(self.total_read):
|
||||
for i in range(self.word_size):
|
||||
self.add_pin("dout{0}[{1}]".format(k,i),"OUT")
|
||||
for k in range(self.total_write):
|
||||
for i in range(self.word_size):
|
||||
self.add_pin("din{0}[{1}]".format(k,i),"IN")
|
||||
for k in range(self.total_ports):
|
||||
for i in range(self.addr_size):
|
||||
self.add_pin("addr{0}[{1}]".format(k,i),"INPUT")
|
||||
for port in range(self.total_read):
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("dout{0}[{1}]".format(port,bit),"OUT")
|
||||
for port in range(self.total_write):
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("din{0}[{1}]".format(port,bit),"IN")
|
||||
for port in range(self.total_ports):
|
||||
for bit in range(self.addr_size):
|
||||
self.add_pin("addr{0}[{1}]".format(port,bit),"INPUT")
|
||||
|
||||
# For more than one bank, we have a bank select and name
|
||||
# the signals gated_*.
|
||||
if self.num_banks > 1:
|
||||
for port in range(self.total_ports):
|
||||
self.add_pin("bank_sel{}".format(port),"INPUT")
|
||||
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 port in range(self.total_read):
|
||||
self.add_pin("s_en{0}".format(port), "INPUT")
|
||||
for port in range(self.total_write):
|
||||
self.add_pin("w_en{0}".format(port), "INPUT")
|
||||
for pin in ["clk_buf_bar","clk_buf"]:
|
||||
self.add_pin(pin,"INPUT")
|
||||
self.add_pin("vdd","POWER")
|
||||
|
|
@ -229,9 +223,9 @@ class bank(design.design):
|
|||
self.total_bitline_list = self.bitcell.list_all_bitline_names()
|
||||
|
||||
self.precharge_array = []
|
||||
for k in range(self.total_read):
|
||||
self.precharge_array.append(self.mod_precharge_array(columns=self.num_cols, bitcell_bl=self.read_bl_list[k], bitcell_br=self.read_br_list[k]))
|
||||
self.add_mod(self.precharge_array[k])
|
||||
for port in range(self.total_read):
|
||||
self.precharge_array.append(self.mod_precharge_array(columns=self.num_cols, bitcell_bl=self.read_bl_list[port], bitcell_br=self.read_br_list[port]))
|
||||
self.add_mod(self.precharge_array[port])
|
||||
|
||||
if self.col_addr_size > 0:
|
||||
self.column_mux_array = self.mod_column_mux_array(columns=self.num_cols,
|
||||
|
|
@ -288,13 +282,13 @@ class bank(design.design):
|
|||
""" Creating Precharge """
|
||||
|
||||
self.precharge_array_inst = []
|
||||
for k in range(self.total_read):
|
||||
self.precharge_array_inst.append(self.add_inst(name="precharge_array{}".format(k),
|
||||
mod=self.precharge_array[k]))
|
||||
for port in range(self.total_read):
|
||||
self.precharge_array_inst.append(self.add_inst(name="precharge_array{}".format(port),
|
||||
mod=self.precharge_array[port]))
|
||||
temp = []
|
||||
for i in range(self.num_cols):
|
||||
temp.append(self.read_bl_list[k]+"[{0}]".format(i))
|
||||
temp.append(self.read_br_list[k]+"[{0}]".format(i))
|
||||
temp.append(self.read_bl_list[port]+"[{0}]".format(i))
|
||||
temp.append(self.read_br_list[port]+"[{0}]".format(i))
|
||||
temp.extend([self.prefix+"clk_buf_bar", "vdd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
|
@ -302,11 +296,11 @@ class bank(design.design):
|
|||
""" Placing Precharge """
|
||||
|
||||
# FIXME: place for multiport
|
||||
for k in range(self.total_read):
|
||||
for port in range(self.total_read):
|
||||
# The wells must be far enough apart
|
||||
# The enclosure is for the well and the spacing is to the bitcell wells
|
||||
y_offset = self.bitcell_array.height + self.m2_gap
|
||||
self.precharge_array_inst[k].place(vector(0,y_offset))
|
||||
self.precharge_array_inst[port].place(vector(0,y_offset))
|
||||
|
||||
def create_column_mux_array(self):
|
||||
""" Creating Column Mux when words_per_row > 1 . """
|
||||
|
|
@ -314,19 +308,19 @@ class bank(design.design):
|
|||
return
|
||||
|
||||
self.col_mux_array_inst = []
|
||||
for k in range(self.total_ports):
|
||||
self.col_mux_array_inst.append(self.add_inst(name="column_mux_array{}".format(k),
|
||||
for port in range(self.total_ports):
|
||||
self.col_mux_array_inst.append(self.add_inst(name="column_mux_array{}".format(port),
|
||||
mod=self.column_mux_array))
|
||||
|
||||
temp = []
|
||||
for i in range(self.num_cols):
|
||||
temp.append(self.total_bl_list[k]+"[{0}]".format(i))
|
||||
temp.append(self.total_br_list[k]+"[{0}]".format(i))
|
||||
for h in range(self.words_per_row):
|
||||
temp.append("sel{0}[{1}]".format(k,h))
|
||||
for j in range(self.word_size):
|
||||
temp.append(self.total_bl_list[k]+"_out[{0}]".format(j))
|
||||
temp.append(self.total_br_list[k]+"_out[{0}]".format(j))
|
||||
for col in range(self.num_cols):
|
||||
temp.append(self.total_bl_list[port]+"[{0}]".format(col))
|
||||
temp.append(self.total_br_list[port]+"[{0}]".format(col))
|
||||
for word in range(self.words_per_row):
|
||||
temp.append("sel{0}[{1}]".format(port,word))
|
||||
for bit in range(self.word_size):
|
||||
temp.append(self.total_bl_list[port]+"_out[{0}]".format(bit))
|
||||
temp.append(self.total_br_list[port]+"_out[{0}]".format(bit))
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
|
@ -338,68 +332,68 @@ class bank(design.design):
|
|||
self.column_mux_height = 0
|
||||
return
|
||||
|
||||
for k in range(self.total_ports):
|
||||
for port in range(self.total_ports):
|
||||
y_offset = self.column_mux_height
|
||||
self.col_mux_array_inst[k].place(vector(0,y_offset).scale(-1,-1))
|
||||
self.col_mux_array_inst[port].place(vector(0,y_offset).scale(-1,-1))
|
||||
|
||||
def create_sense_amp_array(self):
|
||||
""" Creating Sense amp """
|
||||
|
||||
self.sense_amp_array_inst = []
|
||||
for k in range(self.total_read):
|
||||
self.sense_amp_array_inst.append(self.add_inst(name="sense_amp_array{}".format(k),
|
||||
for port in range(self.total_read):
|
||||
self.sense_amp_array_inst.append(self.add_inst(name="sense_amp_array{}".format(port),
|
||||
mod=self.sense_amp_array))
|
||||
|
||||
temp = []
|
||||
for i in range(self.word_size):
|
||||
temp.append("dout{0}[{1}]".format(k,i))
|
||||
for bit in range(self.word_size):
|
||||
temp.append("dout{0}[{1}]".format(port,bit))
|
||||
if self.words_per_row == 1:
|
||||
temp.append(self.read_bl_list[k]+"[{0}]".format(i))
|
||||
temp.append(self.read_br_list[k]+"[{0}]".format(i))
|
||||
temp.append(self.read_bl_list[port]+"[{0}]".format(bit))
|
||||
temp.append(self.read_br_list[port]+"[{0}]".format(bit))
|
||||
else:
|
||||
temp.append(self.read_bl_list[k]+"_out[{0}]".format(i))
|
||||
temp.append(self.read_br_list[k]+"_out[{0}]".format(i))
|
||||
temp.append(self.read_bl_list[port]+"_out[{0}]".format(bit))
|
||||
temp.append(self.read_br_list[port]+"_out[{0}]".format(bit))
|
||||
|
||||
temp.extend([self.prefix+"s_en{0}".format(k), "vdd", "gnd"])
|
||||
temp.extend([self.prefix+"s_en{0}".format(port), "vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
def place_sense_amp_array(self):
|
||||
""" Placing Sense amp """
|
||||
|
||||
# FIXME: place for multiport
|
||||
for k in range(self.total_read):
|
||||
for port in range(self.total_read):
|
||||
y_offset = self.column_mux_height + self.sense_amp_array.height + self.m2_gap
|
||||
self.sense_amp_array_inst[k].place(vector(0,y_offset).scale(-1,-1))
|
||||
self.sense_amp_array_inst[port].place(vector(0,y_offset).scale(-1,-1))
|
||||
|
||||
def create_write_driver_array(self):
|
||||
""" Creating Write Driver """
|
||||
|
||||
self.write_driver_array_inst = []
|
||||
for k in range(self.total_write):
|
||||
self.write_driver_array_inst.append(self.add_inst(name="write_driver_array{}".format(k),
|
||||
for port in range(self.total_write):
|
||||
self.write_driver_array_inst.append(self.add_inst(name="write_driver_array{}".format(port),
|
||||
mod=self.write_driver_array))
|
||||
|
||||
temp = []
|
||||
for i in range(self.word_size):
|
||||
temp.append("din{0}[{1}]".format(k,i))
|
||||
for i in range(self.word_size):
|
||||
for bit in range(self.word_size):
|
||||
temp.append("din{0}[{1}]".format(port,bit))
|
||||
for bit in range(self.word_size):
|
||||
if (self.words_per_row == 1):
|
||||
temp.append(self.write_bl_list[k]+"[{0}]".format(i))
|
||||
temp.append(self.write_br_list[k]+"[{0}]".format(i))
|
||||
temp.append(self.write_bl_list[port]+"[{0}]".format(bit))
|
||||
temp.append(self.write_br_list[port]+"[{0}]".format(bit))
|
||||
else:
|
||||
temp.append(self.write_bl_list[k]+"_out[{0}]".format(i))
|
||||
temp.append(self.write_br_list[k]+"_out[{0}]".format(i))
|
||||
temp.extend([self.prefix+"w_en{0}".format(k), "vdd", "gnd"])
|
||||
temp.append(self.write_bl_list[port]+"_out[{0}]".format(bit))
|
||||
temp.append(self.write_br_list[port]+"_out[{0}]".format(bit))
|
||||
temp.extend([self.prefix+"w_en{0}".format(port), "vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
def place_write_driver_array(self):
|
||||
""" Placing Write Driver """
|
||||
|
||||
# FIXME: place for multiport
|
||||
for k in range(self.total_write):
|
||||
for port in range(self.total_write):
|
||||
y_offset = self.sense_amp_array.height + self.column_mux_height \
|
||||
+ self.m2_gap + self.write_driver_array.height
|
||||
self.write_driver_array_inst[k].place(vector(0,y_offset).scale(-1,-1))
|
||||
self.write_driver_array_inst[port].place(vector(0,y_offset).scale(-1,-1))
|
||||
|
||||
|
||||
|
||||
|
|
@ -407,15 +401,15 @@ class bank(design.design):
|
|||
""" Create the hierarchical row decoder """
|
||||
|
||||
self.row_decoder_inst = []
|
||||
for k in range(self.total_ports):
|
||||
self.row_decoder_inst.append(self.add_inst(name="row_decoder{}".format(k),
|
||||
for port in range(self.total_ports):
|
||||
self.row_decoder_inst.append(self.add_inst(name="row_decoder{}".format(port),
|
||||
mod=self.row_decoder))
|
||||
|
||||
temp = []
|
||||
for i in range(self.row_addr_size):
|
||||
temp.append("addr{0}[{1}]".format(k,i+self.col_addr_size))
|
||||
for j in range(self.num_rows):
|
||||
temp.append("dec_out{0}[{1}]".format(k,j))
|
||||
for bit in range(self.row_addr_size):
|
||||
temp.append("addr{0}[{1}]".format(port,bit+self.col_addr_size))
|
||||
for row in range(self.num_rows):
|
||||
temp.append("dec_out{0}[{1}]".format(port,row))
|
||||
temp.extend(["vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
|
@ -429,24 +423,24 @@ class bank(design.design):
|
|||
# The address flop and decoder are aligned in the x coord.
|
||||
|
||||
# FIXME: place for multiport
|
||||
for k in range(self.total_ports):
|
||||
for port in range(self.total_ports):
|
||||
x_offset = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
|
||||
self.row_decoder_inst[k].place(vector(x_offset,0))
|
||||
self.row_decoder_inst[port].place(vector(x_offset,0))
|
||||
|
||||
|
||||
def create_wordline_driver(self):
|
||||
""" Create the Wordline Driver """
|
||||
|
||||
self.wordline_driver_inst = []
|
||||
for k in range(self.total_ports):
|
||||
self.wordline_driver_inst.append(self.add_inst(name="wordline_driver{}".format(k),
|
||||
for port in range(self.total_ports):
|
||||
self.wordline_driver_inst.append(self.add_inst(name="wordline_driver{}".format(port),
|
||||
mod=self.wordline_driver))
|
||||
|
||||
temp = []
|
||||
for i in range(self.num_rows):
|
||||
temp.append("dec_out{0}[{1}]".format(k,i))
|
||||
for i in range(self.num_rows):
|
||||
temp.append(self.total_wl_list[k]+"[{0}]".format(i))
|
||||
for row in range(self.num_rows):
|
||||
temp.append("dec_out{0}[{1}]".format(port,row))
|
||||
for row in range(self.num_rows):
|
||||
temp.append(self.total_wl_list[port]+"[{0}]".format(row))
|
||||
temp.append(self.prefix+"clk_buf")
|
||||
temp.append("vdd")
|
||||
temp.append("gnd")
|
||||
|
|
@ -456,10 +450,10 @@ class bank(design.design):
|
|||
""" Place the Wordline Driver """
|
||||
|
||||
# FIXME: place for multiport
|
||||
for k in range(self.total_ports):
|
||||
for port in range(self.total_ports):
|
||||
# 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
|
||||
self.wordline_driver_inst[k].place(vector(x_offset,0))
|
||||
self.wordline_driver_inst[port].place(vector(x_offset,0))
|
||||
|
||||
|
||||
def create_column_decoder(self):
|
||||
|
|
@ -481,15 +475,15 @@ class bank(design.design):
|
|||
debug.error("Invalid column decoder?",-1)
|
||||
|
||||
self.col_decoder_inst = []
|
||||
for k in range(self.total_ports):
|
||||
self.col_decoder_inst.append(self.add_inst(name="col_address_decoder{}".format(k),
|
||||
for port in range(self.total_ports):
|
||||
self.col_decoder_inst.append(self.add_inst(name="col_address_decoder{}".format(port),
|
||||
mod=self.col_decoder))
|
||||
|
||||
temp = []
|
||||
for i in range(self.col_addr_size):
|
||||
temp.append("addr{0}[{1}]".format(k,i))
|
||||
for j in range(self.num_col_addr_lines):
|
||||
temp.append("sel{0}[{1}]".format(k,j))
|
||||
for bit in range(self.col_addr_size):
|
||||
temp.append("addr{0}[{1}]".format(port,bit))
|
||||
for bit in range(self.num_col_addr_lines):
|
||||
temp.append("sel{0}[{1}]".format(port,bit))
|
||||
temp.extend(["vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
|
@ -501,11 +495,11 @@ class bank(design.design):
|
|||
return
|
||||
|
||||
# FIXME: place for multiport
|
||||
for k in range(self.total_ports):
|
||||
for port in range(self.total_ports):
|
||||
# Place the col decoder right aligned with row decoder
|
||||
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"])
|
||||
self.col_decoder_inst[k].place(vector(x_off,y_off))
|
||||
self.col_decoder_inst[port].place(vector(x_off,y_off))
|
||||
|
||||
|
||||
def create_bank_select(self):
|
||||
|
|
@ -533,7 +527,7 @@ class bank(design.design):
|
|||
return
|
||||
|
||||
# FIXME: place for multiport
|
||||
for k in range(self.total_ports):
|
||||
for port in range(self.total_ports):
|
||||
x_off = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
|
||||
if self.col_addr_size > 0:
|
||||
y_off = min(self.col_decoder_inst[0].by(), self.col_mux_array_inst[0].by())
|
||||
|
|
@ -541,7 +535,7 @@ class bank(design.design):
|
|||
y_off = self.row_decoder_inst[0].by()
|
||||
y_off -= (self.bank_select.height + drc["well_to_well"])
|
||||
self.bank_select_pos = vector(x_off,y_off)
|
||||
self.bank_select_inst[k].place(self.bank_select_pos)
|
||||
self.bank_select_inst[port].place(self.bank_select_pos)
|
||||
|
||||
|
||||
def route_vdd_gnd(self):
|
||||
|
|
@ -550,19 +544,19 @@ class bank(design.design):
|
|||
# These are the instances that every bank has
|
||||
top_instances = [self.bitcell_array_inst]
|
||||
|
||||
for k in range(self.total_ports):
|
||||
top_instances.extend([self.precharge_array_inst[k],
|
||||
self.sense_amp_array_inst[k],
|
||||
self.write_driver_array_inst[k],
|
||||
self.row_decoder_inst[k],
|
||||
self.wordline_driver_inst[k]])
|
||||
for port in range(self.total_ports):
|
||||
top_instances.extend([self.precharge_array_inst[port],
|
||||
self.sense_amp_array_inst[port],
|
||||
self.write_driver_array_inst[port],
|
||||
self.row_decoder_inst[port],
|
||||
self.wordline_driver_inst[port]])
|
||||
# Add these if we use the part...
|
||||
if self.col_addr_size > 0:
|
||||
top_instances.append(self.col_decoder_inst[k])
|
||||
top_instances.append(self.col_mux_array_inst[k])
|
||||
top_instances.append(self.col_decoder_inst[port])
|
||||
top_instances.append(self.col_mux_array_inst[port])
|
||||
|
||||
if self.num_banks > 1:
|
||||
top_instances.append(self.bank_select_inst[k])
|
||||
top_instances.append(self.bank_select_inst[port])
|
||||
|
||||
|
||||
for inst in top_instances:
|
||||
|
|
@ -576,13 +570,13 @@ class bank(design.design):
|
|||
def route_bank_select(self):
|
||||
""" Route the bank select logic. """
|
||||
|
||||
for k in range(self.total_ports):
|
||||
for port in range(self.total_ports):
|
||||
for input_name in self.input_control_signals+["bank_sel"]:
|
||||
self.copy_layout_pin(self.bank_select_inst[k], input_name)
|
||||
self.copy_layout_pin(self.bank_select_inst[port], input_name)
|
||||
|
||||
for gated_name in self.control_signals:
|
||||
# Connect the inverter output to the central bus
|
||||
out_pos = self.bank_select_inst[k].get_pin(gated_name).rc()
|
||||
out_pos = self.bank_select_inst[port].get_pin(gated_name).rc()
|
||||
bus_pos = vector(self.bus_xoffset[gated_name].x, out_pos.y)
|
||||
self.add_path("metal3",[out_pos, bus_pos])
|
||||
self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
|
|
@ -660,12 +654,12 @@ class bank(design.design):
|
|||
""" Routing of BL and BR between pre-charge and bitcell array """
|
||||
|
||||
# FIXME: Update for multiport
|
||||
for k in range(self.total_read):
|
||||
for i in range(self.num_cols):
|
||||
precharge_bl = self.precharge_array_inst[k].get_pin("bl[{}]".format(i)).bc()
|
||||
precharge_br = self.precharge_array_inst[k].get_pin("br[{}]".format(i)).bc()
|
||||
bitcell_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[k]+"[{}]".format(i)).uc()
|
||||
bitcell_br = self.bitcell_array_inst.get_pin(self.read_br_list[k]+"[{}]".format(i)).uc()
|
||||
for port in range(self.total_read):
|
||||
for col in range(self.num_cols):
|
||||
precharge_bl = self.precharge_array_inst[port].get_pin("bl[{}]".format(col)).bc()
|
||||
precharge_br = self.precharge_array_inst[port].get_pin("br[{}]".format(col)).bc()
|
||||
bitcell_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[port]+"[{}]".format(col)).uc()
|
||||
bitcell_br = self.bitcell_array_inst.get_pin(self.read_br_list[port]+"[{}]".format(col)).uc()
|
||||
|
||||
yoffset = 0.5*(precharge_bl.y+bitcell_bl.y)
|
||||
self.add_path("metal2",[precharge_bl, vector(precharge_bl.x,yoffset),
|
||||
|
|
@ -682,12 +676,12 @@ class bank(design.design):
|
|||
return
|
||||
|
||||
# FIXME: Update for multiport
|
||||
for k in range(self.total_ports):
|
||||
for i in range(self.num_cols):
|
||||
col_mux_bl = self.col_mux_array_inst[k].get_pin("bl[{}]".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(self.total_bl_list[k]+"[{}]".format(i)).bc()
|
||||
bitcell_br = self.bitcell_array_inst.get_pin(self.total_br_list[k]+"[{}]".format(i)).bc()
|
||||
for port in range(self.total_ports):
|
||||
for col in range(self.num_cols):
|
||||
col_mux_bl = self.col_mux_array_inst[port].get_pin("bl[{}]".format(col)).uc()
|
||||
col_mux_br = self.col_mux_array_inst[port].get_pin("br[{}]".format(col)).uc()
|
||||
bitcell_bl = self.bitcell_array_inst.get_pin(self.total_bl_list[port]+"[{}]".format(col)).bc()
|
||||
bitcell_br = self.bitcell_array_inst.get_pin(self.total_br_list[port]+"[{}]".format(col)).bc()
|
||||
|
||||
yoffset = 0.5*(col_mux_bl.y+bitcell_bl.y)
|
||||
self.add_path("metal2",[col_mux_bl, vector(col_mux_bl.x,yoffset),
|
||||
|
|
@ -698,19 +692,19 @@ class bank(design.design):
|
|||
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 """
|
||||
|
||||
for k in range(self.total_read):
|
||||
for i in range(self.word_size):
|
||||
sense_amp_bl = self.sense_amp_array_inst[k].get_pin("bl[{}]".format(i)).uc()
|
||||
sense_amp_br = self.sense_amp_array_inst[k].get_pin("br[{}]".format(i)).uc()
|
||||
for port in range(self.total_read):
|
||||
for bit in range(self.word_size):
|
||||
sense_amp_bl = self.sense_amp_array_inst[port].get_pin("bl[{}]".format(bit)).uc()
|
||||
sense_amp_br = self.sense_amp_array_inst[port].get_pin("br[{}]".format(bit)).uc()
|
||||
|
||||
if self.col_addr_size>0:
|
||||
# Sense amp is connected to the col mux
|
||||
connect_bl = self.col_mux_array_inst[k].get_pin("bl_out[{}]".format(i)).bc()
|
||||
connect_br = self.col_mux_array_inst[k].get_pin("br_out[{}]".format(i)).bc()
|
||||
connect_bl = self.col_mux_array_inst[port].get_pin("bl_out[{}]".format(bit)).bc()
|
||||
connect_br = self.col_mux_array_inst[port].get_pin("br_out[{}]".format(bit)).bc()
|
||||
else:
|
||||
# Sense amp is directly connected to the bitcell array
|
||||
connect_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[k]+"[{}]".format(i)).bc()
|
||||
connect_br = self.bitcell_array_inst.get_pin(self.read_br_list[k]+"[{}]".format(i)).bc()
|
||||
connect_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[port]+"[{}]".format(bit)).bc()
|
||||
connect_br = self.bitcell_array_inst.get_pin(self.read_br_list[port]+"[{}]".format(bit)).bc()
|
||||
|
||||
|
||||
yoffset = 0.5*(sense_amp_bl.y+connect_bl.y)
|
||||
|
|
@ -722,9 +716,11 @@ class bank(design.design):
|
|||
|
||||
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[0].get_pin("data[{}]".format(i))
|
||||
self.add_layout_pin_rect_center(text="dout0[{}]".format(i),
|
||||
|
||||
# FIXME: Update for multiport
|
||||
for bit in range(self.word_size):
|
||||
data_pin = self.sense_amp_array_inst[0].get_pin("data[{}]".format(bit))
|
||||
self.add_layout_pin_rect_center(text="dout0[{}]".format(bit),
|
||||
layer=data_pin.layer,
|
||||
offset=data_pin.center(),
|
||||
height=data_pin.height(),
|
||||
|
|
@ -734,10 +730,11 @@ class bank(design.design):
|
|||
def route_row_decoder(self):
|
||||
""" Routes the row decoder inputs and supplies """
|
||||
|
||||
# FIXME: Update for multiport
|
||||
# Create inputs for the row address lines
|
||||
for i in range(self.row_addr_size):
|
||||
addr_idx = i + self.col_addr_size
|
||||
decoder_name = "addr[{}]".format(i)
|
||||
for row in range(self.row_addr_size):
|
||||
addr_idx = row + self.col_addr_size
|
||||
decoder_name = "addr[{}]".format(row)
|
||||
addr_name = "addr0[{}]".format(addr_idx)
|
||||
self.copy_layout_pin(self.row_decoder_inst[0], decoder_name, addr_name)
|
||||
|
||||
|
|
@ -745,9 +742,9 @@ class bank(design.design):
|
|||
def route_write_driver(self):
|
||||
""" Connecting write driver """
|
||||
|
||||
for i in range(self.word_size):
|
||||
data_name = "data[{}]".format(i)
|
||||
din_name = "din0[{}]".format(i)
|
||||
for row in range(self.word_size):
|
||||
data_name = "data[{}]".format(row)
|
||||
din_name = "din0[{}]".format(row)
|
||||
self.copy_layout_pin(self.write_driver_array_inst[0], data_name, din_name)
|
||||
|
||||
|
||||
|
|
@ -755,17 +752,17 @@ class bank(design.design):
|
|||
def route_wordline_driver(self):
|
||||
""" Connecting Wordline driver output to Bitcell WL connection """
|
||||
|
||||
for i in range(self.num_rows):
|
||||
for row in range(self.num_rows):
|
||||
# The pre/post is to access the pin from "outside" the cell to avoid DRCs
|
||||
decoder_out_pos = self.row_decoder_inst[0].get_pin("decode[{}]".format(i)).rc()
|
||||
driver_in_pos = self.wordline_driver_inst[0].get_pin("in[{}]".format(i)).lc()
|
||||
decoder_out_pos = self.row_decoder_inst[0].get_pin("decode[{}]".format(row)).rc()
|
||||
driver_in_pos = self.wordline_driver_inst[0].get_pin("in[{}]".format(row)).lc()
|
||||
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)
|
||||
self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos])
|
||||
|
||||
# The mid guarantees we exit the input cell to the right.
|
||||
driver_wl_pos = self.wordline_driver_inst[0].get_pin("wl[{}]".format(i)).rc()
|
||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.total_wl_list[0]+"[{}]".format(i)).lc()
|
||||
driver_wl_pos = self.wordline_driver_inst[0].get_pin("wl[{}]".format(row)).rc()
|
||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.total_wl_list[0]+"[{}]".format(row)).lc()
|
||||
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)
|
||||
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ report_status()
|
|||
|
||||
# Start importing design modules after we have the config file
|
||||
import verify
|
||||
import sram
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
|
||||
output_extensions = ["sp","v","lib"]
|
||||
if not OPTS.netlist_only:
|
||||
|
|
@ -51,11 +52,14 @@ print(*output_files,sep="\n")
|
|||
start_time = datetime.datetime.now()
|
||||
print_time("Start",start_time)
|
||||
|
||||
c = sram_config(word_size=OPTS.word_size,
|
||||
num_words=OPTS.num_words,
|
||||
num_rw_ports=OPTS.num_rw_ports,
|
||||
num_w_ports=OPTS.num_w_ports,
|
||||
num_r_ports=OPTS.num_r_ports)
|
||||
|
||||
# import SRAM test generation
|
||||
s = sram.sram(word_size=OPTS.word_size,
|
||||
num_words=OPTS.num_words,
|
||||
num_banks=OPTS.num_banks,
|
||||
name=OPTS.output_name)
|
||||
s = sram(c, OPTS.output_name)
|
||||
|
||||
# Output the files for the resulting SRAM
|
||||
s.save()
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ class options(optparse.Values):
|
|||
purge_temp = True
|
||||
|
||||
# These are the configuration parameters
|
||||
rw_ports = 1
|
||||
r_ports = 0
|
||||
w_ports = 0
|
||||
num_rw_ports = 1
|
||||
num_r_ports = 0
|
||||
num_w_ports = 0
|
||||
# These will get initialized by the the file
|
||||
supply_voltages = ""
|
||||
temperatures = ""
|
||||
|
|
|
|||
|
|
@ -16,18 +16,18 @@ class pbitcell(pgate.pgate):
|
|||
width = None
|
||||
height = None
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, num_readwrite=OPTS.rw_ports, num_write=OPTS.w_ports, num_read=OPTS.r_ports):
|
||||
name = "pbitcell_{0}RW_{1}W_{2}R_{3}".format(num_readwrite, num_write, num_read, pbitcell.unique_id)
|
||||
pbitcell.unique_id += 1
|
||||
pgate.pgate.__init__(self, name)
|
||||
debug.info(2, "create a multi-port bitcell with {0} write ports and {1} read ports".format(num_write, num_read))
|
||||
def __init__(self, num_rw_ports=OPTS.num_rw_ports, num_w_ports=OPTS.num_w_ports, num_r_ports=OPTS.num_r_ports):
|
||||
|
||||
self.num_readwrite = num_readwrite
|
||||
self.num_write = num_write
|
||||
self.num_read = num_read
|
||||
name = "pbitcell_{0}RW_{1}W_{2}R".format(num_rw_ports, num_w_ports, num_r_ports)
|
||||
pgate.pgate.__init__(self, name)
|
||||
debug.info(2, "create a multi-port bitcell with {0} rw ports, {1} w ports and {2} r ports".format(num_rw_ports,
|
||||
num_w_ports,
|
||||
num_r_ports))
|
||||
|
||||
self.num_rw_ports = num_rw_ports
|
||||
self.num_w_ports = num_w_ports
|
||||
self.num_r_ports = num_r_ports
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
self.create_layout()
|
||||
|
|
@ -41,11 +41,11 @@ class pbitcell(pgate.pgate):
|
|||
self.add_modules()
|
||||
self.create_storage()
|
||||
|
||||
if(self.num_readwrite > 0):
|
||||
if(self.num_rw_ports > 0):
|
||||
self.create_readwrite_ports()
|
||||
if(self.num_write > 0):
|
||||
if(self.num_w_ports > 0):
|
||||
self.create_write_ports()
|
||||
if(self.num_read > 0):
|
||||
if(self.num_r_ports > 0):
|
||||
self.create_read_ports()
|
||||
|
||||
def create_layout(self):
|
||||
|
|
@ -56,11 +56,11 @@ class pbitcell(pgate.pgate):
|
|||
self.route_storage()
|
||||
self.route_rails()
|
||||
|
||||
if(self.num_readwrite > 0):
|
||||
if(self.num_rw_ports > 0):
|
||||
self.place_readwrite_ports()
|
||||
if(self.num_write > 0):
|
||||
if(self.num_w_ports > 0):
|
||||
self.place_write_ports()
|
||||
if(self.num_read > 0):
|
||||
if(self.num_r_ports > 0):
|
||||
self.place_read_ports()
|
||||
self.extend_well()
|
||||
|
||||
|
|
@ -68,21 +68,21 @@ class pbitcell(pgate.pgate):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
self.add_pin("rwbl{}".format(k))
|
||||
self.add_pin("rwbl_bar{}".format(k))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
self.add_pin("wbl{}".format(k))
|
||||
self.add_pin("wbl_bar{}".format(k))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
self.add_pin("rbl{}".format(k))
|
||||
self.add_pin("rbl_bar{}".format(k))
|
||||
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
self.add_pin("rwwl{}".format(k))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
self.add_pin("wwl{}".format(k))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
self.add_pin("rwl{}".format(k))
|
||||
|
||||
self.add_pin("vdd")
|
||||
|
|
@ -90,8 +90,8 @@ class pbitcell(pgate.pgate):
|
|||
|
||||
def add_modules(self):
|
||||
# if there are any read/write ports, then the inverter nmos is sized based the number of them
|
||||
if(self.num_readwrite > 0):
|
||||
inverter_nmos_width = self.num_readwrite*3*parameter["min_tx_size"]
|
||||
if(self.num_rw_ports > 0):
|
||||
inverter_nmos_width = self.num_rw_ports*3*parameter["min_tx_size"]
|
||||
inverter_pmos_width = parameter["min_tx_size"]
|
||||
readwrite_nmos_width = 1.5*parameter["min_tx_size"]
|
||||
write_nmos_width = parameter["min_tx_size"]
|
||||
|
|
@ -167,7 +167,7 @@ class pbitcell(pgate.pgate):
|
|||
|
||||
# write to read transistor spacing (also acts as readwrite to read transistor spacing)
|
||||
# calculation is dependent on whether the read transistor is adjacent to a write transistor or a readwrite transistor
|
||||
if(self.num_write > 0):
|
||||
if(self.num_w_ports > 0):
|
||||
if(self.write_nmos_contact_extension > self.gate_contact_thres):
|
||||
write_portion = drc["minwidth_metal2"] + self.write_nmos_contact_extension
|
||||
else:
|
||||
|
|
@ -206,23 +206,23 @@ class pbitcell(pgate.pgate):
|
|||
Calculate positions that describe the edges of the cell
|
||||
"""
|
||||
# create flags for excluding readwrite, write, or read port calculations if they are not included in the bitcell
|
||||
if(self.num_readwrite > 0):
|
||||
if(self.num_rw_ports > 0):
|
||||
self.readwrite_port_flag = True
|
||||
else:
|
||||
self.readwrite_port_flag = False
|
||||
|
||||
if(self.num_write > 0):
|
||||
if(self.num_w_ports > 0):
|
||||
self.write_port_flag = True
|
||||
else:
|
||||
self.write_port_flag = False
|
||||
|
||||
if(self.num_read > 0):
|
||||
if(self.num_r_ports > 0):
|
||||
self.read_port_flag = True
|
||||
else:
|
||||
self.read_port_flag = False
|
||||
|
||||
# determine the distance of the leftmost/rightmost transistor gate connection
|
||||
if (self.num_read > 0):
|
||||
if (self.num_r_ports > 0):
|
||||
if(self.read_nmos_contact_extension > self.gate_contact_thres):
|
||||
end_connection = drc["minwidth_metal2"] + self.read_nmos_contact_extension + contact.m1m2.height
|
||||
else:
|
||||
|
|
@ -236,11 +236,11 @@ class pbitcell(pgate.pgate):
|
|||
# leftmost position = storage width + read/write ports width + write ports width + read ports width + end transistor gate connections + metal spacing necessary for tiling the bitcell
|
||||
self.leftmost_xpos = -self.inverter_tile_width \
|
||||
- self.inverter_to_write_spacing \
|
||||
- self.readwrite_port_flag*(self.readwrite_nmos.active_height + (self.num_readwrite-1)*self.readwrite_tile_width) \
|
||||
- self.readwrite_port_flag*(self.readwrite_nmos.active_height + (self.num_rw_ports-1)*self.readwrite_tile_width) \
|
||||
- self.write_port_flag*self.readwrite_port_flag*self.write_to_write_spacing \
|
||||
- self.write_port_flag*(self.write_nmos.active_height + (self.num_write-1)*self.write_tile_width) \
|
||||
- self.write_port_flag*(self.write_nmos.active_height + (self.num_w_ports-1)*self.write_tile_width) \
|
||||
- self.read_port_flag*self.write_to_read_spacing \
|
||||
- self.read_port_flag*(self.read_nmos.active_height + (self.num_read-1)*self.read_tile_width) \
|
||||
- self.read_port_flag*(self.read_nmos.active_height + (self.num_r_ports-1)*self.read_tile_width) \
|
||||
- end_connection \
|
||||
- 0.5*drc["poly_to_polycontact"]
|
||||
|
||||
|
|
@ -249,9 +249,9 @@ class pbitcell(pgate.pgate):
|
|||
# bottommost position = gnd height + rwwl height + wwl height + rwl height + space needed between tiled bitcells
|
||||
array_tiling_offset = 0.5*drc["minwidth_metal2"]
|
||||
self.botmost_ypos = -self.rail_tile_height \
|
||||
- self.num_readwrite*self.rowline_tile_height \
|
||||
- self.num_write*self.rowline_tile_height \
|
||||
- self.num_read*self.rowline_tile_height \
|
||||
- self.num_rw_ports*self.rowline_tile_height \
|
||||
- self.num_w_ports*self.rowline_tile_height \
|
||||
- self.num_r_ports*self.rowline_tile_height \
|
||||
- array_tiling_offset
|
||||
|
||||
# topmost position = height of the inverter + height of vdd
|
||||
|
|
@ -390,11 +390,11 @@ class pbitcell(pgate.pgate):
|
|||
"""
|
||||
|
||||
# define write transistor variables as empty arrays based on the number of write ports
|
||||
self.readwrite_nmos_left = [None] * self.num_readwrite
|
||||
self.readwrite_nmos_right = [None] * self.num_readwrite
|
||||
self.readwrite_nmos_left = [None] * self.num_rw_ports
|
||||
self.readwrite_nmos_right = [None] * self.num_rw_ports
|
||||
|
||||
# iterate over the number of read/write ports
|
||||
for k in range(0,self.num_readwrite):
|
||||
for k in range(0,self.num_rw_ports):
|
||||
# add read/write transistors
|
||||
self.readwrite_nmos_left[k] = self.add_inst(name="readwrite_nmos_left{}".format(k),
|
||||
mod=self.readwrite_nmos)
|
||||
|
|
@ -411,15 +411,15 @@ class pbitcell(pgate.pgate):
|
|||
"""
|
||||
|
||||
# Define variables relevant to write transistors
|
||||
self.rwwl_positions = [None] * self.num_readwrite
|
||||
self.rwbl_positions = [None] * self.num_readwrite
|
||||
self.rwbl_bar_positions = [None] * self.num_readwrite
|
||||
self.rwwl_positions = [None] * self.num_rw_ports
|
||||
self.rwbl_positions = [None] * self.num_rw_ports
|
||||
self.rwbl_bar_positions = [None] * self.num_rw_ports
|
||||
|
||||
# define offset correction due to rotation of the ptx module
|
||||
readwrite_rotation_correct = self.readwrite_nmos.active_height
|
||||
|
||||
# iterate over the number of read/write ports
|
||||
for k in range(0,self.num_readwrite):
|
||||
for k in range(0,self.num_rw_ports):
|
||||
# Add transistors
|
||||
# calculate read/write transistor offsets
|
||||
left_readwrite_transistor_xpos = self.left_building_edge \
|
||||
|
|
@ -529,7 +529,7 @@ class pbitcell(pgate.pgate):
|
|||
|
||||
# Drain/Storage connections
|
||||
# this path only needs to be drawn once on the last iteration of the loop
|
||||
if(k == self.num_readwrite-1):
|
||||
if(k == self.num_rw_ports-1):
|
||||
# add contacts to connect gate of inverters to drain of read/write transistors
|
||||
left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - drc["poly_to_polycontact"] - 0.5*contact.poly.width, self.cross_couple_lower_ypos)
|
||||
self.add_contact_center(layers=("poly", "contact", "metal1"),
|
||||
|
|
@ -580,11 +580,11 @@ class pbitcell(pgate.pgate):
|
|||
write_rotation_correct = self.write_nmos.active_height
|
||||
|
||||
# define write transistor variables as empty arrays based on the number of write ports
|
||||
self.write_nmos_left = [None] * self.num_write
|
||||
self.write_nmos_right = [None] * self.num_write
|
||||
self.write_nmos_left = [None] * self.num_w_ports
|
||||
self.write_nmos_right = [None] * self.num_w_ports
|
||||
|
||||
# iterate over the number of write ports
|
||||
for k in range(0,self.num_write):
|
||||
for k in range(0,self.num_w_ports):
|
||||
# add write transistors
|
||||
self.write_nmos_left[k] = self.add_inst(name="write_nmos_left{}".format(k),
|
||||
mod=self.write_nmos)
|
||||
|
|
@ -601,15 +601,15 @@ class pbitcell(pgate.pgate):
|
|||
"""
|
||||
|
||||
# Define variables relevant to write transistors
|
||||
self.wwl_positions = [None] * self.num_write
|
||||
self.wbl_positions = [None] * self.num_write
|
||||
self.wbl_bar_positions = [None] * self.num_write
|
||||
self.wwl_positions = [None] * self.num_w_ports
|
||||
self.wbl_positions = [None] * self.num_w_ports
|
||||
self.wbl_bar_positions = [None] * self.num_w_ports
|
||||
|
||||
# define offset correction due to rotation of the ptx module
|
||||
write_rotation_correct = self.write_nmos.active_height
|
||||
|
||||
# iterate over the number of write ports
|
||||
for k in range(0,self.num_write):
|
||||
for k in range(0,self.num_w_ports):
|
||||
# Add transistors
|
||||
# calculate write transistor offsets
|
||||
left_write_transistor_xpos = self.left_building_edge \
|
||||
|
|
@ -634,7 +634,7 @@ class pbitcell(pgate.pgate):
|
|||
# Add WWL lines
|
||||
# calculate WWL position
|
||||
wwl_ypos = self.gnd_position.y \
|
||||
- self.num_readwrite*self.rowline_tile_height \
|
||||
- self.num_rw_ports*self.rowline_tile_height \
|
||||
- (k+1)*self.rowline_tile_height
|
||||
self.wwl_positions[k] = vector(self.leftmost_xpos, wwl_ypos)
|
||||
|
||||
|
|
@ -723,7 +723,7 @@ class pbitcell(pgate.pgate):
|
|||
|
||||
# Drain/Storage connections
|
||||
# this path only needs to be drawn once on the last iteration of the loop
|
||||
if(k == self.num_write-1):
|
||||
if(k == self.num_w_ports-1):
|
||||
# add contacts to connect gate of inverters to drain of write transistors
|
||||
left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - drc["poly_to_polycontact"] - 0.5*contact.poly.width, self.cross_couple_lower_ypos)
|
||||
self.add_contact_center(layers=("poly", "contact", "metal1"),
|
||||
|
|
@ -771,13 +771,13 @@ class pbitcell(pgate.pgate):
|
|||
"""
|
||||
|
||||
# define read transistor variables as empty arrays based on the number of read ports
|
||||
self.read_nmos_left = [None] * self.num_read
|
||||
self.read_nmos_right = [None] * self.num_read
|
||||
self.read_access_nmos_left = [None] * self.num_read
|
||||
self.read_access_nmos_right = [None] * self.num_read
|
||||
self.read_nmos_left = [None] * self.num_r_ports
|
||||
self.read_nmos_right = [None] * self.num_r_ports
|
||||
self.read_access_nmos_left = [None] * self.num_r_ports
|
||||
self.read_access_nmos_right = [None] * self.num_r_ports
|
||||
|
||||
# iterate over the number of read ports
|
||||
for k in range(0,self.num_read):
|
||||
for k in range(0,self.num_r_ports):
|
||||
# add read-access transistors
|
||||
self.read_access_nmos_left[k] = self.add_inst(name="read_access_nmos_left{}".format(k),
|
||||
mod=self.read_nmos)
|
||||
|
|
@ -802,9 +802,9 @@ class pbitcell(pgate.pgate):
|
|||
"""
|
||||
|
||||
# Define variables relevant to read transistors
|
||||
self.rwl_positions = [None] * self.num_read
|
||||
self.rbl_positions = [None] * self.num_read
|
||||
self.rbl_bar_positions = [None] * self.num_read
|
||||
self.rwl_positions = [None] * self.num_r_ports
|
||||
self.rbl_positions = [None] * self.num_r_ports
|
||||
self.rbl_bar_positions = [None] * self.num_r_ports
|
||||
|
||||
# define offset correction due to rotation of the ptx module
|
||||
read_rotation_correct = self.read_nmos.active_height
|
||||
|
|
@ -813,7 +813,7 @@ class pbitcell(pgate.pgate):
|
|||
overlap_offset = self.read_nmos.get_pin("D").ll() - self.read_nmos.get_pin("S").ll()
|
||||
|
||||
# iterate over the number of read ports
|
||||
for k in range(0,self.num_read):
|
||||
for k in range(0,self.num_r_ports):
|
||||
# Add transistors
|
||||
# calculate transistor offsets
|
||||
left_read_transistor_xpos = self.left_building_edge \
|
||||
|
|
@ -843,8 +843,8 @@ class pbitcell(pgate.pgate):
|
|||
# Add RWL lines
|
||||
# calculate RWL position
|
||||
rwl_ypos = self.gnd_position.y \
|
||||
- self.num_readwrite*self.rowline_tile_height \
|
||||
- self.num_write*self.rowline_tile_height \
|
||||
- self.num_rw_ports*self.rowline_tile_height \
|
||||
- self.num_w_ports*self.rowline_tile_height \
|
||||
- (k+1)*self.rowline_tile_height
|
||||
self.rwl_positions[k] = vector(self.leftmost_xpos, rwl_ypos)
|
||||
|
||||
|
|
@ -1003,7 +1003,7 @@ class pbitcell(pgate.pgate):
|
|||
# extend pwell over read/write and write transistors to the
|
||||
# height of the write transistor well (read/write and write
|
||||
# transistors are the same height)
|
||||
if(self.num_write > 0):
|
||||
if(self.num_w_ports > 0):
|
||||
# calculate the edge of the write transistor well closest to the center
|
||||
left_write_well_xpos = self.write_nmos_left[0].offset.x + drc["well_enclosure_active"]
|
||||
right_write_well_xpos = self.write_nmos_right[0].offset.x - self.write_nmos.active_height - drc["well_enclosure_active"]
|
||||
|
|
@ -1029,7 +1029,7 @@ class pbitcell(pgate.pgate):
|
|||
height=write_well_height)
|
||||
|
||||
# extend pwell over the read transistors to the height of the bitcell
|
||||
if(self.num_read > 0):
|
||||
if(self.num_r_ports > 0):
|
||||
# calculate the edge of the read transistor well clostest to the center
|
||||
left_read_well_xpos = self.read_nmos_left[0].offset.x + drc["well_enclosure_active"]
|
||||
right_read_well_xpos = self.read_nmos_right[0].offset.x - self.read_nmos.active_height - drc["well_enclosure_active"]
|
||||
|
|
@ -1088,20 +1088,20 @@ class pbitcell(pgate.pgate):
|
|||
def list_bitcell_pins(self, col, row):
|
||||
""" Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """
|
||||
bitcell_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
bitcell_pins.append("rwbl{0}[{1}]".format(k,col))
|
||||
bitcell_pins.append("rwbl_bar{0}[{1}]".format(k,col))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
bitcell_pins.append("wbl{0}[{1}]".format(k,col))
|
||||
bitcell_pins.append("wbl_bar{0}[{1}]".format(k,col))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
bitcell_pins.append("rbl{0}[{1}]".format(k,col))
|
||||
bitcell_pins.append("rbl_bar{0}[{1}]".format(k,col))
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
bitcell_pins.append("rwwl{0}[{1}]".format(k,row))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
bitcell_pins.append("wwl{0}[{1}]".format(k,row))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
bitcell_pins.append("rwl{0}[{1}]".format(k,row))
|
||||
bitcell_pins.append("vdd")
|
||||
bitcell_pins.append("gnd")
|
||||
|
|
@ -1111,11 +1111,11 @@ class pbitcell(pgate.pgate):
|
|||
def list_all_wl_names(self):
|
||||
""" Creates a list of all wordline pin names """
|
||||
row_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
row_pins.append("rwwl{0}".format(k))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
row_pins.append("wwl{0}".format(k))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
row_pins.append("rwl{0}".format(k))
|
||||
|
||||
return row_pins
|
||||
|
|
@ -1123,9 +1123,9 @@ class pbitcell(pgate.pgate):
|
|||
def list_read_wl_names(self):
|
||||
""" Creates a list of wordline pin names associated with read ports """
|
||||
row_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
row_pins.append("rwwl{0}".format(k))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
row_pins.append("rwl{0}".format(k))
|
||||
|
||||
return row_pins
|
||||
|
|
@ -1133,9 +1133,9 @@ class pbitcell(pgate.pgate):
|
|||
def list_write_wl_names(self):
|
||||
""" Creates a list of wordline pin names associated with write ports """
|
||||
row_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
row_pins.append("rwwl{0}".format(k))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
row_pins.append("wwl{0}".format(k))
|
||||
|
||||
return row_pins
|
||||
|
|
@ -1144,13 +1144,13 @@ class pbitcell(pgate.pgate):
|
|||
def list_all_bitline_names(self):
|
||||
""" Creates a list of all bitline pin names (both bl and br) """
|
||||
column_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
column_pins.append("rwbl{0}".format(k))
|
||||
column_pins.append("rwbl_bar{0}".format(k))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
column_pins.append("wbl{0}".format(k))
|
||||
column_pins.append("wbl_bar{0}".format(k))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
column_pins.append("rbl{0}".format(k))
|
||||
column_pins.append("rbl_bar{0}".format(k))
|
||||
|
||||
|
|
@ -1159,11 +1159,11 @@ class pbitcell(pgate.pgate):
|
|||
def list_all_bl_names(self):
|
||||
""" Creates a list of all bl pins names """
|
||||
column_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
column_pins.append("rwbl{0}".format(k))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
column_pins.append("wbl{0}".format(k))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
column_pins.append("rbl{0}".format(k))
|
||||
|
||||
return column_pins
|
||||
|
|
@ -1171,11 +1171,11 @@ class pbitcell(pgate.pgate):
|
|||
def list_all_br_names(self):
|
||||
""" Creates a list of all br pins names """
|
||||
column_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
column_pins.append("rwbl_bar{0}".format(k))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
column_pins.append("wbl_bar{0}".format(k))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
column_pins.append("rbl_bar{0}".format(k))
|
||||
|
||||
return column_pins
|
||||
|
|
@ -1183,9 +1183,9 @@ class pbitcell(pgate.pgate):
|
|||
def list_read_bl_names(self):
|
||||
""" Creates a list of bl pin names associated with read ports """
|
||||
column_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
column_pins.append("rwbl{0}".format(k))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
column_pins.append("rbl{0}".format(k))
|
||||
|
||||
return column_pins
|
||||
|
|
@ -1193,9 +1193,9 @@ class pbitcell(pgate.pgate):
|
|||
def list_read_br_names(self):
|
||||
""" Creates a list of br pin names associated with read ports """
|
||||
column_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
column_pins.append("rwbl_bar{0}".format(k))
|
||||
for k in range(self.num_read):
|
||||
for k in range(self.num_r_ports):
|
||||
column_pins.append("rbl_bar{0}".format(k))
|
||||
|
||||
return column_pins
|
||||
|
|
@ -1203,9 +1203,9 @@ class pbitcell(pgate.pgate):
|
|||
def list_write_bl_names(self):
|
||||
""" Creates a list of bl pin names associated with write ports """
|
||||
column_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
column_pins.append("rwbl{0}".format(k))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
column_pins.append("wbl{0}".format(k))
|
||||
|
||||
return column_pins
|
||||
|
|
@ -1213,9 +1213,9 @@ class pbitcell(pgate.pgate):
|
|||
def list_write_br_names(self):
|
||||
""" Creates a list of br pin names asscociated with write ports"""
|
||||
column_pins = []
|
||||
for k in range(self.num_readwrite):
|
||||
for k in range(self.num_rw_ports):
|
||||
column_pins.append("rwbl_bar{0}".format(k))
|
||||
for k in range(self.num_write):
|
||||
for k in range(self.num_w_ports):
|
||||
column_pins.append("wbl_bar{0}".format(k))
|
||||
|
||||
return column_pins
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import datetime
|
|||
import getpass
|
||||
import debug
|
||||
from globals import OPTS, print_time
|
||||
|
||||
from sram_config import sram_config
|
||||
|
||||
class sram():
|
||||
"""
|
||||
|
|
@ -12,31 +12,31 @@ class sram():
|
|||
results.
|
||||
We can later add visualizer and other high-level functions as needed.
|
||||
"""
|
||||
def __init__(self, word_size, num_words, num_banks, name):
|
||||
def __init__(self, sram_config, name="sram"):
|
||||
|
||||
sram_config.set_local_config(self)
|
||||
|
||||
# reset the static duplicate name checker for unit tests
|
||||
# in case we create more than one SRAM
|
||||
from design import design
|
||||
design.name_map=[]
|
||||
|
||||
debug.info(2, "create sram of size {0} with {1} num of words".format(word_size,
|
||||
num_words))
|
||||
debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size,
|
||||
self.num_words,
|
||||
self.num_banks))
|
||||
start_time = datetime.datetime.now()
|
||||
|
||||
self.name = name
|
||||
|
||||
if num_banks == 1:
|
||||
from sram_1bank import sram_1bank
|
||||
self.s=sram_1bank(word_size, num_words, name)
|
||||
elif num_banks == 2:
|
||||
from sram_2bank import sram_2bank
|
||||
self.s=sram_2bank(word_size, num_words, name)
|
||||
elif num_banks == 4:
|
||||
from sram_4bank import sram_4bank
|
||||
self.s=sram_4bank(word_size, num_words, name)
|
||||
if self.num_banks == 1:
|
||||
from sram_1bank import sram_1bank as sram
|
||||
elif self.num_banks == 2:
|
||||
from sram_2bank import sram_2bank as sram
|
||||
elif self.num_banks == 4:
|
||||
from sram_4bank import sram_4bank as sram
|
||||
else:
|
||||
debug.error("Invalid number of banks.",-1)
|
||||
|
||||
|
||||
self.s = sram(sram_config, name)
|
||||
self.s.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
self.s.create_layout()
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ class sram_1bank(sram_base):
|
|||
"""
|
||||
Procedures specific to a one bank SRAM.
|
||||
"""
|
||||
def __init__(self, word_size, num_words, name):
|
||||
sram_base.__init__(self, word_size, num_words, 1, name)
|
||||
def __init__(self, sram_config, name):
|
||||
sram_base.__init__(self, sram_config, name)
|
||||
|
||||
|
||||
def create_netlist(self):
|
||||
self.compute_sizes()
|
||||
|
|
@ -99,18 +100,18 @@ class sram_1bank(sram_base):
|
|||
|
||||
for i in range(self.word_size):
|
||||
dout_name = "dout0[{}]".format(i)
|
||||
self.copy_layout_pin(self.bank_inst, dout_name, "DOUT[{}]".format(i))
|
||||
self.copy_layout_pin(self.bank_inst, dout_name, "DOUT0[{}]".format(i))
|
||||
|
||||
# Lower address bits
|
||||
for i in range(self.col_addr_size):
|
||||
self.copy_layout_pin(self.col_addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i))
|
||||
self.copy_layout_pin(self.col_addr_dff_inst, "din[{}]".format(i),"ADDR0[{}]".format(i))
|
||||
# Upper address bits
|
||||
for i in range(self.row_addr_size):
|
||||
self.copy_layout_pin(self.row_addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i+self.col_addr_size))
|
||||
self.copy_layout_pin(self.row_addr_dff_inst, "din[{}]".format(i),"ADDR0[{}]".format(i+self.col_addr_size))
|
||||
|
||||
for i in range(self.word_size):
|
||||
din_name = "din[{}]".format(i)
|
||||
self.copy_layout_pin(self.data_dff_inst, din_name, din_name.upper())
|
||||
self.copy_layout_pin(self.data_dff_inst, din_name, "DIN0[{}]".format(i))
|
||||
|
||||
def route(self):
|
||||
""" Route a single bank SRAM """
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ class sram_2bank(sram_base):
|
|||
"""
|
||||
Procedures specific to a two bank SRAM.
|
||||
"""
|
||||
def __init__(self, word_size, num_words, name):
|
||||
sram_base.__init__(self, word_size, num_words, 2, name)
|
||||
def __init__(self, sram_config, name):
|
||||
sram_base.__init__(self, sram_config, name)
|
||||
|
||||
def compute_bank_offsets(self):
|
||||
""" Compute the overall offsets for a two bank SRAM """
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ class sram_4bank(sram_base):
|
|||
"""
|
||||
Procedures specific to a four bank SRAM.
|
||||
"""
|
||||
def __init__(self, word_size, num_words, name):
|
||||
sram_base.__init__(self, word_size, num_words, 4, name)
|
||||
def __init__(self, sram_config, name):
|
||||
sram_base.__init__(self, sram_config, name)
|
||||
|
||||
def compute_bank_offsets(self):
|
||||
""" Compute the overall offsets for a four bank SRAM """
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import sys
|
|||
import datetime
|
||||
import getpass
|
||||
import debug
|
||||
from importlib import reload
|
||||
from math import log,sqrt,ceil
|
||||
from vector import vector
|
||||
from globals import OPTS, print_time
|
||||
|
|
@ -13,28 +14,17 @@ class sram_base(design):
|
|||
Dynamically generated SRAM by connecting banks to control logic. The
|
||||
number of banks should be 1 , 2 or 4
|
||||
"""
|
||||
def __init__(self, word_size, num_words, num_banks, name):
|
||||
def __init__(self, sram_config, name):
|
||||
design.__init__(self, name)
|
||||
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.control_logic))
|
||||
self.mod_control_logic = getattr(c, OPTS.control_logic)
|
||||
|
||||
# This is used to compute the sizes of the SRAM
|
||||
# and must be loaded before netlist creation
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
self.bitcell = self.mod_bitcell()
|
||||
|
||||
c = reload(__import__(OPTS.ms_flop))
|
||||
self.mod_ms_flop = getattr(c, OPTS.ms_flop)
|
||||
self.ms_flop = self.mod_ms_flop()
|
||||
|
||||
self.word_size = word_size
|
||||
self.num_words = num_words
|
||||
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
|
||||
self.sram_config = sram_config
|
||||
self.sram_config.set_local_config(self)
|
||||
|
||||
self.bank_insts = []
|
||||
|
||||
|
|
@ -45,18 +35,22 @@ class sram_base(design):
|
|||
|
||||
self.num_words_per_bank = self.num_words/self.num_banks
|
||||
self.num_bits_per_bank = self.word_size*self.num_words_per_bank
|
||||
|
||||
# If this was hard coded, don't dynamically compute it!
|
||||
if self.sram_config.words_per_row:
|
||||
self.words_per_row = self.sram_config.words_per_row
|
||||
else:
|
||||
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
|
||||
self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank
|
||||
self.bank_side_length = sqrt(self.bank_area)
|
||||
|
||||
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
|
||||
self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank
|
||||
self.bank_side_length = sqrt(self.bank_area)
|
||||
# Estimate the words per row given the height of the bitcell and the square side length
|
||||
self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width)
|
||||
self.words_per_row = self.estimate_words_per_row(self.tentative_num_cols, self.word_size)
|
||||
|
||||
# Estimate the words per row given the height of the bitcell and the square side length
|
||||
self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width)
|
||||
self.words_per_row = self.estimate_words_per_row(self.tentative_num_cols, self.word_size)
|
||||
|
||||
# Estimate the number of rows given the tentative words per row
|
||||
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
|
||||
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
|
||||
# Estimate the number of rows given the tentative words per row
|
||||
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
|
||||
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
|
||||
|
||||
# Fix the number of columns and rows
|
||||
self.num_cols = int(self.words_per_row*self.word_size)
|
||||
|
|
@ -67,7 +61,8 @@ class sram_base(design):
|
|||
self.col_addr_size = int(log(self.words_per_row, 2))
|
||||
self.bank_addr_size = self.col_addr_size + self.row_addr_size
|
||||
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
|
||||
|
||||
|
||||
self.sram_config.words_per_row = self.words_per_row
|
||||
debug.info(1,"Words per row: {}".format(self.words_per_row))
|
||||
|
||||
def estimate_words_per_row(self,tentative_num_cols, word_size):
|
||||
|
|
@ -279,7 +274,15 @@ class sram_base(design):
|
|||
|
||||
def add_modules(self):
|
||||
""" Create all the modules that will be used """
|
||||
|
||||
c = reload(__import__(OPTS.control_logic))
|
||||
self.mod_control_logic = getattr(c, OPTS.control_logic)
|
||||
|
||||
c = reload(__import__(OPTS.ms_flop))
|
||||
self.mod_ms_flop = getattr(c, OPTS.ms_flop)
|
||||
self.ms_flop = self.mod_ms_flop()
|
||||
|
||||
|
||||
from control_logic import control_logic
|
||||
# Create the control logic module
|
||||
self.control_logic = self.mod_control_logic(num_rows=self.num_rows)
|
||||
|
|
@ -301,10 +304,7 @@ class sram_base(design):
|
|||
|
||||
# Create the bank module (up to four are instantiated)
|
||||
from bank import bank
|
||||
self.bank = bank(word_size=self.word_size,
|
||||
num_words=self.num_words_per_bank,
|
||||
words_per_row=self.words_per_row,
|
||||
num_banks=self.num_banks,
|
||||
self.bank = bank(self.sram_config,
|
||||
name="bank")
|
||||
self.add_mod(self.bank)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
from globals import OPTS
|
||||
|
||||
class sram_config:
|
||||
""" This is a structure that is used to hold the SRAM configuration options. """
|
||||
|
||||
def __init__(self, word_size, num_words, num_banks=1, num_rw_ports=OPTS.num_rw_ports, num_w_ports=OPTS.num_w_ports, num_r_ports=OPTS.num_r_ports):
|
||||
self.word_size = word_size
|
||||
self.num_words = num_words
|
||||
self.num_banks = num_banks
|
||||
self.num_rw_ports = num_rw_ports
|
||||
self.num_w_ports = num_w_ports
|
||||
self.num_r_ports = num_r_ports
|
||||
|
||||
# This will get over-written when we determine the organization
|
||||
self.num_banks = 1
|
||||
self.words_per_row = None
|
||||
|
||||
self.total_write = num_rw_ports + num_w_ports
|
||||
self.total_read = num_rw_ports + num_r_ports
|
||||
self.total_ports = num_rw_ports + num_w_ports + num_r_ports
|
||||
|
||||
|
||||
def set_local_config(self, module):
|
||||
module.word_size = self.word_size
|
||||
module.num_words = self.num_words
|
||||
module.num_banks = self.num_banks
|
||||
module.num_rw_ports = self.num_rw_ports
|
||||
module.num_w_ports = self.num_w_ports
|
||||
module.num_r_ports = self.num_r_ports
|
||||
|
||||
module.words_per_row = self.words_per_row
|
||||
|
||||
module.total_write = self.total_write
|
||||
module.total_read = self.total_read
|
||||
module.total_ports = self.total_ports
|
||||
|
||||
|
|
@ -22,43 +22,43 @@ class pbitcell_test(openram_test):
|
|||
import tech
|
||||
|
||||
debug.info(2, "Bitcell with 1 of each port: read/write, write, and read")
|
||||
tx = pbitcell.pbitcell(num_readwrite=1,num_write=1,num_read=1)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=1,num_r_ports=1)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Bitcell with 0 read/write ports")
|
||||
tx = pbitcell.pbitcell(num_readwrite=0,num_write=1,num_read=1)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=0,num_w_ports=1,num_r_ports=1)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Bitcell with 0 write ports")
|
||||
tx = pbitcell.pbitcell(num_readwrite=1,num_write=0,num_read=1)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=0,num_r_ports=1)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Bitcell with 0 read ports")
|
||||
tx = pbitcell.pbitcell(num_readwrite=1,num_write=1,num_read=0)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=1,num_r_ports=0)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
|
||||
tx = pbitcell.pbitcell(num_readwrite=1,num_write=0,num_read=0)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=0,num_r_ports=0)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Bitcell with 2 of each port: read/write, write, and read")
|
||||
tx = pbitcell.pbitcell(num_readwrite=2,num_write=2,num_read=2)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=2,num_r_ports=2)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Bitcell with 0 read/write ports")
|
||||
tx = pbitcell.pbitcell(num_readwrite=0,num_write=2,num_read=2)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=0,num_w_ports=2,num_r_ports=2)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Bitcell with 0 write ports")
|
||||
tx = pbitcell.pbitcell(num_readwrite=2,num_write=0,num_read=2)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=0,num_r_ports=2)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Bitcell with 0 read ports")
|
||||
tx = pbitcell.pbitcell(num_readwrite=2,num_write=2,num_read=0)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=2,num_r_ports=0)
|
||||
self.local_check(tx)
|
||||
|
||||
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
|
||||
tx = pbitcell.pbitcell(num_readwrite=2,num_write=0,num_read=0)
|
||||
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=0,num_r_ports=0)
|
||||
self.local_check(tx)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ class precharge_test(openram_test):
|
|||
|
||||
debug.info(2, "Checking precharge for pbitcell")
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.r_ports = 2
|
||||
OPTS.w_ports = 2
|
||||
OPTS.num_rw_ports = 2
|
||||
OPTS.num_r_ports = 2
|
||||
OPTS.num_w_ports = 2
|
||||
tx = precharge.precharge(name="precharge_driver", size=1, bitcell_bl="rwbl0", bitcell_br="rwbl_bar0")
|
||||
self.local_check(tx)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,25 +20,25 @@ class pbitcell_array_test(openram_test):
|
|||
|
||||
debug.info(2, "Testing 4x4 array for multiport bitcell, with read ports at the edge of the bit cell")
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.r_ports = 2
|
||||
OPTS.w_ports = 2
|
||||
OPTS.num_rw_ports = 2
|
||||
OPTS.num_r_ports = 2
|
||||
OPTS.num_w_ports = 2
|
||||
a = bitcell_array.bitcell_array(name="pbitcell_array_Rport_edge", cols=4, rows=4)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing 4x4 array for multiport bitcell, with write ports at the edge of the bit cell")
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.r_ports = 0
|
||||
OPTS.w_ports = 2
|
||||
OPTS.num_rw_ports = 2
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 2
|
||||
a = bitcell_array.bitcell_array(name="pbitcell_array_Wport_edge", cols=4, rows=4)
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(2, "Testing 4x4 array for multiport bitcell, with read/write ports at the edge of the bit cell")
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.r_ports = 0
|
||||
OPTS.w_ports = 0
|
||||
OPTS.num_rw_ports = 2
|
||||
OPTS.num_r_ports = 0
|
||||
OPTS.num_w_ports = 0
|
||||
a = bitcell_array.bitcell_array(name="pbitcell_array_RWport_edge", cols=4, rows=4)
|
||||
self.local_check(a)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ class precharge_test(openram_test):
|
|||
|
||||
debug.info(2, "Checking precharge for pbitcell")
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.r_ports = 2
|
||||
OPTS.w_ports = 2
|
||||
OPTS.num_rw_ports = 2
|
||||
OPTS.num_r_ports = 2
|
||||
OPTS.num_w_ports = 2
|
||||
|
||||
pc = precharge_array.precharge_array(columns=3, bitcell_bl="rwbl0", bitcell_br="rwbl_bar0")
|
||||
self.local_check(pc)
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ class wordline_driver_test(openram_test):
|
|||
|
||||
# check wordline driver array in multi-port
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.rw_ports = 1
|
||||
OPTS.w_ports = 0
|
||||
OPTS.r_ports = 0
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
debug.info(2, "Checking driver (multi-port case)")
|
||||
tx = wordline_driver.wordline_driver(rows=8)
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ class sense_amp_test(openram_test):
|
|||
|
||||
# check sense amp array in multi-port
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.rw_ports = 1
|
||||
OPTS.w_ports = 0
|
||||
OPTS.r_ports = 0
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=2 (multi-port case)")
|
||||
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=2)
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ class write_driver_test(openram_test):
|
|||
|
||||
# check write driver array in multi-port
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.rw_ports = 1
|
||||
OPTS.w_ports = 0
|
||||
OPTS.r_ports = 0
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
debug.info(2, "Testing write_driver_array for columns=8, word_size=8 (multi-port case)")
|
||||
a = write_driver_array.write_driver_array(columns=8, word_size=8)
|
||||
|
|
|
|||
|
|
@ -16,21 +16,34 @@ class multi_bank_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
from bank import bank
|
||||
from sram_config import sram_config
|
||||
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16)
|
||||
c.num_banks=2
|
||||
|
||||
c.words_per_row=1
|
||||
debug.info(1, "No column mux")
|
||||
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=2, name="bank1_multi")
|
||||
a = bank(c, name="bank1_multi")
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=32
|
||||
c.words_per_row=2
|
||||
debug.info(1, "Two way column mux")
|
||||
a = bank(word_size=4, num_words=32, words_per_row=2, num_banks=2, name="bank2_multi")
|
||||
a = bank(c, name="bank2_multi")
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=64
|
||||
c.words_per_row=4
|
||||
debug.info(1, "Four way column mux")
|
||||
a = bank(word_size=4, num_words=64, words_per_row=4, num_banks=2, name="bank3_multi")
|
||||
a = bank(c, name="bank3_multi")
|
||||
self.local_check(a)
|
||||
|
||||
c.word_size=2
|
||||
c.num_words=128
|
||||
c.words_per_row=8
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = bank(word_size=2, num_words=128, words_per_row=8, num_banks=2, name="bank4_multi")
|
||||
a = bank(c, name="bank4_multi")
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -20,80 +20,103 @@ class psingle_bank_test(openram_test):
|
|||
import verify
|
||||
|
||||
from bank import bank
|
||||
from sram_config import sram_config
|
||||
OPTS.bitcell = "pbitcell"
|
||||
|
||||
# testing layout of bank using pbitcell with 1 RW port (a 6T-cell equivalent)
|
||||
OPTS.rw_ports = 1
|
||||
OPTS.w_ports = 0
|
||||
OPTS.r_ports = 0
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16)
|
||||
c.words_per_row=1
|
||||
debug.info(1, "No column mux")
|
||||
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_1rw_0w_0r_single")
|
||||
a = bank(c, name="bank1_1rw_0w_0r_single")
|
||||
self.local_check(a)
|
||||
|
||||
"""
|
||||
# testing all port configurations (with no column mux) to verify layout between bitcell array and peripheral circuitry
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.w_ports = 2
|
||||
OPTS.r_ports = 2
|
||||
|
||||
# multiport can't generate layout yet on the bank level
|
||||
OPTS.netlist_only = True
|
||||
|
||||
debug.info(1, "No column mux")
|
||||
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_2rw_2w_2r_single")
|
||||
self.local_check(a)
|
||||
"""
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
|
||||
"""
|
||||
OPTS.rw_ports = 0
|
||||
OPTS.w_ports = 2
|
||||
OPTS.r_ports = 2
|
||||
|
||||
debug.info(1, "No column mux")
|
||||
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_0rw_2w_2r_single")
|
||||
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||
a = bank(c, name=name)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.w_ports = 0
|
||||
OPTS.r_ports = 2
|
||||
OPTS.num_rw_ports = c.num_rw_ports = 2
|
||||
OPTS.num_w_ports = c.num_w_ports = 2
|
||||
OPTS.num_r_ports = c.num_r_ports = 2
|
||||
|
||||
debug.info(1, "No column mux")
|
||||
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_2rw_0w_2r_single")
|
||||
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||
a = bank(c, name=name)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.num_rw_ports = c.num_rw_ports = 0
|
||||
OPTS.num_w_ports = c.num_w_ports = 2
|
||||
OPTS.num_r_ports = c.num_r_ports = 2
|
||||
|
||||
debug.info(1, "No column mux")
|
||||
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||
a = bank(c, name=name)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.w_ports = 2
|
||||
OPTS.r_ports = 0
|
||||
OPTS.num_rw_ports = c.num_rw_ports = 2
|
||||
OPTS.num_w_ports = c.num_w_ports = 0
|
||||
OPTS.num_r_ports = c.num_r_ports = 2
|
||||
|
||||
debug.info(1, "No column mux")
|
||||
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_2rw_2w_0r_single")
|
||||
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||
a = bank(c, name=name)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.w_ports = 0
|
||||
OPTS.r_ports = 0
|
||||
OPTS.num_rw_ports = c.num_rw_ports = 2
|
||||
OPTS.num_w_ports = c.num_w_ports = 2
|
||||
OPTS.num_r_ports = c.num_r_ports = 0
|
||||
|
||||
debug.info(1, "No column mux")
|
||||
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_2rw_0w_0r_single")
|
||||
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||
a = bank(c, name=name)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.num_rw_ports = c.num_rw_ports = 2
|
||||
OPTS.num_w_ports = c.num_w_ports = 0
|
||||
OPTS.num_r_ports = c.num_r_ports = 0
|
||||
|
||||
debug.info(1, "No column mux")
|
||||
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||
a = bank(c, name=name)
|
||||
self.local_check(a)
|
||||
|
||||
# testing with various column muxes
|
||||
OPTS.rw_ports = 2
|
||||
OPTS.w_ports = 2
|
||||
OPTS.r_ports = 2
|
||||
OPTS.num_rw_ports = c.num_rw_ports = 2
|
||||
OPTS.num_w_ports = c.num_w_ports = 2
|
||||
OPTS.num_r_ports = c.num_r_ports = 2
|
||||
|
||||
c.num_words=32
|
||||
c.words_per_row=2
|
||||
debug.info(1, "Two way column mux")
|
||||
a = bank(word_size=4, num_words=32, words_per_row=2, num_banks=1, name="bank2_single")
|
||||
name = "bank2_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||
a = bank(c, name=name)
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=64
|
||||
c.words_per_row=4
|
||||
debug.info(1, "Four way column mux")
|
||||
a = bank(word_size=4, num_words=64, words_per_row=4, num_banks=1, name="bank3_single")
|
||||
name = "bank3_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||
a = bank(c, name=name)
|
||||
self.local_check(a)
|
||||
|
||||
# Eight way has a short circuit of one column mux select to gnd rail
|
||||
c.word_size=2
|
||||
c.num_words=128
|
||||
c.words_per_row=8
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = bank(word_size=2, num_words=128, words_per_row=8, num_banks=1, name="bank4_single")
|
||||
name = "bank4_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
|
||||
a = bank(c, name=name)
|
||||
self.local_check(a)
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -16,22 +16,34 @@ class single_bank_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
from bank import bank
|
||||
from sram_config import sram_config
|
||||
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16)
|
||||
|
||||
c.words_per_row=1
|
||||
debug.info(1, "No column mux")
|
||||
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_single")
|
||||
self.local_check(a)
|
||||
|
||||
debug.info(1, "Two way column mux")
|
||||
a = bank(word_size=4, num_words=32, words_per_row=2, num_banks=1, name="bank2_single")
|
||||
a = bank(c, name="bank1_single")
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=32
|
||||
c.words_per_row=2
|
||||
debug.info(1, "Two way column mux")
|
||||
a = bank(c, name="bank2_single")
|
||||
self.local_check(a)
|
||||
|
||||
c.num_words=64
|
||||
c.words_per_row=4
|
||||
debug.info(1, "Four way column mux")
|
||||
a = bank(word_size=4, num_words=64, words_per_row=4, num_banks=1, name="bank3_single")
|
||||
a = bank(c, name="bank3_single")
|
||||
self.local_check(a)
|
||||
|
||||
# Eight way has a short circuit of one column mux select to gnd rail
|
||||
c.word_size=2
|
||||
c.num_words=128
|
||||
c.words_per_row=8
|
||||
debug.info(1, "Eight way column mux")
|
||||
a = bank(word_size=2, num_words=128, words_per_row=8, num_banks=1, name="bank4_single")
|
||||
a = bank(c, name="bank4_single")
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -16,22 +16,33 @@ class sram_1bank_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
from sram import sram
|
||||
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
debug.info(1, "Single bank, no column mux with control logic")
|
||||
a = sram(word_size=4, num_words=16, num_banks=1, name="sram1")
|
||||
a = sram(c, name="sram1")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
# debug.info(1, "Single bank two way column mux with control logic")
|
||||
# a = sram(word_size=4, num_words=32, num_banks=1, name="sram2")
|
||||
# self.local_check(a, final_verification=True)
|
||||
c.num_words=32
|
||||
c.words_per_row=2
|
||||
debug.info(1, "Single bank two way column mux with control logic")
|
||||
a = sram(c, name="sram2")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
# debug.info(1, "Single bank, four way column mux with control logic")
|
||||
# a = sram(word_size=4, num_words=64, num_banks=1, name="sram3")
|
||||
# self.local_check(a, final_verification=True)
|
||||
c.num_words=64
|
||||
c.words_per_row=4
|
||||
debug.info(1, "Single bank, four way column mux with control logic")
|
||||
a = sram(c, name="sram3")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
# debug.info(1, "Single bank, eight way column mux with control logic")
|
||||
# a = sram(word_size=2, num_words=128, num_banks=1, name="sram4")
|
||||
# self.local_check(a, final_verification=True)
|
||||
c.word_size=2
|
||||
c.num_words=128
|
||||
c.words_per_row=8
|
||||
debug.info(1, "Single bank, eight way column mux with control logic")
|
||||
a = sram(c, name="sram4")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
|
|
|
|||
|
|
@ -17,21 +17,32 @@ class sram_2bank_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=16,
|
||||
num_words=32,
|
||||
num_banks=2)
|
||||
|
||||
debug.info(1, "Two bank, no column mux with control logic")
|
||||
a = sram(word_size=16, num_words=32, num_banks=2, name="sram1")
|
||||
a = sram(c, name="sram1")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
c.num_words=64
|
||||
c.words_per_row=2
|
||||
debug.info(1, "Two bank two way column mux with control logic")
|
||||
a = sram(word_size=16, num_words=64, num_banks=2, name="sram2")
|
||||
a = sram(c, name="sram2")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
c.num_words=128
|
||||
c.words_per_row=4
|
||||
debug.info(1, "Two bank, four way column mux with control logic")
|
||||
a = sram(word_size=16, num_words=128, num_banks=2, name="sram3")
|
||||
a = sram(c, name="sram3")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
c.word_size=2
|
||||
c.num_words=256
|
||||
c.words_per_row=8
|
||||
debug.info(1, "Two bank, eight way column mux with control logic")
|
||||
a = sram(word_size=2, num_words=256, num_banks=2, name="sram4")
|
||||
a = sram(c, name="sram4")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -17,19 +17,30 @@ class sram_4bank_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=16,
|
||||
num_words=64,
|
||||
num_banks=4)
|
||||
|
||||
debug.info(1, "Four bank, no column mux with control logic")
|
||||
a = sram(word_size=16, num_words=64, num_banks=4, name="sram1")
|
||||
a = sram(c, name="sram1")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
c.num_words=128
|
||||
c.words_per_row=2
|
||||
debug.info(1, "Four bank two way column mux with control logic")
|
||||
a = sram(word_size=16, num_words=128, num_banks=4, name="sram2")
|
||||
a = sram(c, name="sram2")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
c.num_words=256
|
||||
c.words_per_row=4
|
||||
debug.info(1, "Four bank, four way column mux with control logic")
|
||||
a = sram(word_size=16, num_words=256, num_banks=4, name="sram3")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
c.word_size=2
|
||||
c.num_words=256
|
||||
c.words_per_row=8
|
||||
debug.info(1, "Four bank, eight way column mux with control logic")
|
||||
a = sram.sram(word_size=2, num_words=256, num_banks=4, name="sram4")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@ class timing_sram_test(openram_test):
|
|||
if not OPTS.spice_exe:
|
||||
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
|
||||
|
||||
import sram
|
||||
import tech
|
||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
||||
s = sram.sram(word_size=OPTS.word_size,
|
||||
num_words=OPTS.num_words,
|
||||
num_banks=OPTS.num_banks,
|
||||
name="sram1")
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=1,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
||||
s = sram(c, name="sram1")
|
||||
|
||||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
|
|
|||
|
|
@ -27,13 +27,14 @@ class timing_sram_test(openram_test):
|
|||
if not OPTS.spice_exe:
|
||||
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
|
||||
|
||||
import sram
|
||||
import tech
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=1,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
||||
s = sram.sram(word_size=OPTS.word_size,
|
||||
num_words=OPTS.num_words,
|
||||
num_banks=OPTS.num_banks,
|
||||
name="sram1")
|
||||
s = sram(c, name="sram1")
|
||||
|
||||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
|
|
|||
|
|
@ -16,15 +16,16 @@ class lib_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
|
||||
import sram
|
||||
from characterizer import lib
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=2,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
debug.info(1, "Testing analytical timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
|
||||
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||
s = sram.sram(word_size=2,
|
||||
num_words=16,
|
||||
num_banks=1,
|
||||
name="sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
|
||||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
|
|
|
|||
|
|
@ -26,13 +26,14 @@ class lib_test(openram_test):
|
|||
if not OPTS.spice_exe:
|
||||
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
|
||||
|
||||
import sram
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=2,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||
s = sram.sram(word_size=2,
|
||||
num_words=16,
|
||||
num_banks=1,
|
||||
name="sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
debug.info(1, "Testing pruned timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
|
||||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
|
|
|||
|
|
@ -26,13 +26,14 @@ class lib_test(openram_test):
|
|||
if not OPTS.spice_exe:
|
||||
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
|
||||
|
||||
import sram
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=2,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
|
||||
s = sram.sram(word_size=2,
|
||||
num_words=16,
|
||||
num_banks=1,
|
||||
name="sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
|
||||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
|
|
|||
|
|
@ -17,13 +17,14 @@ class lef_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
|
||||
import sram
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=2,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank")
|
||||
s = sram.sram(word_size=2,
|
||||
num_words=OPTS.num_words,
|
||||
num_banks=OPTS.num_banks,
|
||||
name="sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
|
||||
gdsfile = s.name + ".gds"
|
||||
leffile = s.name + ".lef"
|
||||
|
|
|
|||
|
|
@ -16,13 +16,14 @@ class verilog_test(openram_test):
|
|||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
|
||||
import sram
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=2,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank")
|
||||
s = sram.sram(word_size=2,
|
||||
num_words=OPTS.num_words,
|
||||
num_banks=OPTS.num_banks,
|
||||
name="sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
|
||||
|
||||
vfile = s.name + ".v"
|
||||
vname = OPTS.openram_temp + vfile
|
||||
|
|
|
|||
Loading…
Reference in New Issue