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

View File

@ -20,22 +20,16 @@ class bank(design.design):
write driver and sense amplifiers.
"""
def __init__(self, word_size, num_words, words_per_row, num_banks=1, name=""):
def __init__(self, sram_config, name=""):
if name == "":
name = "bank_{0}_{1}".format(word_size, num_words)
design.design.__init__(self, name)
debug.info(2, "create sram of size {0} with {1} words".format(word_size,num_words))
self.word_size = word_size
self.num_words = num_words
self.words_per_row = words_per_row
self.num_banks = num_banks
sram_config.set_local_config(self)
self.total_write = OPTS.rw_ports + OPTS.w_ports
self.total_read = OPTS.rw_ports + OPTS.r_ports
self.total_ports = OPTS.rw_ports + OPTS.w_ports + OPTS.r_ports
if name == "":
name = "bank_{0}_{1}".format(self.word_size, self.num_words)
design.design.__init__(self, name)
debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words))
# The local control signals are gated when we have bank select logic,
# so this prefix will be added to all of the input signals to create
# the internal gated signals.
@ -70,25 +64,25 @@ class bank(design.design):
def add_pins(self):
""" Adding pins for Bank module"""
for k in range(self.total_read):
for i in range(self.word_size):
self.add_pin("dout{0}[{1}]".format(k,i),"OUT")
for k in range(self.total_write):
for i in range(self.word_size):
self.add_pin("din{0}[{1}]".format(k,i),"IN")
for k in range(self.total_ports):
for i in range(self.addr_size):
self.add_pin("addr{0}[{1}]".format(k,i),"INPUT")
for port in range(self.total_read):
for bit in range(self.word_size):
self.add_pin("dout{0}[{1}]".format(port,bit),"OUT")
for port in range(self.total_write):
for bit in range(self.word_size):
self.add_pin("din{0}[{1}]".format(port,bit),"IN")
for port in range(self.total_ports):
for bit in range(self.addr_size):
self.add_pin("addr{0}[{1}]".format(port,bit),"INPUT")
# For more than one bank, we have a bank select and name
# the signals gated_*.
if self.num_banks > 1:
for port in range(self.total_ports):
self.add_pin("bank_sel{}".format(port),"INPUT")
for k in range(self.total_read):
self.add_pin("s_en{0}".format(k), "INPUT")
for k in range(self.total_write):
self.add_pin("w_en{0}".format(k), "INPUT")
for port in range(self.total_read):
self.add_pin("s_en{0}".format(port), "INPUT")
for port in range(self.total_write):
self.add_pin("w_en{0}".format(port), "INPUT")
for pin in ["clk_buf_bar","clk_buf"]:
self.add_pin(pin,"INPUT")
self.add_pin("vdd","POWER")
@ -229,9 +223,9 @@ class bank(design.design):
self.total_bitline_list = self.bitcell.list_all_bitline_names()
self.precharge_array = []
for k in range(self.total_read):
self.precharge_array.append(self.mod_precharge_array(columns=self.num_cols, bitcell_bl=self.read_bl_list[k], bitcell_br=self.read_br_list[k]))
self.add_mod(self.precharge_array[k])
for port in range(self.total_read):
self.precharge_array.append(self.mod_precharge_array(columns=self.num_cols, bitcell_bl=self.read_bl_list[port], bitcell_br=self.read_br_list[port]))
self.add_mod(self.precharge_array[port])
if self.col_addr_size > 0:
self.column_mux_array = self.mod_column_mux_array(columns=self.num_cols,
@ -288,13 +282,13 @@ class bank(design.design):
""" Creating Precharge """
self.precharge_array_inst = []
for k in range(self.total_read):
self.precharge_array_inst.append(self.add_inst(name="precharge_array{}".format(k),
mod=self.precharge_array[k]))
for port in range(self.total_read):
self.precharge_array_inst.append(self.add_inst(name="precharge_array{}".format(port),
mod=self.precharge_array[port]))
temp = []
for i in range(self.num_cols):
temp.append(self.read_bl_list[k]+"[{0}]".format(i))
temp.append(self.read_br_list[k]+"[{0}]".format(i))
temp.append(self.read_bl_list[port]+"[{0}]".format(i))
temp.append(self.read_br_list[port]+"[{0}]".format(i))
temp.extend([self.prefix+"clk_buf_bar", "vdd"])
self.connect_inst(temp)
@ -302,11 +296,11 @@ class bank(design.design):
""" Placing Precharge """
# FIXME: place for multiport
for k in range(self.total_read):
for port in range(self.total_read):
# The wells must be far enough apart
# The enclosure is for the well and the spacing is to the bitcell wells
y_offset = self.bitcell_array.height + self.m2_gap
self.precharge_array_inst[k].place(vector(0,y_offset))
self.precharge_array_inst[port].place(vector(0,y_offset))
def create_column_mux_array(self):
""" Creating Column Mux when words_per_row > 1 . """
@ -314,19 +308,19 @@ class bank(design.design):
return
self.col_mux_array_inst = []
for k in range(self.total_ports):
self.col_mux_array_inst.append(self.add_inst(name="column_mux_array{}".format(k),
for port in range(self.total_ports):
self.col_mux_array_inst.append(self.add_inst(name="column_mux_array{}".format(port),
mod=self.column_mux_array))
temp = []
for i in range(self.num_cols):
temp.append(self.total_bl_list[k]+"[{0}]".format(i))
temp.append(self.total_br_list[k]+"[{0}]".format(i))
for h in range(self.words_per_row):
temp.append("sel{0}[{1}]".format(k,h))
for j in range(self.word_size):
temp.append(self.total_bl_list[k]+"_out[{0}]".format(j))
temp.append(self.total_br_list[k]+"_out[{0}]".format(j))
for col in range(self.num_cols):
temp.append(self.total_bl_list[port]+"[{0}]".format(col))
temp.append(self.total_br_list[port]+"[{0}]".format(col))
for word in range(self.words_per_row):
temp.append("sel{0}[{1}]".format(port,word))
for bit in range(self.word_size):
temp.append(self.total_bl_list[port]+"_out[{0}]".format(bit))
temp.append(self.total_br_list[port]+"_out[{0}]".format(bit))
temp.append("gnd")
self.connect_inst(temp)
@ -338,68 +332,68 @@ class bank(design.design):
self.column_mux_height = 0
return
for k in range(self.total_ports):
for port in range(self.total_ports):
y_offset = self.column_mux_height
self.col_mux_array_inst[k].place(vector(0,y_offset).scale(-1,-1))
self.col_mux_array_inst[port].place(vector(0,y_offset).scale(-1,-1))
def create_sense_amp_array(self):
""" Creating Sense amp """
self.sense_amp_array_inst = []
for k in range(self.total_read):
self.sense_amp_array_inst.append(self.add_inst(name="sense_amp_array{}".format(k),
for port in range(self.total_read):
self.sense_amp_array_inst.append(self.add_inst(name="sense_amp_array{}".format(port),
mod=self.sense_amp_array))
temp = []
for i in range(self.word_size):
temp.append("dout{0}[{1}]".format(k,i))
for bit in range(self.word_size):
temp.append("dout{0}[{1}]".format(port,bit))
if self.words_per_row == 1:
temp.append(self.read_bl_list[k]+"[{0}]".format(i))
temp.append(self.read_br_list[k]+"[{0}]".format(i))
temp.append(self.read_bl_list[port]+"[{0}]".format(bit))
temp.append(self.read_br_list[port]+"[{0}]".format(bit))
else:
temp.append(self.read_bl_list[k]+"_out[{0}]".format(i))
temp.append(self.read_br_list[k]+"_out[{0}]".format(i))
temp.append(self.read_bl_list[port]+"_out[{0}]".format(bit))
temp.append(self.read_br_list[port]+"_out[{0}]".format(bit))
temp.extend([self.prefix+"s_en{0}".format(k), "vdd", "gnd"])
temp.extend([self.prefix+"s_en{0}".format(port), "vdd", "gnd"])
self.connect_inst(temp)
def place_sense_amp_array(self):
""" Placing Sense amp """
# FIXME: place for multiport
for k in range(self.total_read):
for port in range(self.total_read):
y_offset = self.column_mux_height + self.sense_amp_array.height + self.m2_gap
self.sense_amp_array_inst[k].place(vector(0,y_offset).scale(-1,-1))
self.sense_amp_array_inst[port].place(vector(0,y_offset).scale(-1,-1))
def create_write_driver_array(self):
""" Creating Write Driver """
self.write_driver_array_inst = []
for k in range(self.total_write):
self.write_driver_array_inst.append(self.add_inst(name="write_driver_array{}".format(k),
for port in range(self.total_write):
self.write_driver_array_inst.append(self.add_inst(name="write_driver_array{}".format(port),
mod=self.write_driver_array))
temp = []
for i in range(self.word_size):
temp.append("din{0}[{1}]".format(k,i))
for i in range(self.word_size):
for bit in range(self.word_size):
temp.append("din{0}[{1}]".format(port,bit))
for bit in range(self.word_size):
if (self.words_per_row == 1):
temp.append(self.write_bl_list[k]+"[{0}]".format(i))
temp.append(self.write_br_list[k]+"[{0}]".format(i))
temp.append(self.write_bl_list[port]+"[{0}]".format(bit))
temp.append(self.write_br_list[port]+"[{0}]".format(bit))
else:
temp.append(self.write_bl_list[k]+"_out[{0}]".format(i))
temp.append(self.write_br_list[k]+"_out[{0}]".format(i))
temp.extend([self.prefix+"w_en{0}".format(k), "vdd", "gnd"])
temp.append(self.write_bl_list[port]+"_out[{0}]".format(bit))
temp.append(self.write_br_list[port]+"_out[{0}]".format(bit))
temp.extend([self.prefix+"w_en{0}".format(port), "vdd", "gnd"])
self.connect_inst(temp)
def place_write_driver_array(self):
""" Placing Write Driver """
# FIXME: place for multiport
for k in range(self.total_write):
for port in range(self.total_write):
y_offset = self.sense_amp_array.height + self.column_mux_height \
+ self.m2_gap + self.write_driver_array.height
self.write_driver_array_inst[k].place(vector(0,y_offset).scale(-1,-1))
self.write_driver_array_inst[port].place(vector(0,y_offset).scale(-1,-1))
@ -407,15 +401,15 @@ class bank(design.design):
""" Create the hierarchical row decoder """
self.row_decoder_inst = []
for k in range(self.total_ports):
self.row_decoder_inst.append(self.add_inst(name="row_decoder{}".format(k),
for port in range(self.total_ports):
self.row_decoder_inst.append(self.add_inst(name="row_decoder{}".format(port),
mod=self.row_decoder))
temp = []
for i in range(self.row_addr_size):
temp.append("addr{0}[{1}]".format(k,i+self.col_addr_size))
for j in range(self.num_rows):
temp.append("dec_out{0}[{1}]".format(k,j))
for bit in range(self.row_addr_size):
temp.append("addr{0}[{1}]".format(port,bit+self.col_addr_size))
for row in range(self.num_rows):
temp.append("dec_out{0}[{1}]".format(port,row))
temp.extend(["vdd", "gnd"])
self.connect_inst(temp)
@ -429,24 +423,24 @@ class bank(design.design):
# The address flop and decoder are aligned in the x coord.
# FIXME: place for multiport
for k in range(self.total_ports):
for port in range(self.total_ports):
x_offset = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
self.row_decoder_inst[k].place(vector(x_offset,0))
self.row_decoder_inst[port].place(vector(x_offset,0))
def create_wordline_driver(self):
""" Create the Wordline Driver """
self.wordline_driver_inst = []
for k in range(self.total_ports):
self.wordline_driver_inst.append(self.add_inst(name="wordline_driver{}".format(k),
for port in range(self.total_ports):
self.wordline_driver_inst.append(self.add_inst(name="wordline_driver{}".format(port),
mod=self.wordline_driver))
temp = []
for i in range(self.num_rows):
temp.append("dec_out{0}[{1}]".format(k,i))
for i in range(self.num_rows):
temp.append(self.total_wl_list[k]+"[{0}]".format(i))
for row in range(self.num_rows):
temp.append("dec_out{0}[{1}]".format(port,row))
for row in range(self.num_rows):
temp.append(self.total_wl_list[port]+"[{0}]".format(row))
temp.append(self.prefix+"clk_buf")
temp.append("vdd")
temp.append("gnd")
@ -456,10 +450,10 @@ class bank(design.design):
""" Place the Wordline Driver """
# FIXME: place for multiport
for k in range(self.total_ports):
for port in range(self.total_ports):
# The wordline driver is placed to the right of the main decoder width.
x_offset = -(self.central_bus_width + self.wordline_driver.width) + self.m2_pitch
self.wordline_driver_inst[k].place(vector(x_offset,0))
self.wordline_driver_inst[port].place(vector(x_offset,0))
def create_column_decoder(self):
@ -481,15 +475,15 @@ class bank(design.design):
debug.error("Invalid column decoder?",-1)
self.col_decoder_inst = []
for k in range(self.total_ports):
self.col_decoder_inst.append(self.add_inst(name="col_address_decoder{}".format(k),
for port in range(self.total_ports):
self.col_decoder_inst.append(self.add_inst(name="col_address_decoder{}".format(port),
mod=self.col_decoder))
temp = []
for i in range(self.col_addr_size):
temp.append("addr{0}[{1}]".format(k,i))
for j in range(self.num_col_addr_lines):
temp.append("sel{0}[{1}]".format(k,j))
for bit in range(self.col_addr_size):
temp.append("addr{0}[{1}]".format(port,bit))
for bit in range(self.num_col_addr_lines):
temp.append("sel{0}[{1}]".format(port,bit))
temp.extend(["vdd", "gnd"])
self.connect_inst(temp)
@ -501,11 +495,11 @@ class bank(design.design):
return
# FIXME: place for multiport
for k in range(self.total_ports):
for port in range(self.total_ports):
# Place the col decoder right aligned with row decoder
x_off = -(self.central_bus_width + self.wordline_driver.width + self.col_decoder.width)
y_off = -(self.col_decoder.height + 2*drc["well_to_well"])
self.col_decoder_inst[k].place(vector(x_off,y_off))
self.col_decoder_inst[port].place(vector(x_off,y_off))
def create_bank_select(self):
@ -533,7 +527,7 @@ class bank(design.design):
return
# FIXME: place for multiport
for k in range(self.total_ports):
for port in range(self.total_ports):
x_off = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
if self.col_addr_size > 0:
y_off = min(self.col_decoder_inst[0].by(), self.col_mux_array_inst[0].by())
@ -541,7 +535,7 @@ class bank(design.design):
y_off = self.row_decoder_inst[0].by()
y_off -= (self.bank_select.height + drc["well_to_well"])
self.bank_select_pos = vector(x_off,y_off)
self.bank_select_inst[k].place(self.bank_select_pos)
self.bank_select_inst[port].place(self.bank_select_pos)
def route_vdd_gnd(self):
@ -550,19 +544,19 @@ class bank(design.design):
# These are the instances that every bank has
top_instances = [self.bitcell_array_inst]
for k in range(self.total_ports):
top_instances.extend([self.precharge_array_inst[k],
self.sense_amp_array_inst[k],
self.write_driver_array_inst[k],
self.row_decoder_inst[k],
self.wordline_driver_inst[k]])
for port in range(self.total_ports):
top_instances.extend([self.precharge_array_inst[port],
self.sense_amp_array_inst[port],
self.write_driver_array_inst[port],
self.row_decoder_inst[port],
self.wordline_driver_inst[port]])
# Add these if we use the part...
if self.col_addr_size > 0:
top_instances.append(self.col_decoder_inst[k])
top_instances.append(self.col_mux_array_inst[k])
top_instances.append(self.col_decoder_inst[port])
top_instances.append(self.col_mux_array_inst[port])
if self.num_banks > 1:
top_instances.append(self.bank_select_inst[k])
top_instances.append(self.bank_select_inst[port])
for inst in top_instances:
@ -576,13 +570,13 @@ class bank(design.design):
def route_bank_select(self):
""" Route the bank select logic. """
for k in range(self.total_ports):
for port in range(self.total_ports):
for input_name in self.input_control_signals+["bank_sel"]:
self.copy_layout_pin(self.bank_select_inst[k], input_name)
self.copy_layout_pin(self.bank_select_inst[port], input_name)
for gated_name in self.control_signals:
# Connect the inverter output to the central bus
out_pos = self.bank_select_inst[k].get_pin(gated_name).rc()
out_pos = self.bank_select_inst[port].get_pin(gated_name).rc()
bus_pos = vector(self.bus_xoffset[gated_name].x, out_pos.y)
self.add_path("metal3",[out_pos, bus_pos])
self.add_via_center(layers=("metal2", "via2", "metal3"),
@ -660,12 +654,12 @@ class bank(design.design):
""" Routing of BL and BR between pre-charge and bitcell array """
# FIXME: Update for multiport
for k in range(self.total_read):
for i in range(self.num_cols):
precharge_bl = self.precharge_array_inst[k].get_pin("bl[{}]".format(i)).bc()
precharge_br = self.precharge_array_inst[k].get_pin("br[{}]".format(i)).bc()
bitcell_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[k]+"[{}]".format(i)).uc()
bitcell_br = self.bitcell_array_inst.get_pin(self.read_br_list[k]+"[{}]".format(i)).uc()
for port in range(self.total_read):
for col in range(self.num_cols):
precharge_bl = self.precharge_array_inst[port].get_pin("bl[{}]".format(col)).bc()
precharge_br = self.precharge_array_inst[port].get_pin("br[{}]".format(col)).bc()
bitcell_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[port]+"[{}]".format(col)).uc()
bitcell_br = self.bitcell_array_inst.get_pin(self.read_br_list[port]+"[{}]".format(col)).uc()
yoffset = 0.5*(precharge_bl.y+bitcell_bl.y)
self.add_path("metal2",[precharge_bl, vector(precharge_bl.x,yoffset),
@ -682,12 +676,12 @@ class bank(design.design):
return
# FIXME: Update for multiport
for k in range(self.total_ports):
for i in range(self.num_cols):
col_mux_bl = self.col_mux_array_inst[k].get_pin("bl[{}]".format(i)).uc()
col_mux_br = self.col_mux_array_inst[k].get_pin("br[{}]".format(i)).uc()
bitcell_bl = self.bitcell_array_inst.get_pin(self.total_bl_list[k]+"[{}]".format(i)).bc()
bitcell_br = self.bitcell_array_inst.get_pin(self.total_br_list[k]+"[{}]".format(i)).bc()
for port in range(self.total_ports):
for col in range(self.num_cols):
col_mux_bl = self.col_mux_array_inst[port].get_pin("bl[{}]".format(col)).uc()
col_mux_br = self.col_mux_array_inst[port].get_pin("br[{}]".format(col)).uc()
bitcell_bl = self.bitcell_array_inst.get_pin(self.total_bl_list[port]+"[{}]".format(col)).bc()
bitcell_br = self.bitcell_array_inst.get_pin(self.total_br_list[port]+"[{}]".format(col)).bc()
yoffset = 0.5*(col_mux_bl.y+bitcell_bl.y)
self.add_path("metal2",[col_mux_bl, vector(col_mux_bl.x,yoffset),
@ -698,19 +692,19 @@ class bank(design.design):
def route_sense_amp_to_col_mux_or_bitcell_array(self):
""" Routing of BL and BR between sense_amp and column mux or bitcell array """
for k in range(self.total_read):
for i in range(self.word_size):
sense_amp_bl = self.sense_amp_array_inst[k].get_pin("bl[{}]".format(i)).uc()
sense_amp_br = self.sense_amp_array_inst[k].get_pin("br[{}]".format(i)).uc()
for port in range(self.total_read):
for bit in range(self.word_size):
sense_amp_bl = self.sense_amp_array_inst[port].get_pin("bl[{}]".format(bit)).uc()
sense_amp_br = self.sense_amp_array_inst[port].get_pin("br[{}]".format(bit)).uc()
if self.col_addr_size>0:
# Sense amp is connected to the col mux
connect_bl = self.col_mux_array_inst[k].get_pin("bl_out[{}]".format(i)).bc()
connect_br = self.col_mux_array_inst[k].get_pin("br_out[{}]".format(i)).bc()
connect_bl = self.col_mux_array_inst[port].get_pin("bl_out[{}]".format(bit)).bc()
connect_br = self.col_mux_array_inst[port].get_pin("br_out[{}]".format(bit)).bc()
else:
# Sense amp is directly connected to the bitcell array
connect_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[k]+"[{}]".format(i)).bc()
connect_br = self.bitcell_array_inst.get_pin(self.read_br_list[k]+"[{}]".format(i)).bc()
connect_bl = self.bitcell_array_inst.get_pin(self.read_bl_list[port]+"[{}]".format(bit)).bc()
connect_br = self.bitcell_array_inst.get_pin(self.read_br_list[port]+"[{}]".format(bit)).bc()
yoffset = 0.5*(sense_amp_bl.y+connect_bl.y)
@ -722,9 +716,11 @@ class bank(design.design):
def route_sense_amp_out(self):
""" Add pins for the sense amp output """
for i in range(self.word_size):
data_pin = self.sense_amp_array_inst[0].get_pin("data[{}]".format(i))
self.add_layout_pin_rect_center(text="dout0[{}]".format(i),
# FIXME: Update for multiport
for bit in range(self.word_size):
data_pin = self.sense_amp_array_inst[0].get_pin("data[{}]".format(bit))
self.add_layout_pin_rect_center(text="dout0[{}]".format(bit),
layer=data_pin.layer,
offset=data_pin.center(),
height=data_pin.height(),
@ -734,10 +730,11 @@ class bank(design.design):
def route_row_decoder(self):
""" Routes the row decoder inputs and supplies """
# FIXME: Update for multiport
# Create inputs for the row address lines
for i in range(self.row_addr_size):
addr_idx = i + self.col_addr_size
decoder_name = "addr[{}]".format(i)
for row in range(self.row_addr_size):
addr_idx = row + self.col_addr_size
decoder_name = "addr[{}]".format(row)
addr_name = "addr0[{}]".format(addr_idx)
self.copy_layout_pin(self.row_decoder_inst[0], decoder_name, addr_name)
@ -745,9 +742,9 @@ class bank(design.design):
def route_write_driver(self):
""" Connecting write driver """
for i in range(self.word_size):
data_name = "data[{}]".format(i)
din_name = "din0[{}]".format(i)
for row in range(self.word_size):
data_name = "data[{}]".format(row)
din_name = "din0[{}]".format(row)
self.copy_layout_pin(self.write_driver_array_inst[0], data_name, din_name)
@ -755,17 +752,17 @@ class bank(design.design):
def route_wordline_driver(self):
""" Connecting Wordline driver output to Bitcell WL connection """
for i in range(self.num_rows):
for row in range(self.num_rows):
# The pre/post is to access the pin from "outside" the cell to avoid DRCs
decoder_out_pos = self.row_decoder_inst[0].get_pin("decode[{}]".format(i)).rc()
driver_in_pos = self.wordline_driver_inst[0].get_pin("in[{}]".format(i)).lc()
decoder_out_pos = self.row_decoder_inst[0].get_pin("decode[{}]".format(row)).rc()
driver_in_pos = self.wordline_driver_inst[0].get_pin("in[{}]".format(row)).lc()
mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0)
mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1)
self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos])
# The mid guarantees we exit the input cell to the right.
driver_wl_pos = self.wordline_driver_inst[0].get_pin("wl[{}]".format(i)).rc()
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.total_wl_list[0]+"[{}]".format(i)).lc()
driver_wl_pos = self.wordline_driver_inst[0].get_pin("wl[{}]".format(row)).rc()
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.total_wl_list[0]+"[{}]".format(row)).lc()
mid1 = driver_wl_pos.scale(0.5,1)+bitcell_wl_pos.scale(0.5,0)
mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1)
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])

View File

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

View File

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

View File

@ -16,18 +16,18 @@ class pbitcell(pgate.pgate):
width = None
height = None
unique_id = 1
def __init__(self, num_readwrite=OPTS.rw_ports, num_write=OPTS.w_ports, num_read=OPTS.r_ports):
name = "pbitcell_{0}RW_{1}W_{2}R_{3}".format(num_readwrite, num_write, num_read, pbitcell.unique_id)
pbitcell.unique_id += 1
pgate.pgate.__init__(self, name)
debug.info(2, "create a multi-port bitcell with {0} write ports and {1} read ports".format(num_write, num_read))
def __init__(self, num_rw_ports=OPTS.num_rw_ports, num_w_ports=OPTS.num_w_ports, num_r_ports=OPTS.num_r_ports):
self.num_readwrite = num_readwrite
self.num_write = num_write
self.num_read = num_read
name = "pbitcell_{0}RW_{1}W_{2}R".format(num_rw_ports, num_w_ports, num_r_ports)
pgate.pgate.__init__(self, name)
debug.info(2, "create a multi-port bitcell with {0} rw ports, {1} w ports and {2} r ports".format(num_rw_ports,
num_w_ports,
num_r_ports))
self.num_rw_ports = num_rw_ports
self.num_w_ports = num_w_ports
self.num_r_ports = num_r_ports
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
@ -41,11 +41,11 @@ class pbitcell(pgate.pgate):
self.add_modules()
self.create_storage()
if(self.num_readwrite > 0):
if(self.num_rw_ports > 0):
self.create_readwrite_ports()
if(self.num_write > 0):
if(self.num_w_ports > 0):
self.create_write_ports()
if(self.num_read > 0):
if(self.num_r_ports > 0):
self.create_read_ports()
def create_layout(self):
@ -56,11 +56,11 @@ class pbitcell(pgate.pgate):
self.route_storage()
self.route_rails()
if(self.num_readwrite > 0):
if(self.num_rw_ports > 0):
self.place_readwrite_ports()
if(self.num_write > 0):
if(self.num_w_ports > 0):
self.place_write_ports()
if(self.num_read > 0):
if(self.num_r_ports > 0):
self.place_read_ports()
self.extend_well()
@ -68,21 +68,21 @@ class pbitcell(pgate.pgate):
self.DRC_LVS()
def add_pins(self):
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
self.add_pin("rwbl{}".format(k))
self.add_pin("rwbl_bar{}".format(k))
for k in range(self.num_write):
for k in range(self.num_w_ports):
self.add_pin("wbl{}".format(k))
self.add_pin("wbl_bar{}".format(k))
for k in range(self.num_read):
for k in range(self.num_r_ports):
self.add_pin("rbl{}".format(k))
self.add_pin("rbl_bar{}".format(k))
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
self.add_pin("rwwl{}".format(k))
for k in range(self.num_write):
for k in range(self.num_w_ports):
self.add_pin("wwl{}".format(k))
for k in range(self.num_read):
for k in range(self.num_r_ports):
self.add_pin("rwl{}".format(k))
self.add_pin("vdd")
@ -90,8 +90,8 @@ class pbitcell(pgate.pgate):
def add_modules(self):
# if there are any read/write ports, then the inverter nmos is sized based the number of them
if(self.num_readwrite > 0):
inverter_nmos_width = self.num_readwrite*3*parameter["min_tx_size"]
if(self.num_rw_ports > 0):
inverter_nmos_width = self.num_rw_ports*3*parameter["min_tx_size"]
inverter_pmos_width = parameter["min_tx_size"]
readwrite_nmos_width = 1.5*parameter["min_tx_size"]
write_nmos_width = parameter["min_tx_size"]
@ -167,7 +167,7 @@ class pbitcell(pgate.pgate):
# write to read transistor spacing (also acts as readwrite to read transistor spacing)
# calculation is dependent on whether the read transistor is adjacent to a write transistor or a readwrite transistor
if(self.num_write > 0):
if(self.num_w_ports > 0):
if(self.write_nmos_contact_extension > self.gate_contact_thres):
write_portion = drc["minwidth_metal2"] + self.write_nmos_contact_extension
else:
@ -206,23 +206,23 @@ class pbitcell(pgate.pgate):
Calculate positions that describe the edges of the cell
"""
# create flags for excluding readwrite, write, or read port calculations if they are not included in the bitcell
if(self.num_readwrite > 0):
if(self.num_rw_ports > 0):
self.readwrite_port_flag = True
else:
self.readwrite_port_flag = False
if(self.num_write > 0):
if(self.num_w_ports > 0):
self.write_port_flag = True
else:
self.write_port_flag = False
if(self.num_read > 0):
if(self.num_r_ports > 0):
self.read_port_flag = True
else:
self.read_port_flag = False
# determine the distance of the leftmost/rightmost transistor gate connection
if (self.num_read > 0):
if (self.num_r_ports > 0):
if(self.read_nmos_contact_extension > self.gate_contact_thres):
end_connection = drc["minwidth_metal2"] + self.read_nmos_contact_extension + contact.m1m2.height
else:
@ -236,11 +236,11 @@ class pbitcell(pgate.pgate):
# leftmost position = storage width + read/write ports width + write ports width + read ports width + end transistor gate connections + metal spacing necessary for tiling the bitcell
self.leftmost_xpos = -self.inverter_tile_width \
- self.inverter_to_write_spacing \
- self.readwrite_port_flag*(self.readwrite_nmos.active_height + (self.num_readwrite-1)*self.readwrite_tile_width) \
- self.readwrite_port_flag*(self.readwrite_nmos.active_height + (self.num_rw_ports-1)*self.readwrite_tile_width) \
- self.write_port_flag*self.readwrite_port_flag*self.write_to_write_spacing \
- self.write_port_flag*(self.write_nmos.active_height + (self.num_write-1)*self.write_tile_width) \
- self.write_port_flag*(self.write_nmos.active_height + (self.num_w_ports-1)*self.write_tile_width) \
- self.read_port_flag*self.write_to_read_spacing \
- self.read_port_flag*(self.read_nmos.active_height + (self.num_read-1)*self.read_tile_width) \
- self.read_port_flag*(self.read_nmos.active_height + (self.num_r_ports-1)*self.read_tile_width) \
- end_connection \
- 0.5*drc["poly_to_polycontact"]
@ -249,9 +249,9 @@ class pbitcell(pgate.pgate):
# bottommost position = gnd height + rwwl height + wwl height + rwl height + space needed between tiled bitcells
array_tiling_offset = 0.5*drc["minwidth_metal2"]
self.botmost_ypos = -self.rail_tile_height \
- self.num_readwrite*self.rowline_tile_height \
- self.num_write*self.rowline_tile_height \
- self.num_read*self.rowline_tile_height \
- self.num_rw_ports*self.rowline_tile_height \
- self.num_w_ports*self.rowline_tile_height \
- self.num_r_ports*self.rowline_tile_height \
- array_tiling_offset
# topmost position = height of the inverter + height of vdd
@ -390,11 +390,11 @@ class pbitcell(pgate.pgate):
"""
# define write transistor variables as empty arrays based on the number of write ports
self.readwrite_nmos_left = [None] * self.num_readwrite
self.readwrite_nmos_right = [None] * self.num_readwrite
self.readwrite_nmos_left = [None] * self.num_rw_ports
self.readwrite_nmos_right = [None] * self.num_rw_ports
# iterate over the number of read/write ports
for k in range(0,self.num_readwrite):
for k in range(0,self.num_rw_ports):
# add read/write transistors
self.readwrite_nmos_left[k] = self.add_inst(name="readwrite_nmos_left{}".format(k),
mod=self.readwrite_nmos)
@ -411,15 +411,15 @@ class pbitcell(pgate.pgate):
"""
# Define variables relevant to write transistors
self.rwwl_positions = [None] * self.num_readwrite
self.rwbl_positions = [None] * self.num_readwrite
self.rwbl_bar_positions = [None] * self.num_readwrite
self.rwwl_positions = [None] * self.num_rw_ports
self.rwbl_positions = [None] * self.num_rw_ports
self.rwbl_bar_positions = [None] * self.num_rw_ports
# define offset correction due to rotation of the ptx module
readwrite_rotation_correct = self.readwrite_nmos.active_height
# iterate over the number of read/write ports
for k in range(0,self.num_readwrite):
for k in range(0,self.num_rw_ports):
# Add transistors
# calculate read/write transistor offsets
left_readwrite_transistor_xpos = self.left_building_edge \
@ -529,7 +529,7 @@ class pbitcell(pgate.pgate):
# Drain/Storage connections
# this path only needs to be drawn once on the last iteration of the loop
if(k == self.num_readwrite-1):
if(k == self.num_rw_ports-1):
# add contacts to connect gate of inverters to drain of read/write transistors
left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - drc["poly_to_polycontact"] - 0.5*contact.poly.width, self.cross_couple_lower_ypos)
self.add_contact_center(layers=("poly", "contact", "metal1"),
@ -580,11 +580,11 @@ class pbitcell(pgate.pgate):
write_rotation_correct = self.write_nmos.active_height
# define write transistor variables as empty arrays based on the number of write ports
self.write_nmos_left = [None] * self.num_write
self.write_nmos_right = [None] * self.num_write
self.write_nmos_left = [None] * self.num_w_ports
self.write_nmos_right = [None] * self.num_w_ports
# iterate over the number of write ports
for k in range(0,self.num_write):
for k in range(0,self.num_w_ports):
# add write transistors
self.write_nmos_left[k] = self.add_inst(name="write_nmos_left{}".format(k),
mod=self.write_nmos)
@ -601,15 +601,15 @@ class pbitcell(pgate.pgate):
"""
# Define variables relevant to write transistors
self.wwl_positions = [None] * self.num_write
self.wbl_positions = [None] * self.num_write
self.wbl_bar_positions = [None] * self.num_write
self.wwl_positions = [None] * self.num_w_ports
self.wbl_positions = [None] * self.num_w_ports
self.wbl_bar_positions = [None] * self.num_w_ports
# define offset correction due to rotation of the ptx module
write_rotation_correct = self.write_nmos.active_height
# iterate over the number of write ports
for k in range(0,self.num_write):
for k in range(0,self.num_w_ports):
# Add transistors
# calculate write transistor offsets
left_write_transistor_xpos = self.left_building_edge \
@ -634,7 +634,7 @@ class pbitcell(pgate.pgate):
# Add WWL lines
# calculate WWL position
wwl_ypos = self.gnd_position.y \
- self.num_readwrite*self.rowline_tile_height \
- self.num_rw_ports*self.rowline_tile_height \
- (k+1)*self.rowline_tile_height
self.wwl_positions[k] = vector(self.leftmost_xpos, wwl_ypos)
@ -723,7 +723,7 @@ class pbitcell(pgate.pgate):
# Drain/Storage connections
# this path only needs to be drawn once on the last iteration of the loop
if(k == self.num_write-1):
if(k == self.num_w_ports-1):
# add contacts to connect gate of inverters to drain of write transistors
left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - drc["poly_to_polycontact"] - 0.5*contact.poly.width, self.cross_couple_lower_ypos)
self.add_contact_center(layers=("poly", "contact", "metal1"),
@ -771,13 +771,13 @@ class pbitcell(pgate.pgate):
"""
# define read transistor variables as empty arrays based on the number of read ports
self.read_nmos_left = [None] * self.num_read
self.read_nmos_right = [None] * self.num_read
self.read_access_nmos_left = [None] * self.num_read
self.read_access_nmos_right = [None] * self.num_read
self.read_nmos_left = [None] * self.num_r_ports
self.read_nmos_right = [None] * self.num_r_ports
self.read_access_nmos_left = [None] * self.num_r_ports
self.read_access_nmos_right = [None] * self.num_r_ports
# iterate over the number of read ports
for k in range(0,self.num_read):
for k in range(0,self.num_r_ports):
# add read-access transistors
self.read_access_nmos_left[k] = self.add_inst(name="read_access_nmos_left{}".format(k),
mod=self.read_nmos)
@ -802,9 +802,9 @@ class pbitcell(pgate.pgate):
"""
# Define variables relevant to read transistors
self.rwl_positions = [None] * self.num_read
self.rbl_positions = [None] * self.num_read
self.rbl_bar_positions = [None] * self.num_read
self.rwl_positions = [None] * self.num_r_ports
self.rbl_positions = [None] * self.num_r_ports
self.rbl_bar_positions = [None] * self.num_r_ports
# define offset correction due to rotation of the ptx module
read_rotation_correct = self.read_nmos.active_height
@ -813,7 +813,7 @@ class pbitcell(pgate.pgate):
overlap_offset = self.read_nmos.get_pin("D").ll() - self.read_nmos.get_pin("S").ll()
# iterate over the number of read ports
for k in range(0,self.num_read):
for k in range(0,self.num_r_ports):
# Add transistors
# calculate transistor offsets
left_read_transistor_xpos = self.left_building_edge \
@ -843,8 +843,8 @@ class pbitcell(pgate.pgate):
# Add RWL lines
# calculate RWL position
rwl_ypos = self.gnd_position.y \
- self.num_readwrite*self.rowline_tile_height \
- self.num_write*self.rowline_tile_height \
- self.num_rw_ports*self.rowline_tile_height \
- self.num_w_ports*self.rowline_tile_height \
- (k+1)*self.rowline_tile_height
self.rwl_positions[k] = vector(self.leftmost_xpos, rwl_ypos)
@ -1003,7 +1003,7 @@ class pbitcell(pgate.pgate):
# extend pwell over read/write and write transistors to the
# height of the write transistor well (read/write and write
# transistors are the same height)
if(self.num_write > 0):
if(self.num_w_ports > 0):
# calculate the edge of the write transistor well closest to the center
left_write_well_xpos = self.write_nmos_left[0].offset.x + drc["well_enclosure_active"]
right_write_well_xpos = self.write_nmos_right[0].offset.x - self.write_nmos.active_height - drc["well_enclosure_active"]
@ -1029,7 +1029,7 @@ class pbitcell(pgate.pgate):
height=write_well_height)
# extend pwell over the read transistors to the height of the bitcell
if(self.num_read > 0):
if(self.num_r_ports > 0):
# calculate the edge of the read transistor well clostest to the center
left_read_well_xpos = self.read_nmos_left[0].offset.x + drc["well_enclosure_active"]
right_read_well_xpos = self.read_nmos_right[0].offset.x - self.read_nmos.active_height - drc["well_enclosure_active"]
@ -1088,20 +1088,20 @@ class pbitcell(pgate.pgate):
def list_bitcell_pins(self, col, row):
""" Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """
bitcell_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
bitcell_pins.append("rwbl{0}[{1}]".format(k,col))
bitcell_pins.append("rwbl_bar{0}[{1}]".format(k,col))
for k in range(self.num_write):
for k in range(self.num_w_ports):
bitcell_pins.append("wbl{0}[{1}]".format(k,col))
bitcell_pins.append("wbl_bar{0}[{1}]".format(k,col))
for k in range(self.num_read):
for k in range(self.num_r_ports):
bitcell_pins.append("rbl{0}[{1}]".format(k,col))
bitcell_pins.append("rbl_bar{0}[{1}]".format(k,col))
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
bitcell_pins.append("rwwl{0}[{1}]".format(k,row))
for k in range(self.num_write):
for k in range(self.num_w_ports):
bitcell_pins.append("wwl{0}[{1}]".format(k,row))
for k in range(self.num_read):
for k in range(self.num_r_ports):
bitcell_pins.append("rwl{0}[{1}]".format(k,row))
bitcell_pins.append("vdd")
bitcell_pins.append("gnd")
@ -1111,11 +1111,11 @@ class pbitcell(pgate.pgate):
def list_all_wl_names(self):
""" Creates a list of all wordline pin names """
row_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
row_pins.append("rwwl{0}".format(k))
for k in range(self.num_write):
for k in range(self.num_w_ports):
row_pins.append("wwl{0}".format(k))
for k in range(self.num_read):
for k in range(self.num_r_ports):
row_pins.append("rwl{0}".format(k))
return row_pins
@ -1123,9 +1123,9 @@ class pbitcell(pgate.pgate):
def list_read_wl_names(self):
""" Creates a list of wordline pin names associated with read ports """
row_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
row_pins.append("rwwl{0}".format(k))
for k in range(self.num_read):
for k in range(self.num_r_ports):
row_pins.append("rwl{0}".format(k))
return row_pins
@ -1133,9 +1133,9 @@ class pbitcell(pgate.pgate):
def list_write_wl_names(self):
""" Creates a list of wordline pin names associated with write ports """
row_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
row_pins.append("rwwl{0}".format(k))
for k in range(self.num_write):
for k in range(self.num_w_ports):
row_pins.append("wwl{0}".format(k))
return row_pins
@ -1144,13 +1144,13 @@ class pbitcell(pgate.pgate):
def list_all_bitline_names(self):
""" Creates a list of all bitline pin names (both bl and br) """
column_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
column_pins.append("rwbl{0}".format(k))
column_pins.append("rwbl_bar{0}".format(k))
for k in range(self.num_write):
for k in range(self.num_w_ports):
column_pins.append("wbl{0}".format(k))
column_pins.append("wbl_bar{0}".format(k))
for k in range(self.num_read):
for k in range(self.num_r_ports):
column_pins.append("rbl{0}".format(k))
column_pins.append("rbl_bar{0}".format(k))
@ -1159,11 +1159,11 @@ class pbitcell(pgate.pgate):
def list_all_bl_names(self):
""" Creates a list of all bl pins names """
column_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
column_pins.append("rwbl{0}".format(k))
for k in range(self.num_write):
for k in range(self.num_w_ports):
column_pins.append("wbl{0}".format(k))
for k in range(self.num_read):
for k in range(self.num_r_ports):
column_pins.append("rbl{0}".format(k))
return column_pins
@ -1171,11 +1171,11 @@ class pbitcell(pgate.pgate):
def list_all_br_names(self):
""" Creates a list of all br pins names """
column_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
column_pins.append("rwbl_bar{0}".format(k))
for k in range(self.num_write):
for k in range(self.num_w_ports):
column_pins.append("wbl_bar{0}".format(k))
for k in range(self.num_read):
for k in range(self.num_r_ports):
column_pins.append("rbl_bar{0}".format(k))
return column_pins
@ -1183,9 +1183,9 @@ class pbitcell(pgate.pgate):
def list_read_bl_names(self):
""" Creates a list of bl pin names associated with read ports """
column_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
column_pins.append("rwbl{0}".format(k))
for k in range(self.num_read):
for k in range(self.num_r_ports):
column_pins.append("rbl{0}".format(k))
return column_pins
@ -1193,9 +1193,9 @@ class pbitcell(pgate.pgate):
def list_read_br_names(self):
""" Creates a list of br pin names associated with read ports """
column_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
column_pins.append("rwbl_bar{0}".format(k))
for k in range(self.num_read):
for k in range(self.num_r_ports):
column_pins.append("rbl_bar{0}".format(k))
return column_pins
@ -1203,9 +1203,9 @@ class pbitcell(pgate.pgate):
def list_write_bl_names(self):
""" Creates a list of bl pin names associated with write ports """
column_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
column_pins.append("rwbl{0}".format(k))
for k in range(self.num_write):
for k in range(self.num_w_ports):
column_pins.append("wbl{0}".format(k))
return column_pins
@ -1213,9 +1213,9 @@ class pbitcell(pgate.pgate):
def list_write_br_names(self):
""" Creates a list of br pin names asscociated with write ports"""
column_pins = []
for k in range(self.num_readwrite):
for k in range(self.num_rw_ports):
column_pins.append("rwbl_bar{0}".format(k))
for k in range(self.num_write):
for k in range(self.num_w_ports):
column_pins.append("wbl_bar{0}".format(k))
return column_pins

View File

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

View File

@ -18,8 +18,9 @@ class sram_1bank(sram_base):
"""
Procedures specific to a one bank SRAM.
"""
def __init__(self, word_size, num_words, name):
sram_base.__init__(self, word_size, num_words, 1, name)
def __init__(self, sram_config, name):
sram_base.__init__(self, sram_config, name)
def create_netlist(self):
self.compute_sizes()
@ -99,18 +100,18 @@ class sram_1bank(sram_base):
for i in range(self.word_size):
dout_name = "dout0[{}]".format(i)
self.copy_layout_pin(self.bank_inst, dout_name, "DOUT[{}]".format(i))
self.copy_layout_pin(self.bank_inst, dout_name, "DOUT0[{}]".format(i))
# Lower address bits
for i in range(self.col_addr_size):
self.copy_layout_pin(self.col_addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i))
self.copy_layout_pin(self.col_addr_dff_inst, "din[{}]".format(i),"ADDR0[{}]".format(i))
# Upper address bits
for i in range(self.row_addr_size):
self.copy_layout_pin(self.row_addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i+self.col_addr_size))
self.copy_layout_pin(self.row_addr_dff_inst, "din[{}]".format(i),"ADDR0[{}]".format(i+self.col_addr_size))
for i in range(self.word_size):
din_name = "din[{}]".format(i)
self.copy_layout_pin(self.data_dff_inst, din_name, din_name.upper())
self.copy_layout_pin(self.data_dff_inst, din_name, "DIN0[{}]".format(i))
def route(self):
""" Route a single bank SRAM """

View File

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

View File

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

View File

@ -2,6 +2,7 @@ import sys
import datetime
import getpass
import debug
from importlib import reload
from math import log,sqrt,ceil
from vector import vector
from globals import OPTS, print_time
@ -13,28 +14,17 @@ class sram_base(design):
Dynamically generated SRAM by connecting banks to control logic. The
number of banks should be 1 , 2 or 4
"""
def __init__(self, word_size, num_words, num_banks, name):
def __init__(self, sram_config, name):
design.__init__(self, name)
from importlib import reload
c = reload(__import__(OPTS.control_logic))
self.mod_control_logic = getattr(c, OPTS.control_logic)
# This is used to compute the sizes of the SRAM
# and must be loaded before netlist creation
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
c = reload(__import__(OPTS.ms_flop))
self.mod_ms_flop = getattr(c, OPTS.ms_flop)
self.ms_flop = self.mod_ms_flop()
self.word_size = word_size
self.num_words = num_words
self.num_banks = num_banks
self.total_write = OPTS.rw_ports + OPTS.w_ports
self.total_read = OPTS.rw_ports + OPTS.r_ports
self.total_ports = OPTS.rw_ports + OPTS.w_ports + OPTS.r_ports
self.sram_config = sram_config
self.sram_config.set_local_config(self)
self.bank_insts = []
@ -45,18 +35,22 @@ class sram_base(design):
self.num_words_per_bank = self.num_words/self.num_banks
self.num_bits_per_bank = self.word_size*self.num_words_per_bank
# If this was hard coded, don't dynamically compute it!
if self.sram_config.words_per_row:
self.words_per_row = self.sram_config.words_per_row
else:
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank
self.bank_side_length = sqrt(self.bank_area)
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank
self.bank_side_length = sqrt(self.bank_area)
# Estimate the words per row given the height of the bitcell and the square side length
self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width)
self.words_per_row = self.estimate_words_per_row(self.tentative_num_cols, self.word_size)
# Estimate the words per row given the height of the bitcell and the square side length
self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width)
self.words_per_row = self.estimate_words_per_row(self.tentative_num_cols, self.word_size)
# Estimate the number of rows given the tentative words per row
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
# Estimate the number of rows given the tentative words per row
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
# Fix the number of columns and rows
self.num_cols = int(self.words_per_row*self.word_size)
@ -67,7 +61,8 @@ class sram_base(design):
self.col_addr_size = int(log(self.words_per_row, 2))
self.bank_addr_size = self.col_addr_size + self.row_addr_size
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
self.sram_config.words_per_row = self.words_per_row
debug.info(1,"Words per row: {}".format(self.words_per_row))
def estimate_words_per_row(self,tentative_num_cols, word_size):
@ -279,7 +274,15 @@ class sram_base(design):
def add_modules(self):
""" Create all the modules that will be used """
c = reload(__import__(OPTS.control_logic))
self.mod_control_logic = getattr(c, OPTS.control_logic)
c = reload(__import__(OPTS.ms_flop))
self.mod_ms_flop = getattr(c, OPTS.ms_flop)
self.ms_flop = self.mod_ms_flop()
from control_logic import control_logic
# Create the control logic module
self.control_logic = self.mod_control_logic(num_rows=self.num_rows)
@ -301,10 +304,7 @@ class sram_base(design):
# Create the bank module (up to four are instantiated)
from bank import bank
self.bank = bank(word_size=self.word_size,
num_words=self.num_words_per_bank,
words_per_row=self.words_per_row,
num_banks=self.num_banks,
self.bank = bank(self.sram_config,
name="bank")
self.add_mod(self.bank)

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
debug.info(2, "Bitcell with 1 of each port: read/write, write, and read")
tx = pbitcell.pbitcell(num_readwrite=1,num_write=1,num_read=1)
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=1,num_r_ports=1)
self.local_check(tx)
debug.info(2, "Bitcell with 0 read/write ports")
tx = pbitcell.pbitcell(num_readwrite=0,num_write=1,num_read=1)
tx = pbitcell.pbitcell(num_rw_ports=0,num_w_ports=1,num_r_ports=1)
self.local_check(tx)
debug.info(2, "Bitcell with 0 write ports")
tx = pbitcell.pbitcell(num_readwrite=1,num_write=0,num_read=1)
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=0,num_r_ports=1)
self.local_check(tx)
debug.info(2, "Bitcell with 0 read ports")
tx = pbitcell.pbitcell(num_readwrite=1,num_write=1,num_read=0)
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=1,num_r_ports=0)
self.local_check(tx)
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
tx = pbitcell.pbitcell(num_readwrite=1,num_write=0,num_read=0)
tx = pbitcell.pbitcell(num_rw_ports=1,num_w_ports=0,num_r_ports=0)
self.local_check(tx)
debug.info(2, "Bitcell with 2 of each port: read/write, write, and read")
tx = pbitcell.pbitcell(num_readwrite=2,num_write=2,num_read=2)
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=2,num_r_ports=2)
self.local_check(tx)
debug.info(2, "Bitcell with 0 read/write ports")
tx = pbitcell.pbitcell(num_readwrite=0,num_write=2,num_read=2)
tx = pbitcell.pbitcell(num_rw_ports=0,num_w_ports=2,num_r_ports=2)
self.local_check(tx)
debug.info(2, "Bitcell with 0 write ports")
tx = pbitcell.pbitcell(num_readwrite=2,num_write=0,num_read=2)
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=0,num_r_ports=2)
self.local_check(tx)
debug.info(2, "Bitcell with 0 read ports")
tx = pbitcell.pbitcell(num_readwrite=2,num_write=2,num_read=0)
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=2,num_r_ports=0)
self.local_check(tx)
debug.info(2, "Bitcell with 0 read ports and 0 write ports")
tx = pbitcell.pbitcell(num_readwrite=2,num_write=0,num_read=0)
tx = pbitcell.pbitcell(num_rw_ports=2,num_w_ports=0,num_r_ports=0)
self.local_check(tx)
globals.end_openram()

View File

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

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

View File

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

View File

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

View File

@ -28,9 +28,9 @@ class sense_amp_test(openram_test):
# check sense amp array in multi-port
OPTS.bitcell = "pbitcell"
OPTS.rw_ports = 1
OPTS.w_ports = 0
OPTS.r_ports = 0
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=2 (multi-port case)")
a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=2)

View File

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

View File

@ -16,21 +16,34 @@ class multi_bank_test(openram_test):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
from bank import bank
from sram_config import sram_config
c = sram_config(word_size=4,
num_words=16)
c.num_banks=2
c.words_per_row=1
debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=2, name="bank1_multi")
a = bank(c, name="bank1_multi")
self.local_check(a)
c.num_words=32
c.words_per_row=2
debug.info(1, "Two way column mux")
a = bank(word_size=4, num_words=32, words_per_row=2, num_banks=2, name="bank2_multi")
a = bank(c, name="bank2_multi")
self.local_check(a)
c.num_words=64
c.words_per_row=4
debug.info(1, "Four way column mux")
a = bank(word_size=4, num_words=64, words_per_row=4, num_banks=2, name="bank3_multi")
a = bank(c, name="bank3_multi")
self.local_check(a)
c.word_size=2
c.num_words=128
c.words_per_row=8
debug.info(1, "Eight way column mux")
a = bank(word_size=2, num_words=128, words_per_row=8, num_banks=2, name="bank4_multi")
a = bank(c, name="bank4_multi")
self.local_check(a)
globals.end_openram()

View File

@ -20,80 +20,103 @@ class psingle_bank_test(openram_test):
import verify
from bank import bank
from sram_config import sram_config
OPTS.bitcell = "pbitcell"
# testing layout of bank using pbitcell with 1 RW port (a 6T-cell equivalent)
OPTS.rw_ports = 1
OPTS.w_ports = 0
OPTS.r_ports = 0
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
c = sram_config(word_size=4,
num_words=16)
c.words_per_row=1
debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_1rw_0w_0r_single")
a = bank(c, name="bank1_1rw_0w_0r_single")
self.local_check(a)
"""
# testing all port configurations (with no column mux) to verify layout between bitcell array and peripheral circuitry
OPTS.rw_ports = 2
OPTS.w_ports = 2
OPTS.r_ports = 2
# multiport can't generate layout yet on the bank level
OPTS.netlist_only = True
debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_2rw_2w_2r_single")
self.local_check(a)
"""
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 1
OPTS.num_r_ports = 1
"""
OPTS.rw_ports = 0
OPTS.w_ports = 2
OPTS.r_ports = 2
debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_0rw_2w_2r_single")
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
OPTS.rw_ports = 2
OPTS.w_ports = 0
OPTS.r_ports = 2
OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.num_w_ports = c.num_w_ports = 2
OPTS.num_r_ports = c.num_r_ports = 2
debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_2rw_0w_2r_single")
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
OPTS.num_rw_ports = c.num_rw_ports = 0
OPTS.num_w_ports = c.num_w_ports = 2
OPTS.num_r_ports = c.num_r_ports = 2
debug.info(1, "No column mux")
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
OPTS.rw_ports = 2
OPTS.w_ports = 2
OPTS.r_ports = 0
OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.num_w_ports = c.num_w_ports = 0
OPTS.num_r_ports = c.num_r_ports = 2
debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_2rw_2w_0r_single")
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
OPTS.rw_ports = 2
OPTS.w_ports = 0
OPTS.r_ports = 0
OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.num_w_ports = c.num_w_ports = 2
OPTS.num_r_ports = c.num_r_ports = 0
debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_2rw_0w_0r_single")
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.num_w_ports = c.num_w_ports = 0
OPTS.num_r_ports = c.num_r_ports = 0
debug.info(1, "No column mux")
name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
# testing with various column muxes
OPTS.rw_ports = 2
OPTS.w_ports = 2
OPTS.r_ports = 2
OPTS.num_rw_ports = c.num_rw_ports = 2
OPTS.num_w_ports = c.num_w_ports = 2
OPTS.num_r_ports = c.num_r_ports = 2
c.num_words=32
c.words_per_row=2
debug.info(1, "Two way column mux")
a = bank(word_size=4, num_words=32, words_per_row=2, num_banks=1, name="bank2_single")
name = "bank2_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
c.num_words=64
c.words_per_row=4
debug.info(1, "Four way column mux")
a = bank(word_size=4, num_words=64, words_per_row=4, num_banks=1, name="bank3_single")
name = "bank3_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
# Eight way has a short circuit of one column mux select to gnd rail
c.word_size=2
c.num_words=128
c.words_per_row=8
debug.info(1, "Eight way column mux")
a = bank(word_size=2, num_words=128, words_per_row=8, num_banks=1, name="bank4_single")
name = "bank4_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports)
a = bank(c, name=name)
self.local_check(a)
"""

View File

@ -16,22 +16,34 @@ class single_bank_test(openram_test):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
from bank import bank
from sram_config import sram_config
c = sram_config(word_size=4,
num_words=16)
c.words_per_row=1
debug.info(1, "No column mux")
a = bank(word_size=4, num_words=16, words_per_row=1, num_banks=1, name="bank1_single")
self.local_check(a)
debug.info(1, "Two way column mux")
a = bank(word_size=4, num_words=32, words_per_row=2, num_banks=1, name="bank2_single")
a = bank(c, name="bank1_single")
self.local_check(a)
c.num_words=32
c.words_per_row=2
debug.info(1, "Two way column mux")
a = bank(c, name="bank2_single")
self.local_check(a)
c.num_words=64
c.words_per_row=4
debug.info(1, "Four way column mux")
a = bank(word_size=4, num_words=64, words_per_row=4, num_banks=1, name="bank3_single")
a = bank(c, name="bank3_single")
self.local_check(a)
# Eight way has a short circuit of one column mux select to gnd rail
c.word_size=2
c.num_words=128
c.words_per_row=8
debug.info(1, "Eight way column mux")
a = bank(word_size=2, num_words=128, words_per_row=8, num_banks=1, name="bank4_single")
a = bank(c, name="bank4_single")
self.local_check(a)
globals.end_openram()

View File

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

View File

@ -17,21 +17,32 @@ class sram_2bank_test(openram_test):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
from sram import sram
from sram_config import sram_config
c = sram_config(word_size=16,
num_words=32,
num_banks=2)
debug.info(1, "Two bank, no column mux with control logic")
a = sram(word_size=16, num_words=32, num_banks=2, name="sram1")
a = sram(c, name="sram1")
self.local_check(a, final_verification=True)
c.num_words=64
c.words_per_row=2
debug.info(1, "Two bank two way column mux with control logic")
a = sram(word_size=16, num_words=64, num_banks=2, name="sram2")
a = sram(c, name="sram2")
self.local_check(a, final_verification=True)
c.num_words=128
c.words_per_row=4
debug.info(1, "Two bank, four way column mux with control logic")
a = sram(word_size=16, num_words=128, num_banks=2, name="sram3")
a = sram(c, name="sram3")
self.local_check(a, final_verification=True)
c.word_size=2
c.num_words=256
c.words_per_row=8
debug.info(1, "Two bank, eight way column mux with control logic")
a = sram(word_size=2, num_words=256, num_banks=2, name="sram4")
a = sram(c, name="sram4")
self.local_check(a, final_verification=True)
globals.end_openram()

View File

@ -17,19 +17,30 @@ class sram_4bank_test(openram_test):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
from sram import sram
from sram_config import sram_config
c = sram_config(word_size=16,
num_words=64,
num_banks=4)
debug.info(1, "Four bank, no column mux with control logic")
a = sram(word_size=16, num_words=64, num_banks=4, name="sram1")
a = sram(c, name="sram1")
self.local_check(a, final_verification=True)
c.num_words=128
c.words_per_row=2
debug.info(1, "Four bank two way column mux with control logic")
a = sram(word_size=16, num_words=128, num_banks=4, name="sram2")
a = sram(c, name="sram2")
self.local_check(a, final_verification=True)
c.num_words=256
c.words_per_row=4
debug.info(1, "Four bank, four way column mux with control logic")
a = sram(word_size=16, num_words=256, num_banks=4, name="sram3")
self.local_check(a, final_verification=True)
c.word_size=2
c.num_words=256
c.words_per_row=8
debug.info(1, "Four bank, eight way column mux with control logic")
a = sram.sram(word_size=2, num_words=256, num_banks=4, name="sram4")
self.local_check(a, final_verification=True)

View File

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

View File

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

View File

@ -16,15 +16,16 @@ class lib_test(openram_test):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
import sram
from characterizer import lib
from sram import sram
from sram_config import sram_config
c = sram_config(word_size=2,
num_words=16,
num_banks=1)
debug.info(1, "Testing analytical timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2,
num_words=16,
num_banks=1,
name="sram_2_16_1_{0}".format(OPTS.tech_name))
tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice)

View File

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

View File

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

View File

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

View File

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