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: elif self.col_addr_size == 3:
self.column_decoder = factory.create(module_type="hierarchical_predecode3x8", self.column_decoder = factory.create(module_type="hierarchical_predecode3x8",
height=self.dff.height) height=self.dff.height)
elif self.col_addr_size == 4:
self.column_decoder = factory.create(module_type="hierarchical_predecode4x16",
height=self.dff.height)
else: else:
# No error checking before? # No error checking before?
debug.error("Invalid column decoder?", -1) 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, "vdd")
self.copy_power_pins(inst, "gnd") self.copy_power_pins(inst, "gnd")
rbl_vdd_pin = self.rbl_driver_inst.get_pin("vdd") for rbl_vdd_pin in self.rbl_driver_inst.get_pins("vdd"):
self.add_power_pin("vdd", rbl_vdd_pin.lc()) self.add_power_pin("vdd", rbl_vdd_pin.center())
def route_pins(self): def route_pins(self):
for row in range(self.addr_size): for row in range(self.addr_size):

View File

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

View File

@ -79,13 +79,6 @@ class sram():
""" Save all the output files while reporting time to do it as well. """ """ Save all the output files while reporting time to do it as well. """
if not OPTS.netlist_only: 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 # Write the layout
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
gdsname = OPTS.output_path + self.s.name + ".gds" gdsname = OPTS.output_path + self.s.name + ".gds"
@ -93,6 +86,13 @@ class sram():
self.gds_write(gdsname) self.gds_write(gdsname)
print_time("GDS", datetime.datetime.now(), start_time) 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 # Save the spice file
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
spname = OPTS.output_path + self.s.name + ".sp" spname = OPTS.output_path + self.s.name + ".sp"

View File

@ -6,15 +6,15 @@
# All rights reserved. # All rights reserved.
# #
import debug import debug
from math import log,sqrt,ceil from math import log, sqrt, ceil
from importlib import reload
from globals import OPTS from globals import OPTS
from sram_factory import factory from sram_factory import factory
class sram_config: class sram_config:
""" This is a structure that is used to hold the SRAM configuration options. """ """ 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.word_size = word_size
self.num_words = num_words self.num_words = num_words
self.write_size = write_size self.write_size = write_size
@ -25,7 +25,7 @@ class sram_config:
# This will get over-written when we determine the organization # This will get over-written when we determine the organization
self.words_per_row = words_per_row self.words_per_row = words_per_row
self.compute_sizes() self.compute_sizes()
def set_local_config(self, module): def set_local_config(self, module):
""" Copy all of the member variables to the given module for convenience """ """ 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 # Copy all the variables to the local module
for member in members: for member in members:
setattr(module,member,getattr(self,member)) setattr(module, member, getattr(self, member))
def compute_sizes(self): def compute_sizes(self):
""" Computes the organization of the memory using bitcell size by trying to make it square.""" """ Computes the organization of the memory using bitcell size by trying to make it square."""
bitcell = factory.create(module_type="bitcell") bitcell = factory.create(module_type="bitcell")
debug.check(self.num_banks in [1, 2, 4],
debug.check(self.num_banks in [1,2,4], "Valid number of banks are 1 , 2 and 4.") "Valid number of banks are 1 , 2 and 4.")
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 this was hard coded, don't dynamically compute it!
if not self.words_per_row: if not self.words_per_row:
# Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry) # 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) self.bank_side_length = sqrt(self.bank_area)
# Estimate the words per row given the height of the bitcell and the square side length # 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) 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 # 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.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
self.recompute_sizes() self.recompute_sizes()
@ -70,57 +70,57 @@ class sram_config:
SRAM for testing. 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 # If the banks changed
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
# 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)
self.num_rows_temp = int(self.num_words_per_bank/self.words_per_row) 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 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 # Compute the address and bank sizes
self.row_addr_size = ceil(log(self.num_rows, 2)) self.row_addr_size = ceil(log(self.num_rows, 2))
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))
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) + " Col addr size: {}".format(self.col_addr_size)
+ " Bank addr size: {}".format(self.bank_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 This provides a heuristic rounded estimate for the number of words
per row. 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: closest_way = min(column_mux_sizes, key=lambda x: abs(x - tentative_column_ways))
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
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 This picks the number of words per row more accurately by limiting
it to a minimum and maximum. it to a minimum and maximum.
""" """
# Recompute the words per row given a hard max # Recompute the words per row given a hard max
if(not OPTS.is_unit_test and tentative_num_rows > 512): 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") debug.check(tentative_num_rows * words_per_row <= 4096,
return int(words_per_row*tentative_num_rows/512) "Number of words exceeds 2048")
return int(words_per_row * tentative_num_rows / 512)
# Recompute the words per row given a hard min # Recompute the words per row given a hard min
if(not OPTS.is_unit_test and 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)) debug.check(tentative_num_rows * words_per_row >= 16,
return int(words_per_row*tentative_num_rows/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 return words_per_row