mirror of https://github.com/VLSIDA/OpenRAM.git
Allow 16-way column mux
This commit is contained in:
parent
27d921d2db
commit
c2629edc1b
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue