Allow 16-way column mux

This commit is contained in:
mrg 2020-10-06 16:27:02 -07:00
parent 27d921d2db
commit c2629edc1b
5 changed files with 53 additions and 48 deletions

View File

@ -533,6 +533,9 @@ class bank(design.design):
elif self.col_addr_size == 3:
self.column_decoder = factory.create(module_type="hierarchical_predecode3x8",
height=self.dff.height)
elif self.col_addr_size == 4:
self.column_decoder = factory.create(module_type="hierarchical_predecode4x16",
height=self.dff.height)
else:
# No error checking before?
debug.error("Invalid column decoder?", -1)

View File

@ -79,8 +79,8 @@ class port_address(design.design):
self.copy_power_pins(inst, "vdd")
self.copy_power_pins(inst, "gnd")
rbl_vdd_pin = self.rbl_driver_inst.get_pin("vdd")
self.add_power_pin("vdd", rbl_vdd_pin.lc())
for rbl_vdd_pin in self.rbl_driver_inst.get_pins("vdd"):
self.add_power_pin("vdd", rbl_vdd_pin.center())
def route_pins(self):
for row in range(self.addr_size):

View File

@ -221,8 +221,10 @@ class replica_column(bitcell_base_array):
bitcell_pins = []
for port in self.all_ports:
bitcell_pins.extend([x for x in self.get_bitline_names(port) if x.endswith("_{0}".format(col))])
bitcell_pins.append("vdd")
bitcell_pins.append("gnd")
if len(self.edge_cell.get_pins("vdd")) > 0:
bitcell_pins.append("vdd")
if len(self.edge_cell.get_pins("gnd")) > 0:
bitcell_pins.append("gnd")
return bitcell_pins

View File

@ -79,13 +79,6 @@ class sram():
""" Save all the output files while reporting time to do it as well. """
if not OPTS.netlist_only:
# Create a LEF physical model
start_time = datetime.datetime.now()
lefname = OPTS.output_path + self.s.name + ".lef"
debug.print_raw("LEF: Writing to {0}".format(lefname))
self.lef_write(lefname)
print_time("LEF", datetime.datetime.now(), start_time)
# Write the layout
start_time = datetime.datetime.now()
gdsname = OPTS.output_path + self.s.name + ".gds"
@ -93,6 +86,13 @@ class sram():
self.gds_write(gdsname)
print_time("GDS", datetime.datetime.now(), start_time)
# Create a LEF physical model
start_time = datetime.datetime.now()
lefname = OPTS.output_path + self.s.name + ".lef"
debug.print_raw("LEF: Writing to {0}".format(lefname))
self.lef_write(lefname)
print_time("LEF", datetime.datetime.now(), start_time)
# Save the spice file
start_time = datetime.datetime.now()
spname = OPTS.output_path + self.s.name + ".sp"

View File

@ -6,15 +6,15 @@
# All rights reserved.
#
import debug
from math import log,sqrt,ceil
from importlib import reload
from math import log, sqrt, ceil
from globals import OPTS
from sram_factory import factory
class sram_config:
""" This is a structure that is used to hold the SRAM configuration options. """
def __init__(self, word_size, num_words, write_size = None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0):
def __init__(self, word_size, num_words, write_size=None, num_banks=1, words_per_row=None, num_spare_rows=0, num_spare_cols=0):
self.word_size = word_size
self.num_words = num_words
self.write_size = write_size
@ -25,7 +25,7 @@ class sram_config:
# This will get over-written when we determine the organization
self.words_per_row = words_per_row
self.compute_sizes()
self.compute_sizes()
def set_local_config(self, module):
""" Copy all of the member variables to the given module for convenience """
@ -34,31 +34,31 @@ class sram_config:
# Copy all the variables to the local module
for member in members:
setattr(module,member,getattr(self,member))
setattr(module, member, getattr(self, member))
def compute_sizes(self):
""" Computes the organization of the memory using bitcell size by trying to make it square."""
bitcell = factory.create(module_type="bitcell")
debug.check(self.num_banks in [1,2,4], "Valid number of banks are 1 , 2 and 4.")
debug.check(self.num_banks in [1, 2, 4],
"Valid number of banks are 1 , 2 and 4.")
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_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 not self.words_per_row:
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
self.bank_area = bitcell.width*bitcell.height*self.num_bits_per_bank
self.bank_area = bitcell.width * 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/bitcell.width)
self.tentative_num_cols = int(self.bank_side_length / 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.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)
self.recompute_sizes()
@ -70,57 +70,57 @@ class sram_config:
SRAM for testing.
"""
debug.info(1,"Recomputing with words per row: {}".format(self.words_per_row))
debug.info(1, "Recomputing with words per row: {}".format(self.words_per_row))
# If the banks changed
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_words_per_bank = self.num_words / self.num_banks
self.num_bits_per_bank = self.word_size * self.num_words_per_bank
# Fix the number of columns and rows
self.num_cols = int(self.words_per_row*self.word_size)
self.num_rows_temp = int(self.num_words_per_bank/self.words_per_row)
self.num_cols = int(self.words_per_row * self.word_size)
self.num_rows_temp = int(self.num_words_per_bank / self.words_per_row)
self.num_rows = self.num_rows_temp + self.num_spare_rows
debug.info(1,"Rows: {} Cols: {}".format(self.num_rows_temp,self.num_cols))
debug.info(1, "Rows: {} Cols: {}".format(self.num_rows_temp, self.num_cols))
# Compute the address and bank sizes
self.row_addr_size = ceil(log(self.num_rows, 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.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
debug.info(1,"Row addr size: {}".format(self.row_addr_size)
debug.info(1, "Row addr size: {}".format(self.row_addr_size)
+ " Col addr size: {}".format(self.col_addr_size)
+ " Bank addr size: {}".format(self.bank_addr_size))
def estimate_words_per_row(self,tentative_num_cols, word_size):
def estimate_words_per_row(self, tentative_num_cols, word_size):
"""
This provides a heuristic rounded estimate for the number of words
per row.
"""
tentative_column_ways = tentative_num_cols / word_size
column_mux_sizes = [1, 2, 4, 8, 16]
# If we are double, we may want a larger column mux
if tentative_column_ways > 2 * column_mux_sizes[-1]:
debug.warning("Extremely large number of columns for 16-way maximum column mux.")
if tentative_num_cols < 1.5*word_size:
return 1
elif tentative_num_cols < 3*word_size:
return 2
elif tentative_num_cols < 6*word_size:
return 4
else:
if tentative_num_cols > 16*word_size:
debug.warning("Reaching column mux size limit. Consider increasing above 8-way.")
return 8
closest_way = min(column_mux_sizes, key=lambda x: abs(x - tentative_column_ways))
def amend_words_per_row(self,tentative_num_rows, words_per_row):
return closest_way
def amend_words_per_row(self, tentative_num_rows, words_per_row):
"""
This picks the number of words per row more accurately by limiting
it to a minimum and maximum.
"""
# Recompute the words per row given a hard max
if(not OPTS.is_unit_test and tentative_num_rows > 512):
debug.check(tentative_num_rows*words_per_row <= 2048, "Number of words exceeds 2048")
return int(words_per_row*tentative_num_rows/512)
debug.check(tentative_num_rows * words_per_row <= 4096,
"Number of words exceeds 2048")
return int(words_per_row * tentative_num_rows / 512)
# Recompute the words per row given a hard min
if(not OPTS.is_unit_test and tentative_num_rows < 16):
debug.check(tentative_num_rows*words_per_row >= 16, "Minimum number of rows is 16, but given {0}".format(tentative_num_rows))
return int(words_per_row*tentative_num_rows/16)
if (not OPTS.is_unit_test and tentative_num_rows < 16):
debug.check(tentative_num_rows * words_per_row >= 16,
"Minimum number of rows is 16, but given {0}".format(tentative_num_rows))
return int(words_per_row * tentative_num_rows / 16)
return words_per_row