Merging changes and updating multiport syntax across several tests

This commit is contained in:
Michael Timothy Grimes 2018-09-03 19:36:20 -07:00
commit af0756382f
31 changed files with 580 additions and 451 deletions

View File

@ -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! # Note that if we re-read a config file, nothing will get read again!
if not k in OPTS.__dict__ or k=="tech_name": if not k in OPTS.__dict__ or k=="tech_name":
OPTS.__dict__[k]=v OPTS.__dict__[k]=v
# Massage the output path to be an absolute one
if not OPTS.output_path.endswith('/'): if not OPTS.output_path.endswith('/'):
OPTS.output_path += "/" OPTS.output_path += "/"
if not OPTS.output_path.startswith('/'): if not OPTS.output_path.startswith('/'):
OPTS.output_path = os.getcwd() + "/" + OPTS.output_path OPTS.output_path = os.getcwd() + "/" + OPTS.output_path
debug.info(1, "Output saved in " + 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 OPTS.is_unit_test=is_unit_test
# If we are only generating a netlist, we can't do DRC/LVS # If we are only generating a netlist, we can't do DRC/LVS
if OPTS.netlist_only: if OPTS.netlist_only:
OPTS.check_lvsdrc=False OPTS.check_lvsdrc=False
# If config didn't set output name, make a reasonable default. # If config didn't set output name, make a reasonable default.
if (OPTS.output_name == ""): if (OPTS.output_name == ""):
OPTS.output_name = "sram_{0}rw_{1}b_{2}w_{3}bank_{4}".format(OPTS.rw_ports, OPTS.output_name = "sram_{0}b_{1}w_{2}bank_{3}rw_{4}w_{5}r_{6}".format(OPTS.word_size,
OPTS.word_size, OPTS.num_words,
OPTS.num_words, OPTS.num_banks,
OPTS.num_banks, OPTS.num_rw_ports,
OPTS.tech_name) OPTS.num_w_ports,
OPTS.num_r_ports,
OPTS.tech_name)
# Don't delete the output dir, it may have other files! # Don't delete the output dir, it may have other files!
# make the directory if it doesn't exist # make the directory if it doesn't exist

View File

@ -20,22 +20,16 @@ class bank(design.design):
write driver and sense amplifiers. 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 == "": sram_config.set_local_config(self)
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
self.total_write = OPTS.rw_ports + OPTS.w_ports if name == "":
self.total_read = OPTS.rw_ports + OPTS.r_ports name = "bank_{0}_{1}".format(self.word_size, self.num_words)
self.total_ports = OPTS.rw_ports + OPTS.w_ports + OPTS.r_ports 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, # 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.
@ -70,25 +64,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 port in range(self.total_read):
for i in range(self.word_size): for bit in range(self.word_size):
self.add_pin("dout{0}[{1}]".format(k,i),"OUT") self.add_pin("dout{0}[{1}]".format(port,bit),"OUT")
for k in range(self.total_write): for port in range(self.total_write):
for i in range(self.word_size): for bit in range(self.word_size):
self.add_pin("din{0}[{1}]".format(k,i),"IN") self.add_pin("din{0}[{1}]".format(port,bit),"IN")
for k in range(self.total_ports): for port in range(self.total_ports):
for i in range(self.addr_size): for bit in range(self.addr_size):
self.add_pin("addr{0}[{1}]".format(k,i),"INPUT") self.add_pin("addr{0}[{1}]".format(port,bit),"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:
for port in range(self.total_ports): for port in range(self.total_ports):
self.add_pin("bank_sel{}".format(port),"INPUT") self.add_pin("bank_sel{}".format(port),"INPUT")
for k in range(self.total_read): for port in range(self.total_read):
self.add_pin("s_en{0}".format(k), "INPUT") self.add_pin("s_en{0}".format(port), "INPUT")
for k in range(self.total_write): for port in range(self.total_write):
self.add_pin("w_en{0}".format(k), "INPUT") self.add_pin("w_en{0}".format(port), "INPUT")
for pin in ["clk_buf_bar","clk_buf"]: for pin in ["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")
@ -229,9 +223,9 @@ class bank(design.design):
self.total_bitline_list = self.bitcell.list_all_bitline_names() self.total_bitline_list = self.bitcell.list_all_bitline_names()
self.precharge_array = [] self.precharge_array = []
for k in range(self.total_read): 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[k], bitcell_br=self.read_br_list[k])) 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[k]) self.add_mod(self.precharge_array[port])
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,
@ -288,13 +282,13 @@ class bank(design.design):
""" Creating Precharge """ """ Creating Precharge """
self.precharge_array_inst = [] self.precharge_array_inst = []
for k in range(self.total_read): for port in range(self.total_read):
self.precharge_array_inst.append(self.add_inst(name="precharge_array{}".format(k), self.precharge_array_inst.append(self.add_inst(name="precharge_array{}".format(port),
mod=self.precharge_array[k])) mod=self.precharge_array[port]))
temp = [] temp = []
for i in range(self.num_cols): for i in range(self.num_cols):
temp.append(self.read_bl_list[k]+"[{0}]".format(i)) temp.append(self.read_bl_list[port]+"[{0}]".format(i))
temp.append(self.read_br_list[k]+"[{0}]".format(i)) temp.append(self.read_br_list[port]+"[{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)
@ -302,11 +296,11 @@ class bank(design.design):
""" Placing Precharge """ """ Placing Precharge """
# FIXME: place for multiport # 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 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[k].place(vector(0,y_offset)) self.precharge_array_inst[port].place(vector(0,y_offset))
def create_column_mux_array(self): def create_column_mux_array(self):
""" Creating Column Mux when words_per_row > 1 . """ """ Creating Column Mux when words_per_row > 1 . """
@ -314,19 +308,19 @@ class bank(design.design):
return return
self.col_mux_array_inst = [] self.col_mux_array_inst = []
for k in range(self.total_ports): for port in range(self.total_ports):
self.col_mux_array_inst.append(self.add_inst(name="column_mux_array{}".format(k), self.col_mux_array_inst.append(self.add_inst(name="column_mux_array{}".format(port),
mod=self.column_mux_array)) mod=self.column_mux_array))
temp = [] temp = []
for i in range(self.num_cols): for col in range(self.num_cols):
temp.append(self.total_bl_list[k]+"[{0}]".format(i)) temp.append(self.total_bl_list[port]+"[{0}]".format(col))
temp.append(self.total_br_list[k]+"[{0}]".format(i)) temp.append(self.total_br_list[port]+"[{0}]".format(col))
for h in range(self.words_per_row): for word in range(self.words_per_row):
temp.append("sel{0}[{1}]".format(k,h)) temp.append("sel{0}[{1}]".format(port,word))
for j in range(self.word_size): for bit in range(self.word_size):
temp.append(self.total_bl_list[k]+"_out[{0}]".format(j)) temp.append(self.total_bl_list[port]+"_out[{0}]".format(bit))
temp.append(self.total_br_list[k]+"_out[{0}]".format(j)) temp.append(self.total_br_list[port]+"_out[{0}]".format(bit))
temp.append("gnd") temp.append("gnd")
self.connect_inst(temp) self.connect_inst(temp)
@ -338,68 +332,68 @@ class bank(design.design):
self.column_mux_height = 0 self.column_mux_height = 0
return return
for k in range(self.total_ports): for port in range(self.total_ports):
y_offset = self.column_mux_height 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): def create_sense_amp_array(self):
""" Creating Sense amp """ """ Creating Sense amp """
self.sense_amp_array_inst = [] self.sense_amp_array_inst = []
for k in range(self.total_read): for port in range(self.total_read):
self.sense_amp_array_inst.append(self.add_inst(name="sense_amp_array{}".format(k), self.sense_amp_array_inst.append(self.add_inst(name="sense_amp_array{}".format(port),
mod=self.sense_amp_array)) mod=self.sense_amp_array))
temp = [] temp = []
for i in range(self.word_size): for bit in range(self.word_size):
temp.append("dout{0}[{1}]".format(k,i)) temp.append("dout{0}[{1}]".format(port,bit))
if self.words_per_row == 1: if self.words_per_row == 1:
temp.append(self.read_bl_list[k]+"[{0}]".format(i)) temp.append(self.read_bl_list[port]+"[{0}]".format(bit))
temp.append(self.read_br_list[k]+"[{0}]".format(i)) temp.append(self.read_br_list[port]+"[{0}]".format(bit))
else: else:
temp.append(self.read_bl_list[k]+"_out[{0}]".format(i)) temp.append(self.read_bl_list[port]+"_out[{0}]".format(bit))
temp.append(self.read_br_list[k]+"_out[{0}]".format(i)) 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) self.connect_inst(temp)
def place_sense_amp_array(self): def place_sense_amp_array(self):
""" Placing Sense amp """ """ Placing Sense amp """
# FIXME: place for multiport # 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 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): def create_write_driver_array(self):
""" Creating Write Driver """ """ Creating Write Driver """
self.write_driver_array_inst = [] self.write_driver_array_inst = []
for k in range(self.total_write): for port in range(self.total_write):
self.write_driver_array_inst.append(self.add_inst(name="write_driver_array{}".format(k), self.write_driver_array_inst.append(self.add_inst(name="write_driver_array{}".format(port),
mod=self.write_driver_array)) mod=self.write_driver_array))
temp = [] temp = []
for i in range(self.word_size): for bit in range(self.word_size):
temp.append("din{0}[{1}]".format(k,i)) temp.append("din{0}[{1}]".format(port,bit))
for i in range(self.word_size): for bit in range(self.word_size):
if (self.words_per_row == 1): if (self.words_per_row == 1):
temp.append(self.write_bl_list[k]+"[{0}]".format(i)) temp.append(self.write_bl_list[port]+"[{0}]".format(bit))
temp.append(self.write_br_list[k]+"[{0}]".format(i)) temp.append(self.write_br_list[port]+"[{0}]".format(bit))
else: else:
temp.append(self.write_bl_list[k]+"_out[{0}]".format(i)) temp.append(self.write_bl_list[port]+"_out[{0}]".format(bit))
temp.append(self.write_br_list[k]+"_out[{0}]".format(i)) temp.append(self.write_br_list[port]+"_out[{0}]".format(bit))
temp.extend([self.prefix+"w_en{0}".format(k), "vdd", "gnd"]) temp.extend([self.prefix+"w_en{0}".format(port), "vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
def place_write_driver_array(self): def place_write_driver_array(self):
""" Placing Write Driver """ """ Placing Write Driver """
# FIXME: place for multiport # 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 \ 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[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 """ """ Create the hierarchical row decoder """
self.row_decoder_inst = [] self.row_decoder_inst = []
for k in range(self.total_ports): for port in range(self.total_ports):
self.row_decoder_inst.append(self.add_inst(name="row_decoder{}".format(k), self.row_decoder_inst.append(self.add_inst(name="row_decoder{}".format(port),
mod=self.row_decoder)) mod=self.row_decoder))
temp = [] temp = []
for i in range(self.row_addr_size): for bit in range(self.row_addr_size):
temp.append("addr{0}[{1}]".format(k,i+self.col_addr_size)) temp.append("addr{0}[{1}]".format(port,bit+self.col_addr_size))
for j in range(self.num_rows): for row in range(self.num_rows):
temp.append("dec_out{0}[{1}]".format(k,j)) temp.append("dec_out{0}[{1}]".format(port,row))
temp.extend(["vdd", "gnd"]) temp.extend(["vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
@ -429,24 +423,24 @@ class bank(design.design):
# The address flop and decoder are aligned in the x coord. # The address flop and decoder are aligned in the x coord.
# FIXME: place for multiport # 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) 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): def create_wordline_driver(self):
""" Create the Wordline Driver """ """ Create the Wordline Driver """
self.wordline_driver_inst = [] self.wordline_driver_inst = []
for k in range(self.total_ports): for port in range(self.total_ports):
self.wordline_driver_inst.append(self.add_inst(name="wordline_driver{}".format(k), self.wordline_driver_inst.append(self.add_inst(name="wordline_driver{}".format(port),
mod=self.wordline_driver)) mod=self.wordline_driver))
temp = [] temp = []
for i in range(self.num_rows): for row in range(self.num_rows):
temp.append("dec_out{0}[{1}]".format(k,i)) temp.append("dec_out{0}[{1}]".format(port,row))
for i in range(self.num_rows): for row in range(self.num_rows):
temp.append(self.total_wl_list[k]+"[{0}]".format(i)) temp.append(self.total_wl_list[port]+"[{0}]".format(row))
temp.append(self.prefix+"clk_buf") temp.append(self.prefix+"clk_buf")
temp.append("vdd") temp.append("vdd")
temp.append("gnd") temp.append("gnd")
@ -456,10 +450,10 @@ class bank(design.design):
""" Place the Wordline Driver """ """ Place the Wordline Driver """
# FIXME: place for multiport # 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. # 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[k].place(vector(x_offset,0)) self.wordline_driver_inst[port].place(vector(x_offset,0))
def create_column_decoder(self): def create_column_decoder(self):
@ -481,15 +475,15 @@ class bank(design.design):
debug.error("Invalid column decoder?",-1) debug.error("Invalid column decoder?",-1)
self.col_decoder_inst = [] self.col_decoder_inst = []
for k in range(self.total_ports): for port in range(self.total_ports):
self.col_decoder_inst.append(self.add_inst(name="col_address_decoder{}".format(k), self.col_decoder_inst.append(self.add_inst(name="col_address_decoder{}".format(port),
mod=self.col_decoder)) mod=self.col_decoder))
temp = [] temp = []
for i in range(self.col_addr_size): for bit in range(self.col_addr_size):
temp.append("addr{0}[{1}]".format(k,i)) temp.append("addr{0}[{1}]".format(port,bit))
for j in range(self.num_col_addr_lines): for bit in range(self.num_col_addr_lines):
temp.append("sel{0}[{1}]".format(k,j)) temp.append("sel{0}[{1}]".format(port,bit))
temp.extend(["vdd", "gnd"]) temp.extend(["vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
@ -501,11 +495,11 @@ class bank(design.design):
return return
# FIXME: place for multiport # 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 # 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[k].place(vector(x_off,y_off)) self.col_decoder_inst[port].place(vector(x_off,y_off))
def create_bank_select(self): def create_bank_select(self):
@ -533,7 +527,7 @@ class bank(design.design):
return return
# FIXME: place for multiport # 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) 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[0].by(), self.col_mux_array_inst[0].by()) 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.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[k].place(self.bank_select_pos) self.bank_select_inst[port].place(self.bank_select_pos)
def route_vdd_gnd(self): def route_vdd_gnd(self):
@ -550,19 +544,19 @@ 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]
for k in range(self.total_ports): for port in range(self.total_ports):
top_instances.extend([self.precharge_array_inst[k], top_instances.extend([self.precharge_array_inst[port],
self.sense_amp_array_inst[k], self.sense_amp_array_inst[port],
self.write_driver_array_inst[k], self.write_driver_array_inst[port],
self.row_decoder_inst[k], self.row_decoder_inst[port],
self.wordline_driver_inst[k]]) self.wordline_driver_inst[port]])
# 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[k]) top_instances.append(self.col_decoder_inst[port])
top_instances.append(self.col_mux_array_inst[k]) top_instances.append(self.col_mux_array_inst[port])
if self.num_banks > 1: 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: for inst in top_instances:
@ -576,13 +570,13 @@ class bank(design.design):
def route_bank_select(self): def route_bank_select(self):
""" Route the bank select logic. """ """ 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"]: 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: for gated_name in self.control_signals:
# Connect the inverter output to the central bus # 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) bus_pos = vector(self.bus_xoffset[gated_name].x, out_pos.y)
self.add_path("metal3",[out_pos, bus_pos]) self.add_path("metal3",[out_pos, bus_pos])
self.add_via_center(layers=("metal2", "via2", "metal3"), 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 """ """ Routing of BL and BR between pre-charge and bitcell array """
# FIXME: Update for multiport # FIXME: Update for multiport
for k in range(self.total_read): for port in range(self.total_read):
for i in range(self.num_cols): for col in range(self.num_cols):
precharge_bl = self.precharge_array_inst[k].get_pin("bl[{}]".format(i)).bc() precharge_bl = self.precharge_array_inst[port].get_pin("bl[{}]".format(col)).bc()
precharge_br = self.precharge_array_inst[k].get_pin("br[{}]".format(i)).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[k]+"[{}]".format(i)).uc() 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[k]+"[{}]".format(i)).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) 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),
@ -682,12 +676,12 @@ class bank(design.design):
return return
# FIXME: Update for multiport # FIXME: Update for multiport
for k in range(self.total_ports): for port in range(self.total_ports):
for i in range(self.num_cols): for col in range(self.num_cols):
col_mux_bl = self.col_mux_array_inst[k].get_pin("bl[{}]".format(i)).uc() col_mux_bl = self.col_mux_array_inst[port].get_pin("bl[{}]".format(col)).uc()
col_mux_br = self.col_mux_array_inst[k].get_pin("br[{}]".format(i)).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[k]+"[{}]".format(i)).bc() 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[k]+"[{}]".format(i)).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) 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),
@ -698,19 +692,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 port in range(self.total_read):
for i in range(self.word_size): for bit in range(self.word_size):
sense_amp_bl = self.sense_amp_array_inst[k].get_pin("bl[{}]".format(i)).uc() sense_amp_bl = self.sense_amp_array_inst[port].get_pin("bl[{}]".format(bit)).uc()
sense_amp_br = self.sense_amp_array_inst[k].get_pin("br[{}]".format(i)).uc() sense_amp_br = self.sense_amp_array_inst[port].get_pin("br[{}]".format(bit)).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[k].get_pin("bl_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[k].get_pin("br_out[{}]".format(i)).bc() connect_br = self.col_mux_array_inst[port].get_pin("br_out[{}]".format(bit)).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(self.read_bl_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[k]+"[{}]".format(i)).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) yoffset = 0.5*(sense_amp_bl.y+connect_bl.y)
@ -722,9 +716,11 @@ 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):
data_pin = self.sense_amp_array_inst[0].get_pin("data[{}]".format(i)) # FIXME: Update for multiport
self.add_layout_pin_rect_center(text="dout0[{}]".format(i), 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, layer=data_pin.layer,
offset=data_pin.center(), offset=data_pin.center(),
height=data_pin.height(), height=data_pin.height(),
@ -734,10 +730,11 @@ class bank(design.design):
def route_row_decoder(self): def route_row_decoder(self):
""" Routes the row decoder inputs and supplies """ """ Routes the row decoder inputs and supplies """
# FIXME: Update for multiport
# Create inputs for the row address lines # Create inputs for the row address lines
for i in range(self.row_addr_size): for row in range(self.row_addr_size):
addr_idx = i + self.col_addr_size addr_idx = row + self.col_addr_size
decoder_name = "addr[{}]".format(i) decoder_name = "addr[{}]".format(row)
addr_name = "addr0[{}]".format(addr_idx) addr_name = "addr0[{}]".format(addr_idx)
self.copy_layout_pin(self.row_decoder_inst[0], decoder_name, addr_name) 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): def route_write_driver(self):
""" Connecting write driver """ """ Connecting write driver """
for i in range(self.word_size): for row in range(self.word_size):
data_name = "data[{}]".format(i) data_name = "data[{}]".format(row)
din_name = "din0[{}]".format(i) din_name = "din0[{}]".format(row)
self.copy_layout_pin(self.write_driver_array_inst[0], data_name, din_name) 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): def route_wordline_driver(self):
""" Connecting Wordline driver output to Bitcell WL connection """ """ 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 # 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() 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(i)).lc() 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) 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[0].get_pin("wl[{}]".format(i)).rc() 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(i)).lc() 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) 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])

View File

@ -38,7 +38,8 @@ report_status()
# Start importing design modules after we have the config file # Start importing design modules after we have the config file
import verify import verify
import sram from sram import sram
from sram_config import sram_config
output_extensions = ["sp","v","lib"] output_extensions = ["sp","v","lib"]
if not OPTS.netlist_only: if not OPTS.netlist_only:
@ -51,11 +52,14 @@ print(*output_files,sep="\n")
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
print_time("Start",start_time) 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 # import SRAM test generation
s = sram.sram(word_size=OPTS.word_size, s = sram(c, OPTS.output_name)
num_words=OPTS.num_words,
num_banks=OPTS.num_banks,
name=OPTS.output_name)
# Output the files for the resulting SRAM # Output the files for the resulting SRAM
s.save() s.save()

View File

@ -52,9 +52,9 @@ class options(optparse.Values):
purge_temp = True purge_temp = True
# These are the configuration parameters # These are the configuration parameters
rw_ports = 1 num_rw_ports = 1
r_ports = 0 num_r_ports = 0
w_ports = 0 num_w_ports = 0
# These will get initialized by the the file # These will get initialized by the the file
supply_voltages = "" supply_voltages = ""
temperatures = "" temperatures = ""

View File

@ -16,18 +16,18 @@ class pbitcell(pgate.pgate):
width = None width = None
height = None height = None
unique_id = 1 def __init__(self, num_rw_ports=OPTS.num_rw_ports, num_w_ports=OPTS.num_w_ports, num_r_ports=OPTS.num_r_ports):
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))
self.num_readwrite = num_readwrite name = "pbitcell_{0}RW_{1}W_{2}R".format(num_rw_ports, num_w_ports, num_r_ports)
self.num_write = num_write pgate.pgate.__init__(self, name)
self.num_read = num_read 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() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
self.create_layout() self.create_layout()
@ -41,11 +41,11 @@ class pbitcell(pgate.pgate):
self.add_modules() self.add_modules()
self.create_storage() self.create_storage()
if(self.num_readwrite > 0): if(self.num_rw_ports > 0):
self.create_readwrite_ports() self.create_readwrite_ports()
if(self.num_write > 0): if(self.num_w_ports > 0):
self.create_write_ports() self.create_write_ports()
if(self.num_read > 0): if(self.num_r_ports > 0):
self.create_read_ports() self.create_read_ports()
def create_layout(self): def create_layout(self):
@ -56,11 +56,11 @@ class pbitcell(pgate.pgate):
self.route_storage() self.route_storage()
self.route_rails() self.route_rails()
if(self.num_readwrite > 0): if(self.num_rw_ports > 0):
self.place_readwrite_ports() self.place_readwrite_ports()
if(self.num_write > 0): if(self.num_w_ports > 0):
self.place_write_ports() self.place_write_ports()
if(self.num_read > 0): if(self.num_r_ports > 0):
self.place_read_ports() self.place_read_ports()
self.extend_well() self.extend_well()
@ -68,21 +68,21 @@ class pbitcell(pgate.pgate):
self.DRC_LVS() self.DRC_LVS()
def add_pins(self): 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{}".format(k))
self.add_pin("rwbl_bar{}".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{}".format(k))
self.add_pin("wbl_bar{}".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{}".format(k))
self.add_pin("rbl_bar{}".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)) 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)) 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("rwl{}".format(k))
self.add_pin("vdd") self.add_pin("vdd")
@ -90,8 +90,8 @@ class pbitcell(pgate.pgate):
def add_modules(self): def add_modules(self):
# if there are any read/write ports, then the inverter nmos is sized based the number of them # if there are any read/write ports, then the inverter nmos is sized based the number of them
if(self.num_readwrite > 0): if(self.num_rw_ports > 0):
inverter_nmos_width = self.num_readwrite*3*parameter["min_tx_size"] inverter_nmos_width = self.num_rw_ports*3*parameter["min_tx_size"]
inverter_pmos_width = parameter["min_tx_size"] inverter_pmos_width = parameter["min_tx_size"]
readwrite_nmos_width = 1.5*parameter["min_tx_size"] readwrite_nmos_width = 1.5*parameter["min_tx_size"]
write_nmos_width = 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) # 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 # 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): if(self.write_nmos_contact_extension > self.gate_contact_thres):
write_portion = drc["minwidth_metal2"] + self.write_nmos_contact_extension write_portion = drc["minwidth_metal2"] + self.write_nmos_contact_extension
else: else:
@ -206,23 +206,23 @@ class pbitcell(pgate.pgate):
Calculate positions that describe the edges of the cell 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 # 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 self.readwrite_port_flag = True
else: else:
self.readwrite_port_flag = False self.readwrite_port_flag = False
if(self.num_write > 0): if(self.num_w_ports > 0):
self.write_port_flag = True self.write_port_flag = True
else: else:
self.write_port_flag = False self.write_port_flag = False
if(self.num_read > 0): if(self.num_r_ports > 0):
self.read_port_flag = True self.read_port_flag = True
else: else:
self.read_port_flag = False self.read_port_flag = False
# determine the distance of the leftmost/rightmost transistor gate connection # 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): if(self.read_nmos_contact_extension > self.gate_contact_thres):
end_connection = drc["minwidth_metal2"] + self.read_nmos_contact_extension + contact.m1m2.height end_connection = drc["minwidth_metal2"] + self.read_nmos_contact_extension + contact.m1m2.height
else: 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 # 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.leftmost_xpos = -self.inverter_tile_width \
- self.inverter_to_write_spacing \ - 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.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.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 \ - end_connection \
- 0.5*drc["poly_to_polycontact"] - 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 # bottommost position = gnd height + rwwl height + wwl height + rwl height + space needed between tiled bitcells
array_tiling_offset = 0.5*drc["minwidth_metal2"] array_tiling_offset = 0.5*drc["minwidth_metal2"]
self.botmost_ypos = -self.rail_tile_height \ self.botmost_ypos = -self.rail_tile_height \
- self.num_readwrite*self.rowline_tile_height \ - self.num_rw_ports*self.rowline_tile_height \
- self.num_write*self.rowline_tile_height \ - self.num_w_ports*self.rowline_tile_height \
- self.num_read*self.rowline_tile_height \ - self.num_r_ports*self.rowline_tile_height \
- array_tiling_offset - array_tiling_offset
# topmost position = height of the inverter + height of vdd # 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 # 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_left = [None] * self.num_rw_ports
self.readwrite_nmos_right = [None] * self.num_readwrite self.readwrite_nmos_right = [None] * self.num_rw_ports
# iterate over the number of read/write 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 # add read/write transistors
self.readwrite_nmos_left[k] = self.add_inst(name="readwrite_nmos_left{}".format(k), self.readwrite_nmos_left[k] = self.add_inst(name="readwrite_nmos_left{}".format(k),
mod=self.readwrite_nmos) mod=self.readwrite_nmos)
@ -411,15 +411,15 @@ class pbitcell(pgate.pgate):
""" """
# Define variables relevant to write transistors # Define variables relevant to write transistors
self.rwwl_positions = [None] * self.num_readwrite self.rwwl_positions = [None] * self.num_rw_ports
self.rwbl_positions = [None] * self.num_readwrite self.rwbl_positions = [None] * self.num_rw_ports
self.rwbl_bar_positions = [None] * self.num_readwrite self.rwbl_bar_positions = [None] * self.num_rw_ports
# define offset correction due to rotation of the ptx module # define offset correction due to rotation of the ptx module
readwrite_rotation_correct = self.readwrite_nmos.active_height readwrite_rotation_correct = self.readwrite_nmos.active_height
# iterate over the number of read/write 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 transistors # Add transistors
# calculate read/write transistor offsets # calculate read/write transistor offsets
left_readwrite_transistor_xpos = self.left_building_edge \ left_readwrite_transistor_xpos = self.left_building_edge \
@ -529,7 +529,7 @@ class pbitcell(pgate.pgate):
# Drain/Storage connections # Drain/Storage connections
# this path only needs to be drawn once on the last iteration of the loop # 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 # 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) 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"), self.add_contact_center(layers=("poly", "contact", "metal1"),
@ -580,11 +580,11 @@ class pbitcell(pgate.pgate):
write_rotation_correct = self.write_nmos.active_height write_rotation_correct = self.write_nmos.active_height
# define write transistor variables as empty arrays based on the number of write ports # 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_left = [None] * self.num_w_ports
self.write_nmos_right = [None] * self.num_write self.write_nmos_right = [None] * self.num_w_ports
# iterate over the number of write 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 # add write transistors
self.write_nmos_left[k] = self.add_inst(name="write_nmos_left{}".format(k), self.write_nmos_left[k] = self.add_inst(name="write_nmos_left{}".format(k),
mod=self.write_nmos) mod=self.write_nmos)
@ -601,15 +601,15 @@ class pbitcell(pgate.pgate):
""" """
# Define variables relevant to write transistors # Define variables relevant to write transistors
self.wwl_positions = [None] * self.num_write self.wwl_positions = [None] * self.num_w_ports
self.wbl_positions = [None] * self.num_write self.wbl_positions = [None] * self.num_w_ports
self.wbl_bar_positions = [None] * self.num_write self.wbl_bar_positions = [None] * self.num_w_ports
# define offset correction due to rotation of the ptx module # define offset correction due to rotation of the ptx module
write_rotation_correct = self.write_nmos.active_height write_rotation_correct = self.write_nmos.active_height
# iterate over the number of write 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 transistors # Add transistors
# calculate write transistor offsets # calculate write transistor offsets
left_write_transistor_xpos = self.left_building_edge \ left_write_transistor_xpos = self.left_building_edge \
@ -634,7 +634,7 @@ class pbitcell(pgate.pgate):
# Add WWL lines # Add WWL lines
# calculate WWL position # calculate WWL position
wwl_ypos = self.gnd_position.y \ 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 - (k+1)*self.rowline_tile_height
self.wwl_positions[k] = vector(self.leftmost_xpos, wwl_ypos) self.wwl_positions[k] = vector(self.leftmost_xpos, wwl_ypos)
@ -723,7 +723,7 @@ class pbitcell(pgate.pgate):
# Drain/Storage connections # Drain/Storage connections
# this path only needs to be drawn once on the last iteration of the loop # 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 # 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) 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"), 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 # 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_left = [None] * self.num_r_ports
self.read_nmos_right = [None] * self.num_read self.read_nmos_right = [None] * self.num_r_ports
self.read_access_nmos_left = [None] * self.num_read self.read_access_nmos_left = [None] * self.num_r_ports
self.read_access_nmos_right = [None] * self.num_read self.read_access_nmos_right = [None] * self.num_r_ports
# iterate over the number of read 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 # add read-access transistors
self.read_access_nmos_left[k] = self.add_inst(name="read_access_nmos_left{}".format(k), self.read_access_nmos_left[k] = self.add_inst(name="read_access_nmos_left{}".format(k),
mod=self.read_nmos) mod=self.read_nmos)
@ -802,9 +802,9 @@ class pbitcell(pgate.pgate):
""" """
# Define variables relevant to read transistors # Define variables relevant to read transistors
self.rwl_positions = [None] * self.num_read self.rwl_positions = [None] * self.num_r_ports
self.rbl_positions = [None] * self.num_read self.rbl_positions = [None] * self.num_r_ports
self.rbl_bar_positions = [None] * self.num_read self.rbl_bar_positions = [None] * self.num_r_ports
# define offset correction due to rotation of the ptx module # define offset correction due to rotation of the ptx module
read_rotation_correct = self.read_nmos.active_height 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() overlap_offset = self.read_nmos.get_pin("D").ll() - self.read_nmos.get_pin("S").ll()
# iterate over the number of read 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 transistors # Add transistors
# calculate transistor offsets # calculate transistor offsets
left_read_transistor_xpos = self.left_building_edge \ left_read_transistor_xpos = self.left_building_edge \
@ -843,8 +843,8 @@ class pbitcell(pgate.pgate):
# Add RWL lines # Add RWL lines
# calculate RWL position # calculate RWL position
rwl_ypos = self.gnd_position.y \ rwl_ypos = self.gnd_position.y \
- self.num_readwrite*self.rowline_tile_height \ - self.num_rw_ports*self.rowline_tile_height \
- self.num_write*self.rowline_tile_height \ - self.num_w_ports*self.rowline_tile_height \
- (k+1)*self.rowline_tile_height - (k+1)*self.rowline_tile_height
self.rwl_positions[k] = vector(self.leftmost_xpos, rwl_ypos) 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 # extend pwell over read/write and write transistors to the
# height of the write transistor well (read/write and write # height of the write transistor well (read/write and write
# transistors are the same height) # 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 # 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"] 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"] 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) height=write_well_height)
# extend pwell over the read transistors to the height of the bitcell # 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 # 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"] 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"] 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): 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 """ """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """
bitcell_pins = [] 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{0}[{1}]".format(k,col))
bitcell_pins.append("rwbl_bar{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{0}[{1}]".format(k,col))
bitcell_pins.append("wbl_bar{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{0}[{1}]".format(k,col))
bitcell_pins.append("rbl_bar{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)) 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)) 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("rwl{0}[{1}]".format(k,row))
bitcell_pins.append("vdd") bitcell_pins.append("vdd")
bitcell_pins.append("gnd") bitcell_pins.append("gnd")
@ -1111,11 +1111,11 @@ class pbitcell(pgate.pgate):
def list_all_wl_names(self): def list_all_wl_names(self):
""" Creates a list of all wordline pin names """ """ Creates a list of all wordline pin names """
row_pins = [] row_pins = []
for k in range(self.num_readwrite): for k in range(self.num_rw_ports):
row_pins.append("rwwl{0}".format(k)) 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)) 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)) row_pins.append("rwl{0}".format(k))
return row_pins return row_pins
@ -1123,9 +1123,9 @@ class pbitcell(pgate.pgate):
def list_read_wl_names(self): def list_read_wl_names(self):
""" Creates a list of wordline pin names associated with read ports """ """ Creates a list of wordline pin names associated with read ports """
row_pins = [] row_pins = []
for k in range(self.num_readwrite): for k in range(self.num_rw_ports):
row_pins.append("rwwl{0}".format(k)) 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)) row_pins.append("rwl{0}".format(k))
return row_pins return row_pins
@ -1133,9 +1133,9 @@ class pbitcell(pgate.pgate):
def list_write_wl_names(self): def list_write_wl_names(self):
""" Creates a list of wordline pin names associated with write ports """ """ Creates a list of wordline pin names associated with write ports """
row_pins = [] row_pins = []
for k in range(self.num_readwrite): for k in range(self.num_rw_ports):
row_pins.append("rwwl{0}".format(k)) 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)) row_pins.append("wwl{0}".format(k))
return row_pins return row_pins
@ -1144,13 +1144,13 @@ class pbitcell(pgate.pgate):
def list_all_bitline_names(self): def list_all_bitline_names(self):
""" Creates a list of all bitline pin names (both bl and br) """ """ Creates a list of all bitline pin names (both bl and br) """
column_pins = [] 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{0}".format(k))
column_pins.append("rwbl_bar{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{0}".format(k))
column_pins.append("wbl_bar{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{0}".format(k))
column_pins.append("rbl_bar{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): def list_all_bl_names(self):
""" Creates a list of all bl pins names """ """ Creates a list of all bl pins names """
column_pins = [] 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{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{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{0}".format(k))
return column_pins return column_pins
@ -1171,11 +1171,11 @@ class pbitcell(pgate.pgate):
def list_all_br_names(self): def list_all_br_names(self):
""" Creates a list of all br pins names """ """ Creates a list of all br pins names """
column_pins = [] 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)) 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)) 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)) column_pins.append("rbl_bar{0}".format(k))
return column_pins return column_pins
@ -1183,9 +1183,9 @@ class pbitcell(pgate.pgate):
def list_read_bl_names(self): def list_read_bl_names(self):
""" Creates a list of bl pin names associated with read ports """ """ Creates a list of bl pin names associated with read ports """
column_pins = [] 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{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{0}".format(k))
return column_pins return column_pins
@ -1193,9 +1193,9 @@ class pbitcell(pgate.pgate):
def list_read_br_names(self): def list_read_br_names(self):
""" Creates a list of br pin names associated with read ports """ """ Creates a list of br pin names associated with read ports """
column_pins = [] 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)) 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)) column_pins.append("rbl_bar{0}".format(k))
return column_pins return column_pins
@ -1203,9 +1203,9 @@ class pbitcell(pgate.pgate):
def list_write_bl_names(self): def list_write_bl_names(self):
""" Creates a list of bl pin names associated with write ports """ """ Creates a list of bl pin names associated with write ports """
column_pins = [] 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{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{0}".format(k))
return column_pins return column_pins
@ -1213,9 +1213,9 @@ class pbitcell(pgate.pgate):
def list_write_br_names(self): def list_write_br_names(self):
""" Creates a list of br pin names asscociated with write ports""" """ Creates a list of br pin names asscociated with write ports"""
column_pins = [] 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)) 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)) column_pins.append("wbl_bar{0}".format(k))
return column_pins return column_pins

View File

@ -3,7 +3,7 @@ import datetime
import getpass import getpass
import debug import debug
from globals import OPTS, print_time from globals import OPTS, print_time
from sram_config import sram_config
class sram(): class sram():
""" """
@ -12,31 +12,31 @@ class sram():
results. results.
We can later add visualizer and other high-level functions as needed. 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 # reset the static duplicate name checker for unit tests
# in case we create more than one SRAM # in case we create more than one SRAM
from design import design from design import design
design.name_map=[] design.name_map=[]
debug.info(2, "create sram of size {0} with {1} num of words".format(word_size, debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size,
num_words)) self.num_words,
self.num_banks))
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
self.name = name self.name = name
if self.num_banks == 1:
if num_banks == 1: from sram_1bank import sram_1bank as sram
from sram_1bank import sram_1bank elif self.num_banks == 2:
self.s=sram_1bank(word_size, num_words, name) from sram_2bank import sram_2bank as sram
elif num_banks == 2: elif self.num_banks == 4:
from sram_2bank import sram_2bank from sram_4bank import sram_4bank as sram
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)
else: else:
debug.error("Invalid number of banks.",-1) debug.error("Invalid number of banks.",-1)
self.s = sram(sram_config, name)
self.s.create_netlist() self.s.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
self.s.create_layout() self.s.create_layout()

View File

@ -18,8 +18,9 @@ class sram_1bank(sram_base):
""" """
Procedures specific to a one bank SRAM. Procedures specific to a one bank SRAM.
""" """
def __init__(self, word_size, num_words, name): def __init__(self, sram_config, name):
sram_base.__init__(self, word_size, num_words, 1, name) sram_base.__init__(self, sram_config, name)
def create_netlist(self): def create_netlist(self):
self.compute_sizes() self.compute_sizes()
@ -99,18 +100,18 @@ class sram_1bank(sram_base):
for i in range(self.word_size): for i in range(self.word_size):
dout_name = "dout0[{}]".format(i) 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 # Lower address bits
for i in range(self.col_addr_size): 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 # Upper address bits
for i in range(self.row_addr_size): 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): for i in range(self.word_size):
din_name = "din[{}]".format(i) 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): def route(self):
""" Route a single bank SRAM """ """ Route a single bank SRAM """

View File

@ -16,8 +16,8 @@ class sram_2bank(sram_base):
""" """
Procedures specific to a two bank SRAM. Procedures specific to a two bank SRAM.
""" """
def __init__(self, word_size, num_words, name): def __init__(self, sram_config, name):
sram_base.__init__(self, word_size, num_words, 2, name) sram_base.__init__(self, sram_config, name)
def compute_bank_offsets(self): def compute_bank_offsets(self):
""" Compute the overall offsets for a two bank SRAM """ """ Compute the overall offsets for a two bank SRAM """

View File

@ -16,8 +16,8 @@ class sram_4bank(sram_base):
""" """
Procedures specific to a four bank SRAM. Procedures specific to a four bank SRAM.
""" """
def __init__(self, word_size, num_words, name): def __init__(self, sram_config, name):
sram_base.__init__(self, word_size, num_words, 4, name) sram_base.__init__(self, sram_config, name)
def compute_bank_offsets(self): def compute_bank_offsets(self):
""" Compute the overall offsets for a four bank SRAM """ """ Compute the overall offsets for a four bank SRAM """

View File

@ -2,6 +2,7 @@ import sys
import datetime import datetime
import getpass import getpass
import debug import debug
from importlib import reload
from math import log,sqrt,ceil from math import log,sqrt,ceil
from vector import vector from vector import vector
from globals import OPTS, print_time from globals import OPTS, print_time
@ -13,28 +14,17 @@ class sram_base(design):
Dynamically generated SRAM by connecting banks to control logic. The Dynamically generated SRAM by connecting banks to control logic. The
number of banks should be 1 , 2 or 4 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) 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)) c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell) self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell() self.bitcell = self.mod_bitcell()
c = reload(__import__(OPTS.ms_flop)) self.sram_config = sram_config
self.mod_ms_flop = getattr(c, OPTS.ms_flop) self.sram_config.set_local_config(self)
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.bank_insts = [] self.bank_insts = []
@ -45,18 +35,22 @@ class sram_base(design):
self.num_words_per_bank = self.num_words/self.num_banks self.num_words_per_bank = self.num_words/self.num_banks
self.num_bits_per_bank = self.word_size*self.num_words_per_bank 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) # Estimate the words per row given the height of the bitcell and the square side length
self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width)
self.bank_side_length = sqrt(self.bank_area) 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 # Estimate the number of rows given the tentative words per row
self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width) self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
self.words_per_row = self.estimate_words_per_row(self.tentative_num_cols, 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 # Fix the number of columns and rows
self.num_cols = int(self.words_per_row*self.word_size) 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.col_addr_size = int(log(self.words_per_row, 2))
self.bank_addr_size = self.col_addr_size + self.row_addr_size 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.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)) debug.info(1,"Words per row: {}".format(self.words_per_row))
def estimate_words_per_row(self,tentative_num_cols, word_size): def estimate_words_per_row(self,tentative_num_cols, word_size):
@ -279,7 +274,15 @@ class sram_base(design):
def add_modules(self): def add_modules(self):
""" Create all the modules that will be used """ """ 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 from control_logic import control_logic
# Create the control logic module # Create the control logic module
self.control_logic = self.mod_control_logic(num_rows=self.num_rows) 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) # Create the bank module (up to four are instantiated)
from bank import bank from bank import bank
self.bank = bank(word_size=self.word_size, self.bank = bank(self.sram_config,
num_words=self.num_words_per_bank,
words_per_row=self.words_per_row,
num_banks=self.num_banks,
name="bank") name="bank")
self.add_mod(self.bank) self.add_mod(self.bank)

36
compiler/sram_config.py Normal file
View File

@ -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

View File

@ -22,43 +22,43 @@ class pbitcell_test(openram_test):
import tech import tech
debug.info(2, "Bitcell with 1 of each port: read/write, write, and read") 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) self.local_check(tx)
debug.info(2, "Bitcell with 0 read/write ports") 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) self.local_check(tx)
debug.info(2, "Bitcell with 0 write ports") 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) self.local_check(tx)
debug.info(2, "Bitcell with 0 read ports") 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) self.local_check(tx)
debug.info(2, "Bitcell with 0 read ports and 0 write ports") 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) self.local_check(tx)
debug.info(2, "Bitcell with 2 of each port: read/write, write, and read") 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) self.local_check(tx)
debug.info(2, "Bitcell with 0 read/write ports") 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) self.local_check(tx)
debug.info(2, "Bitcell with 0 write ports") 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) self.local_check(tx)
debug.info(2, "Bitcell with 0 read ports") 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) self.local_check(tx)
debug.info(2, "Bitcell with 0 read ports and 0 write ports") 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) self.local_check(tx)
globals.end_openram() globals.end_openram()

View File

@ -24,9 +24,9 @@ class precharge_test(openram_test):
debug.info(2, "Checking precharge for pbitcell") debug.info(2, "Checking precharge for pbitcell")
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.rw_ports = 2 OPTS.num_rw_ports = 2
OPTS.r_ports = 2 OPTS.num_r_ports = 2
OPTS.w_ports = 2 OPTS.num_w_ports = 2
tx = precharge.precharge(name="precharge_driver", size=1, bitcell_bl="rwbl0", bitcell_br="rwbl_bar0") tx = precharge.precharge(name="precharge_driver", size=1, bitcell_bl="rwbl0", bitcell_br="rwbl_bar0")
self.local_check(tx) self.local_check(tx)

View File

@ -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") debug.info(2, "Testing 4x4 array for multiport bitcell, with read ports at the edge of the bit cell")
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.rw_ports = 2 OPTS.num_rw_ports = 2
OPTS.r_ports = 2 OPTS.num_r_ports = 2
OPTS.w_ports = 2 OPTS.num_w_ports = 2
a = bitcell_array.bitcell_array(name="pbitcell_array_Rport_edge", cols=4, rows=4) a = bitcell_array.bitcell_array(name="pbitcell_array_Rport_edge", cols=4, rows=4)
self.local_check(a) self.local_check(a)
debug.info(2, "Testing 4x4 array for multiport bitcell, with write ports at the edge of the bit cell") debug.info(2, "Testing 4x4 array for multiport bitcell, with write ports at the edge of the bit cell")
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.rw_ports = 2 OPTS.num_rw_ports = 2
OPTS.r_ports = 0 OPTS.num_r_ports = 0
OPTS.w_ports = 2 OPTS.num_w_ports = 2
a = bitcell_array.bitcell_array(name="pbitcell_array_Wport_edge", cols=4, rows=4) a = bitcell_array.bitcell_array(name="pbitcell_array_Wport_edge", cols=4, rows=4)
self.local_check(a) self.local_check(a)
debug.info(2, "Testing 4x4 array for multiport bitcell, with read/write ports at the edge of the bit cell") debug.info(2, "Testing 4x4 array for multiport bitcell, with read/write ports at the edge of the bit cell")
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.rw_ports = 2 OPTS.num_rw_ports = 2
OPTS.r_ports = 0 OPTS.num_r_ports = 0
OPTS.w_ports = 0 OPTS.num_w_ports = 0
a = bitcell_array.bitcell_array(name="pbitcell_array_RWport_edge", cols=4, rows=4) a = bitcell_array.bitcell_array(name="pbitcell_array_RWport_edge", cols=4, rows=4)
self.local_check(a) self.local_check(a)

View File

@ -24,9 +24,9 @@ class precharge_test(openram_test):
debug.info(2, "Checking precharge for pbitcell") debug.info(2, "Checking precharge for pbitcell")
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.rw_ports = 2 OPTS.num_rw_ports = 2
OPTS.r_ports = 2 OPTS.num_r_ports = 2
OPTS.w_ports = 2 OPTS.num_w_ports = 2
pc = precharge_array.precharge_array(columns=3, bitcell_bl="rwbl0", bitcell_br="rwbl_bar0") pc = precharge_array.precharge_array(columns=3, bitcell_bl="rwbl0", bitcell_br="rwbl_bar0")
self.local_check(pc) self.local_check(pc)

View File

@ -27,9 +27,9 @@ class wordline_driver_test(openram_test):
# check wordline driver array in multi-port # check wordline driver array in multi-port
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.w_ports = 0 OPTS.num_w_ports = 0
OPTS.r_ports = 0 OPTS.num_r_ports = 0
debug.info(2, "Checking driver (multi-port case)") debug.info(2, "Checking driver (multi-port case)")
tx = wordline_driver.wordline_driver(rows=8) tx = wordline_driver.wordline_driver(rows=8)

View File

@ -28,9 +28,9 @@ class sense_amp_test(openram_test):
# check sense amp array in multi-port # check sense amp array in multi-port
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.w_ports = 0 OPTS.num_w_ports = 0
OPTS.r_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)") 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) a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=2)

View File

@ -28,9 +28,9 @@ class write_driver_test(openram_test):
# check write driver array in multi-port # check write driver array in multi-port
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.w_ports = 0 OPTS.num_w_ports = 0
OPTS.r_ports = 0 OPTS.num_r_ports = 0
debug.info(2, "Testing write_driver_array for columns=8, word_size=8 (multi-port case)") 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) a = write_driver_array.write_driver_array(columns=8, word_size=8)

View File

@ -16,21 +16,34 @@ class multi_bank_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
from bank import bank 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") 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) self.local_check(a)
c.num_words=32
c.words_per_row=2
debug.info(1, "Two way column mux") 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) self.local_check(a)
c.num_words=64
c.words_per_row=4
debug.info(1, "Four way column mux") 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) self.local_check(a)
c.word_size=2
c.num_words=128
c.words_per_row=8
debug.info(1, "Eight way column mux") 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) self.local_check(a)
globals.end_openram() globals.end_openram()

View File

@ -20,80 +20,103 @@ class psingle_bank_test(openram_test):
import verify import verify
from bank import bank from bank import bank
from sram_config import sram_config
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
# testing layout of bank using pbitcell with 1 RW port (a 6T-cell equivalent) # testing layout of bank using pbitcell with 1 RW port (a 6T-cell equivalent)
OPTS.rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.w_ports = 0 OPTS.num_w_ports = 0
OPTS.r_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") 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) 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 # multiport can't generate layout yet on the bank level
OPTS.netlist_only = True OPTS.netlist_only = True
debug.info(1, "No column mux") OPTS.num_rw_ports = 1
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_2rw_2w_2r_single") OPTS.num_w_ports = 1
self.local_check(a) OPTS.num_r_ports = 1
"""
"""
OPTS.rw_ports = 0
OPTS.w_ports = 2
OPTS.r_ports = 2
debug.info(1, "No column mux") 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) self.local_check(a)
OPTS.rw_ports = 2 OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.w_ports = 0 OPTS.num_w_ports = c.num_w_ports = 2
OPTS.r_ports = 2 OPTS.num_r_ports = c.num_r_ports = 2
debug.info(1, "No column mux") 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) self.local_check(a)
OPTS.rw_ports = 2 OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.w_ports = 2 OPTS.num_w_ports = c.num_w_ports = 0
OPTS.r_ports = 0 OPTS.num_r_ports = c.num_r_ports = 2
debug.info(1, "No column mux") 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) self.local_check(a)
OPTS.rw_ports = 2 OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.w_ports = 0 OPTS.num_w_ports = c.num_w_ports = 2
OPTS.r_ports = 0 OPTS.num_r_ports = c.num_r_ports = 0
debug.info(1, "No column mux") 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) self.local_check(a)
# testing with various column muxes # testing with various column muxes
OPTS.rw_ports = 2 OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.w_ports = 2 OPTS.num_w_ports = c.num_w_ports = 2
OPTS.r_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") 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) self.local_check(a)
c.num_words=64
c.words_per_row=4
debug.info(1, "Four way column mux") 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) self.local_check(a)
# Eight way has a short circuit of one column mux select to gnd rail # 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") 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) self.local_check(a)
""" """

View File

@ -16,22 +16,34 @@ class single_bank_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
from bank import bank 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") debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_single") a = bank(c, 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")
self.local_check(a) 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") 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) self.local_check(a)
# Eight way has a short circuit of one column mux select to gnd rail # 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") 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) self.local_check(a)
globals.end_openram() globals.end_openram()

View File

@ -16,22 +16,33 @@ class sram_1bank_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
from sram import sram 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") 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) self.local_check(a, final_verification=True)
# debug.info(1, "Single bank two way column mux with control logic") c.num_words=32
# a = sram(word_size=4, num_words=32, num_banks=1, name="sram2") c.words_per_row=2
# self.local_check(a, final_verification=True) 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") c.num_words=64
# a = sram(word_size=4, num_words=64, num_banks=1, name="sram3") c.words_per_row=4
# self.local_check(a, final_verification=True) 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") c.word_size=2
# a = sram(word_size=2, num_words=128, num_banks=1, name="sram4") c.num_words=128
# self.local_check(a, final_verification=True) 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() globals.end_openram()

View File

@ -17,21 +17,32 @@ class sram_2bank_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
from sram import sram 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") 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) 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") 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) 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") 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) 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") 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) self.local_check(a, final_verification=True)
globals.end_openram() globals.end_openram()

View File

@ -17,19 +17,30 @@ class sram_4bank_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
from sram import sram 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") 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) 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") 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) 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") 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") a = sram(word_size=16, num_words=256, num_banks=4, name="sram3")
self.local_check(a, final_verification=True) 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") 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") a = sram.sram(word_size=2, num_words=256, num_banks=4, name="sram4")
self.local_check(a, final_verification=True) self.local_check(a, final_verification=True)

View File

@ -27,14 +27,14 @@ class timing_sram_test(openram_test):
if not OPTS.spice_exe: if not OPTS.spice_exe:
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1) debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
import sram from sram import sram
import tech from sram_config import sram_config
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") c = sram_config(word_size=1,
s = sram.sram(word_size=OPTS.word_size, num_words=16,
num_words=OPTS.num_words, num_banks=1)
num_banks=OPTS.num_banks,
name="sram1")
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram(c, name="sram1")
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)

View File

@ -27,13 +27,14 @@ class timing_sram_test(openram_test):
if not OPTS.spice_exe: if not OPTS.spice_exe:
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1) debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
import sram from sram import sram
import tech 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") debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram.sram(word_size=OPTS.word_size, s = sram(c, name="sram1")
num_words=OPTS.num_words,
num_banks=OPTS.num_banks,
name="sram1")
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)

View File

@ -16,15 +16,16 @@ class lib_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
import sram
from characterizer import lib 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" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)

View File

@ -26,13 +26,14 @@ class lib_test(openram_test):
if not OPTS.spice_exe: if not OPTS.spice_exe:
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1) 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") debug.info(1, "Testing pruned timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
num_words=16,
num_banks=1,
name="sram_2_16_1_{0}".format(OPTS.tech_name))
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)

View File

@ -26,13 +26,14 @@ class lib_test(openram_test):
if not OPTS.spice_exe: if not OPTS.spice_exe:
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1) 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") debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
num_words=16,
num_banks=1,
name="sram_2_16_1_{0}".format(OPTS.tech_name))
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)

View File

@ -17,13 +17,14 @@ class lef_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) 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") debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
num_words=OPTS.num_words,
num_banks=OPTS.num_banks,
name="sram_2_16_1_{0}".format(OPTS.tech_name))
gdsfile = s.name + ".gds" gdsfile = s.name + ".gds"
leffile = s.name + ".lef" leffile = s.name + ".lef"

View File

@ -16,13 +16,14 @@ class verilog_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) 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") debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
num_words=OPTS.num_words,
num_banks=OPTS.num_banks,
name="sram_2_16_1_{0}".format(OPTS.tech_name))
vfile = s.name + ".v" vfile = s.name + ".v"
vname = OPTS.openram_temp + vfile vname = OPTS.openram_temp + vfile