mirror of https://github.com/VLSIDA/OpenRAM.git
Added graph creation to characterizer, re-arranged pin creation.
This commit is contained in:
parent
b4cce65889
commit
b30c20ffb5
|
|
@ -10,6 +10,7 @@ from globals import OPTS
|
|||
from .simulation import simulation
|
||||
from .measurements import *
|
||||
import logical_effort
|
||||
import graph_util
|
||||
|
||||
class delay(simulation):
|
||||
"""Functions to measure the delay and power of an SRAM at a given address and
|
||||
|
|
@ -37,6 +38,8 @@ class delay(simulation):
|
|||
self.period = 0
|
||||
self.set_load_slew(0,0)
|
||||
self.set_corner(corner)
|
||||
self.create_signal_names()
|
||||
self.add_graph_exclusions()
|
||||
|
||||
def create_measurement_names(self):
|
||||
"""Create measurement names. The names themselves currently define the type of measurement"""
|
||||
|
|
@ -157,19 +160,31 @@ class delay(simulation):
|
|||
self.debug_volt_meas[-1].meta_str = debug_meas.meta_str
|
||||
return self.debug_delay_meas+self.debug_volt_meas
|
||||
|
||||
def create_signal_names(self):
|
||||
self.addr_name = "A"
|
||||
self.din_name = "DIN"
|
||||
self.dout_name = "DOUT"
|
||||
|
||||
#This is TODO once multiport control has been finalized.
|
||||
#self.control_name = "CSB"
|
||||
|
||||
def set_load_slew(self,load,slew):
|
||||
""" Set the load and slew """
|
||||
self.load = load
|
||||
self.slew = slew
|
||||
|
||||
def add_graph_exclusions(self):
|
||||
"""Exclude portions of SRAM from timing graph which are not relevant"""
|
||||
#other initializations can only be done during analysis when a bit has been selected
|
||||
#for testing.
|
||||
self.sram.bank.graph_exclude_precharge()
|
||||
self.sram.graph_exclude_addr_dff()
|
||||
self.sram.graph_exclude_data_dff()
|
||||
self.sram.graph_exclude_ctrl_dffs()
|
||||
|
||||
def create_graph(self):
|
||||
"""Creates timing graph to generate the timing paths for the SRAM output."""
|
||||
self.sram.bank.bitcell_array.init_graph_params() #Removes previous bit exclusions
|
||||
self.sram.bank.bitcell_array.graph_exclude_bits(self.wordline_row, self.bitline_column)
|
||||
|
||||
#Generate new graph every analysis as edges might change depending on test bit
|
||||
self.graph = graph_util.timing_graph()
|
||||
self.sram.build_graph(self.graph,"X{}".format(self.sram.name),self.pins)
|
||||
#debug.info(1,"{}".format(graph))
|
||||
#graph.print_all_paths('clk0', 'DOUT0[0]')
|
||||
|
||||
def check_arguments(self):
|
||||
"""Checks if arguments given for write_stimulus() meets requirements"""
|
||||
try:
|
||||
|
|
@ -198,12 +213,8 @@ class delay(simulation):
|
|||
|
||||
# instantiate the sram
|
||||
self.sf.write("\n* Instantiation of the SRAM\n")
|
||||
self.stim.inst_sram(sram=self.sram,
|
||||
port_signal_names=(self.addr_name,self.din_name,self.dout_name),
|
||||
port_info=(len(self.all_ports),self.write_ports,self.read_ports),
|
||||
abits=self.addr_size,
|
||||
dbits=self.word_size,
|
||||
sram_name=self.name)
|
||||
self.stim.inst_model(pins=self.pins,
|
||||
model_name=self.sram.name)
|
||||
self.sf.write("\n* SRAM output loads\n")
|
||||
for port in self.read_ports:
|
||||
for i in range(self.word_size):
|
||||
|
|
@ -812,7 +823,7 @@ class delay(simulation):
|
|||
char_sram_data = {}
|
||||
|
||||
self.set_probe(probe_address, probe_data)
|
||||
self.create_signal_names()
|
||||
self.create_graph()
|
||||
self.create_measurement_names()
|
||||
self.create_measurement_objects()
|
||||
|
||||
|
|
@ -998,7 +1009,6 @@ class delay(simulation):
|
|||
"""
|
||||
if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0:
|
||||
debug.warning("Analytical characterization results are not supported for multiport.")
|
||||
self.create_signal_names()
|
||||
self.create_measurement_names()
|
||||
power = self.analytical_power(slews, loads)
|
||||
port_data = self.get_empty_measure_data_dict()
|
||||
|
|
|
|||
|
|
@ -194,12 +194,7 @@ class functional(simulation):
|
|||
new_value = "0" + new_value
|
||||
|
||||
#print("Binary Conversion: {} to {}".format(value, new_value))
|
||||
return new_value
|
||||
|
||||
def create_signal_names(self):
|
||||
self.addr_name = "A"
|
||||
self.din_name = "DIN"
|
||||
self.dout_name = "DOUT"
|
||||
return new_value
|
||||
|
||||
def write_functional_stimulus(self):
|
||||
""" Writes SPICE stimulus. """
|
||||
|
|
@ -219,12 +214,8 @@ class functional(simulation):
|
|||
|
||||
#Instantiate the SRAM
|
||||
self.sf.write("\n* Instantiation of the SRAM\n")
|
||||
self.stim.inst_sram(sram=self.sram,
|
||||
port_signal_names=(self.addr_name,self.din_name,self.dout_name),
|
||||
port_info=(len(self.all_ports), self.write_ports, self.read_ports),
|
||||
abits=self.addr_size,
|
||||
dbits=self.word_size,
|
||||
sram_name=self.name)
|
||||
self.stim.inst_model(pins=self.pins,
|
||||
model_name=self.sram.name)
|
||||
|
||||
# Add load capacitance to each of the read ports
|
||||
self.sf.write("\n* SRAM output loads\n")
|
||||
|
|
|
|||
|
|
@ -42,6 +42,19 @@ class simulation():
|
|||
self.v_low = tech.spice["v_threshold_typical"]
|
||||
self.gnd_voltage = 0
|
||||
|
||||
def create_signal_names(self):
|
||||
self.addr_name = "A"
|
||||
self.din_name = "DIN"
|
||||
self.dout_name = "DOUT"
|
||||
self.pins = self.gen_pin_names(port_signal_names=(self.addr_name,self.din_name,self.dout_name),
|
||||
port_info=(len(self.all_ports),self.write_ports,self.read_ports),
|
||||
abits=self.addr_size,
|
||||
dbits=self.word_size)
|
||||
debug.check(len(self.sram.pins) == len(self.pins), "Number of pins generated for characterization \
|
||||
do match pins of SRAM\nsram.pins = {0}\npin_names = {1}".format(self.sram.pins,self.pins))
|
||||
#This is TODO once multiport control has been finalized.
|
||||
#self.control_name = "CSB"
|
||||
|
||||
def set_stimulus_variables(self):
|
||||
# Clock signals
|
||||
self.cycle_times = []
|
||||
|
|
@ -223,3 +236,38 @@ class simulation():
|
|||
t_current+self.period)
|
||||
return comment
|
||||
|
||||
def gen_pin_names(self, port_signal_names, port_info, abits, dbits):
|
||||
"""Creates the pins names of the SRAM based on the no. of ports."""
|
||||
#This may seem redundant as the pin names are already defined in the sram. However, it is difficult
|
||||
#to extract the functionality from the names, so they are recreated. As the order is static, changing
|
||||
#the order of the pin names will cause issues here.
|
||||
pin_names = []
|
||||
(addr_name, din_name, dout_name) = port_signal_names
|
||||
(total_ports, write_index, read_index) = port_info
|
||||
|
||||
for write_input in write_index:
|
||||
for i in range(dbits):
|
||||
pin_names.append("{0}{1}_{2}".format(din_name,write_input, i))
|
||||
|
||||
for port in range(total_ports):
|
||||
for i in range(abits):
|
||||
pin_names.append("{0}{1}_{2}".format(addr_name,port,i))
|
||||
|
||||
#Control signals not finalized.
|
||||
for port in range(total_ports):
|
||||
pin_names.append("CSB{0}".format(port))
|
||||
for port in range(total_ports):
|
||||
if (port in read_index) and (port in write_index):
|
||||
pin_names.append("WEB{0}".format(port))
|
||||
|
||||
for port in range(total_ports):
|
||||
pin_names.append("{0}{1}".format(tech.spice["clk"], port))
|
||||
|
||||
for read_output in read_index:
|
||||
for i in range(dbits):
|
||||
pin_names.append("{0}{1}_{2}".format(dout_name,read_output, i))
|
||||
|
||||
pin_names.append("{0}".format(tech.spice["vdd_name"]))
|
||||
pin_names.append("{0}".format(tech.spice["gnd_name"]))
|
||||
return pin_names
|
||||
|
||||
|
|
|
|||
|
|
@ -29,51 +29,15 @@ class stimuli():
|
|||
(self.process, self.voltage, self.temperature) = corner
|
||||
self.device_models = tech.spice["fet_models"][self.process]
|
||||
|
||||
def inst_sram(self, sram, port_signal_names, port_info, abits, dbits, sram_name):
|
||||
self.sram_name = "Xsram"
|
||||
|
||||
def inst_sram(self, pins, inst_name):
|
||||
""" Function to instatiate an SRAM subckt. """
|
||||
pin_names = self.gen_pin_names(port_signal_names, port_info, abits, dbits)
|
||||
#Only checking length. This should check functionality as well (TODO) and/or import that information from the SRAM
|
||||
debug.check(len(sram.pins) == len(pin_names), "Number of pins generated for characterization do match pins of SRAM\nsram.pins = {0}\npin_names = {1}".format(sram.pins,pin_names))
|
||||
|
||||
self.sf.write("Xsram ")
|
||||
for pin in pin_names:
|
||||
|
||||
self.sf.write("{} ".format(self.sram_name))
|
||||
for pin in self.sram_pins:
|
||||
self.sf.write("{0} ".format(pin))
|
||||
self.sf.write("{0}\n".format(sram_name))
|
||||
|
||||
def gen_pin_names(self, port_signal_names, port_info, abits, dbits):
|
||||
"""Creates the pins names of the SRAM based on the no. of ports."""
|
||||
#This may seem redundant as the pin names are already defined in the sram. However, it is difficult to extract the
|
||||
#functionality from the names, so they are recreated. As the order is static, changing the order of the pin names
|
||||
#will cause issues here.
|
||||
pin_names = []
|
||||
(addr_name, din_name, dout_name) = port_signal_names
|
||||
(total_ports, write_index, read_index) = port_info
|
||||
|
||||
for write_input in write_index:
|
||||
for i in range(dbits):
|
||||
pin_names.append("{0}{1}_{2}".format(din_name,write_input, i))
|
||||
|
||||
for port in range(total_ports):
|
||||
for i in range(abits):
|
||||
pin_names.append("{0}{1}_{2}".format(addr_name,port,i))
|
||||
|
||||
#Control signals not finalized.
|
||||
for port in range(total_ports):
|
||||
pin_names.append("CSB{0}".format(port))
|
||||
for port in range(total_ports):
|
||||
if (port in read_index) and (port in write_index):
|
||||
pin_names.append("WEB{0}".format(port))
|
||||
|
||||
for port in range(total_ports):
|
||||
pin_names.append("{0}{1}".format(tech.spice["clk"], port))
|
||||
|
||||
for read_output in read_index:
|
||||
for i in range(dbits):
|
||||
pin_names.append("{0}{1}_{2}".format(dout_name,read_output, i))
|
||||
|
||||
pin_names.append("{0}".format(self.vdd_name))
|
||||
pin_names.append("{0}".format(self.gnd_name))
|
||||
return pin_names
|
||||
self.sf.write("{0}\n".format(inst_name))
|
||||
|
||||
def inst_model(self, pins, model_name):
|
||||
""" Function to instantiate a generic model with a set of pins """
|
||||
|
|
|
|||
|
|
@ -26,26 +26,26 @@ class timing_sram_test(openram_test):
|
|||
reload(characterizer)
|
||||
from characterizer import delay
|
||||
from sram_config import sram_config
|
||||
# c = sram_config(word_size=1,
|
||||
# num_words=16,
|
||||
# num_banks=1)
|
||||
# c.words_per_row=1
|
||||
c = sram_config(word_size=32,
|
||||
num_words=256,
|
||||
c = sram_config(word_size=1,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
c.words_per_row=2
|
||||
OPTS.use_tech_delay_chain_size = True
|
||||
c.words_per_row=1
|
||||
# c = sram_config(word_size=32,
|
||||
# num_words=256,
|
||||
# num_banks=1)
|
||||
# c.words_per_row=2
|
||||
#OPTS.use_tech_delay_chain_size = True
|
||||
c.recompute_sizes()
|
||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
|
||||
#Exclude things known not to be in critical path.
|
||||
#Intended for characterizing read paths. Somewhat hacky implementation
|
||||
s.s.bank.bitcell_array.graph_exclude_bits(15,0)
|
||||
s.s.bank.graph_exclude_precharge()
|
||||
s.s.graph_exclude_addr_dff()
|
||||
s.s.graph_exclude_data_dff()
|
||||
s.s.graph_exclude_ctrl_dffs()
|
||||
# s.s.bank.bitcell_array.graph_exclude_bits(15,0)
|
||||
# s.s.bank.graph_exclude_precharge()
|
||||
# s.s.graph_exclude_addr_dff()
|
||||
# s.s.graph_exclude_data_dff()
|
||||
# s.s.graph_exclude_ctrl_dffs()
|
||||
|
||||
# debug.info(1,'pins={}'.format(s.s.pins))
|
||||
# import graph_util
|
||||
|
|
|
|||
Loading…
Reference in New Issue