mirror of https://github.com/VLSIDA/OpenRAM.git
Cleaned up control logic cycle creation in delay.py. Fixed bug which caused input data to be determined by the read ports.
This commit is contained in:
parent
da6843af5b
commit
91bbc556e8
|
|
@ -64,8 +64,6 @@ class delay():
|
||||||
debug.error("Given probe_data is not an integer to specify a data bit",1)
|
debug.error("Given probe_data is not an integer to specify a data bit",1)
|
||||||
|
|
||||||
#Adding port options here which the characterizer cannot handle. Some may be added later like ROM
|
#Adding port options here which the characterizer cannot handle. Some may be added later like ROM
|
||||||
if len(self.targ_write_ports) == 0 and len(self.targ_read_ports) == 0:
|
|
||||||
debug.error("No ports selected for characterization.",1)
|
|
||||||
if len(self.read_ports) == 0:
|
if len(self.read_ports) == 0:
|
||||||
debug.error("Characterizer does not currently support SRAMs without read ports.",1)
|
debug.error("Characterizer does not currently support SRAMs without read ports.",1)
|
||||||
if len(self.write_ports) == 0:
|
if len(self.write_ports) == 0:
|
||||||
|
|
@ -453,10 +451,6 @@ class delay():
|
||||||
This simulates a disabled SRAM to get the leakage power when it is off.
|
This simulates a disabled SRAM to get the leakage power when it is off.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
#Select any available port. Does not need to be specified for leakage power.
|
|
||||||
#Doing this just passes a debug check and nothing else. Put on TODO to remove...
|
|
||||||
self.targ_read_ports = [self.get_available_port(get_read_port=True)]
|
|
||||||
|
|
||||||
debug.info(1, "Performing leakage power simulations.")
|
debug.info(1, "Performing leakage power simulations.")
|
||||||
self.write_power_stimulus(trim=False)
|
self.write_power_stimulus(trim=False)
|
||||||
self.stim.run_sim()
|
self.stim.run_sim()
|
||||||
|
|
@ -658,16 +652,16 @@ class delay():
|
||||||
# sys.exit(1)
|
# sys.exit(1)
|
||||||
|
|
||||||
#For debugging, skips characterization and returns dummy values.
|
#For debugging, skips characterization and returns dummy values.
|
||||||
char_data = self.char_data
|
# char_data = self.char_data
|
||||||
i = 1.0
|
# i = 1.0
|
||||||
for slew in slews:
|
# for slew in slews:
|
||||||
for load in loads:
|
# for load in loads:
|
||||||
for k,v in char_data.items():
|
# for k,v in char_data.items():
|
||||||
char_data[k].append(i)
|
# char_data[k].append(i)
|
||||||
i+=1.0
|
# i+=1.0
|
||||||
char_data["min_period"] = i
|
# char_data["min_period"] = i
|
||||||
char_data["leakage_power"] = i+1.0
|
# char_data["leakage_power"] = i+1.0
|
||||||
return char_data
|
# return char_data
|
||||||
|
|
||||||
# 1) Find a feasible period and it's corresponding delays using the trimmed array.
|
# 1) Find a feasible period and it's corresponding delays using the trimmed array.
|
||||||
(feasible_delays_lh, feasible_delays_hl) = self.find_feasible_period()
|
(feasible_delays_lh, feasible_delays_hl) = self.find_feasible_period()
|
||||||
|
|
@ -743,11 +737,7 @@ class delay():
|
||||||
def add_noop_one_port(self, address, data, port):
|
def add_noop_one_port(self, address, data, port):
|
||||||
""" Add the control values for a noop to a single port. """
|
""" Add the control values for a noop to a single port. """
|
||||||
#This is to be used as a helper function for the other add functions. Cycle and comments are omitted.
|
#This is to be used as a helper function for the other add functions. Cycle and comments are omitted.
|
||||||
self.csb_values[port].append(1)
|
self.add_control_one_port(port, "noop")
|
||||||
#If port is in both lists, add rw control signal. Condition indicates its a RW port.
|
|
||||||
if port < len(self.web_values):
|
|
||||||
self.web_values[port].append(1)
|
|
||||||
|
|
||||||
if port in self.write_ports:
|
if port in self.write_ports:
|
||||||
self.add_data(data,port)
|
self.add_data(data,port)
|
||||||
self.add_address(address, port)
|
self.add_address(address, port)
|
||||||
|
|
@ -773,10 +763,7 @@ class delay():
|
||||||
port))
|
port))
|
||||||
self.cycle_times.append(self.t_current)
|
self.cycle_times.append(self.t_current)
|
||||||
self.t_current += self.period
|
self.t_current += self.period
|
||||||
self.csb_values[port].append(0)
|
self.add_control_one_port(port, "read")
|
||||||
#If port is in both lists, add rw control signal. Condition indicates its a RW port.
|
|
||||||
if port < len(self.web_values):
|
|
||||||
self.web_values[port].append(1)
|
|
||||||
|
|
||||||
#If the port is also a readwrite then add data.
|
#If the port is also a readwrite then add data.
|
||||||
if port in self.write_ports:
|
if port in self.write_ports:
|
||||||
|
|
@ -799,11 +786,8 @@ class delay():
|
||||||
port))
|
port))
|
||||||
self.cycle_times.append(self.t_current)
|
self.cycle_times.append(self.t_current)
|
||||||
self.t_current += self.period
|
self.t_current += self.period
|
||||||
self.csb_values[port].append(0)
|
|
||||||
#If port is in both lists, add rw control signal. Condition indicates its a RW port.
|
|
||||||
if port < len(self.web_values):
|
|
||||||
self.web_values[port].append(0)
|
|
||||||
|
|
||||||
|
self.add_control_one_port(port, "write")
|
||||||
self.add_data(data,port)
|
self.add_data(data,port)
|
||||||
self.add_address(address,port)
|
self.add_address(address,port)
|
||||||
|
|
||||||
|
|
@ -814,6 +798,25 @@ class delay():
|
||||||
if unselected_port != port:
|
if unselected_port != port:
|
||||||
self.add_noop_one_port(address, noop_data, unselected_port)
|
self.add_noop_one_port(address, noop_data, unselected_port)
|
||||||
|
|
||||||
|
def add_control_one_port(self, port, op):
|
||||||
|
"""Appends control signals for operation to a given port"""
|
||||||
|
#Determine values to write to port
|
||||||
|
web_val = 1
|
||||||
|
csb_val = 1
|
||||||
|
if op == "read":
|
||||||
|
csb_val = 0
|
||||||
|
elif op == "write":
|
||||||
|
csb_val = 0
|
||||||
|
web_val = 0
|
||||||
|
elif op != "noop":
|
||||||
|
debug.error("Could not add control signals for port {0}. Command {1} not recognized".format(port,op),1)
|
||||||
|
|
||||||
|
#Append the values depending on the type of port
|
||||||
|
self.csb_values[port].append(csb_val)
|
||||||
|
#If port is in both lists, add rw control signal. Condition indicates its a RW port.
|
||||||
|
if port < len(self.web_values):
|
||||||
|
self.web_values[port].append(web_val)
|
||||||
|
|
||||||
def gen_test_cycles_one_port(self, read_port, write_port):
|
def gen_test_cycles_one_port(self, read_port, write_port):
|
||||||
"""Intended but not implemented: Returns a list of key time-points [ns] of the waveform (each rising edge)
|
"""Intended but not implemented: Returns a list of key time-points [ns] of the waveform (each rising edge)
|
||||||
of the cycles to do a timing evaluation of a single port. Current: Values overwritten for multiple calls"""
|
of the cycles to do a timing evaluation of a single port. Current: Values overwritten for multiple calls"""
|
||||||
|
|
@ -890,6 +893,9 @@ class delay():
|
||||||
"""Returns a list of key time-points [ns] of the waveform (each rising edge)
|
"""Returns a list of key time-points [ns] of the waveform (each rising edge)
|
||||||
of the cycles to do a timing evaluation. The last time is the end of the simulation
|
of the cycles to do a timing evaluation. The last time is the end of the simulation
|
||||||
and does not need a rising edge."""
|
and does not need a rising edge."""
|
||||||
|
#Using this requires setting at least one port to target for simulation.
|
||||||
|
if len(self.targ_write_ports) == 0 and len(self.targ_read_ports) == 0:
|
||||||
|
debug.error("No ports selected for characterization.",1)
|
||||||
|
|
||||||
# Start at time 0
|
# Start at time 0
|
||||||
self.t_current = 0
|
self.t_current = 0
|
||||||
|
|
@ -906,7 +912,7 @@ class delay():
|
||||||
self.csb_values = [[] for i in range(self.total_port_num)]
|
self.csb_values = [[] for i in range(self.total_port_num)]
|
||||||
|
|
||||||
# Address and data values for each address/data bit. A dict of 3d lists of size #ports x bits x cycles.
|
# Address and data values for each address/data bit. A dict of 3d lists of size #ports x bits x cycles.
|
||||||
self.data_values=[[[] for i in range(self.addr_size)]]*len(self.read_ports)
|
self.data_values=[[[] for i in range(self.addr_size)]]*len(self.write_ports)
|
||||||
self.addr_values=[[[] for i in range(self.addr_size)]]*self.total_port_num
|
self.addr_values=[[[] for i in range(self.addr_size)]]*self.total_port_num
|
||||||
|
|
||||||
#Get any available read/write port in case only a single write or read ports is being characterized.
|
#Get any available read/write port in case only a single write or read ports is being characterized.
|
||||||
|
|
@ -978,10 +984,10 @@ class delay():
|
||||||
|
|
||||||
def gen_data(self):
|
def gen_data(self):
|
||||||
""" Generates the PWL data inputs for a simulation timing test. """
|
""" Generates the PWL data inputs for a simulation timing test. """
|
||||||
for read_port in self.read_ports:
|
for write_port in self.write_ports:
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
sig_name="DIN{0}[{1}] ".format(read_port, i)
|
sig_name="DIN{0}[{1}] ".format(write_port, i)
|
||||||
self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[read_port][i], self.period, self.slew, 0.05)
|
self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[write_port][i], self.period, self.slew, 0.05)
|
||||||
|
|
||||||
def gen_addr(self):
|
def gen_addr(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -1016,11 +1022,10 @@ class delay():
|
||||||
self.read_ports.append(readwrite_port_num)
|
self.read_ports.append(readwrite_port_num)
|
||||||
self.write_ports.append(readwrite_port_num)
|
self.write_ports.append(readwrite_port_num)
|
||||||
#This placement is intentional. It makes indexing input data easier. See self.data_values
|
#This placement is intentional. It makes indexing input data easier. See self.data_values
|
||||||
for read_port_num in range(OPTS.num_rw_ports, OPTS.num_r_ports):
|
for write_port_num in range(OPTS.num_rw_ports, OPTS.num_rw_ports+OPTS.num_w_ports):
|
||||||
self.read_ports.append(read_port_num)
|
|
||||||
for write_port_num in range(OPTS.num_rw_ports+OPTS.num_r_ports, OPTS.num_w_ports):
|
|
||||||
self.write_ports.append(write_port_num)
|
self.write_ports.append(write_port_num)
|
||||||
|
for read_port_num in range(OPTS.num_rw_ports+OPTS.num_w_ports, OPTS.num_rw_ports+OPTS.num_w_ports+OPTS.num_r_ports):
|
||||||
|
self.read_ports.append(read_port_num)
|
||||||
|
|
||||||
#Set the default target ports for simulation. Default is all the ports.
|
#Set the default target ports for simulation. Default is all the ports.
|
||||||
self.targ_read_ports = self.read_ports
|
self.targ_read_ports = self.read_ports
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class lib:
|
||||||
|
|
||||||
def __init__(self, out_dir, sram, sp_file, use_model=OPTS.analytical_delay):
|
def __init__(self, out_dir, sram, sp_file, use_model=OPTS.analytical_delay):
|
||||||
#Temporary Workaround to here to set num of ports. Crashes if set in config file.
|
#Temporary Workaround to here to set num of ports. Crashes if set in config file.
|
||||||
OPTS.num_rw_ports = 2
|
#OPTS.num_rw_ports = 2
|
||||||
#OPTS.num_r_ports = 1
|
#OPTS.num_r_ports = 1
|
||||||
#OPTS.num_w_ports = 1
|
#OPTS.num_w_ports = 1
|
||||||
|
|
||||||
|
|
@ -424,7 +424,7 @@ class lib:
|
||||||
self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
|
self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
|
||||||
|
|
||||||
#Add power values for the ports. lib generated with this is not syntactically correct. TODO once
|
#Add power values for the ports. lib generated with this is not syntactically correct. TODO once
|
||||||
#top level is done
|
#top level is done.
|
||||||
for port in range(self.total_port_num):
|
for port in range(self.total_port_num):
|
||||||
self.add_clk_control_power(port)
|
self.add_clk_control_power(port)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -278,21 +278,21 @@ class setup_hold():
|
||||||
HL_hold = []
|
HL_hold = []
|
||||||
|
|
||||||
#For debugging, skips characterization and returns dummy values.
|
#For debugging, skips characterization and returns dummy values.
|
||||||
i = 1.0
|
# i = 1.0
|
||||||
for self.related_input_slew in related_slews:
|
# for self.related_input_slew in related_slews:
|
||||||
for self.constrained_input_slew in constrained_slews:
|
# for self.constrained_input_slew in constrained_slews:
|
||||||
LH_setup.append(i)
|
# LH_setup.append(i)
|
||||||
HL_setup.append(i+1.0)
|
# HL_setup.append(i+1.0)
|
||||||
LH_hold.append(i+2.0)
|
# LH_hold.append(i+2.0)
|
||||||
HL_hold.append(i+3.0)
|
# HL_hold.append(i+3.0)
|
||||||
i+=4.0
|
# i+=4.0
|
||||||
|
|
||||||
times = {"setup_times_LH": LH_setup,
|
# times = {"setup_times_LH": LH_setup,
|
||||||
"setup_times_HL": HL_setup,
|
# "setup_times_HL": HL_setup,
|
||||||
"hold_times_LH": LH_hold,
|
# "hold_times_LH": LH_hold,
|
||||||
"hold_times_HL": HL_hold
|
# "hold_times_HL": HL_hold
|
||||||
}
|
# }
|
||||||
return times
|
# return times
|
||||||
|
|
||||||
|
|
||||||
for self.related_input_slew in related_slews:
|
for self.related_input_slew in related_slews:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue