Removed windows EOL characters.

This commit is contained in:
Hunter Nichols 2021-08-04 16:09:04 -07:00
parent b44f840814
commit 134bf573ec
2 changed files with 231 additions and 220 deletions

View File

@ -1,120 +1,124 @@
# See LICENSE for licensing information. # See LICENSE for licensing information.
# #
# Copyright (c) 2016-2019 Regents of the University of California and The Board # Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College # of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
from .simulation import simulation from .simulation import simulation
from globals import OPTS from globals import OPTS
import debug import debug
import tech import tech
import math import math
class cacti(simulation): class cacti(simulation):
""" """
Delay model for the SRAM which which Delay model for the SRAM which which
""" """
def __init__(self, sram, spfile, corner): def __init__(self, sram, spfile, corner):
super().__init__(sram, spfile, corner) super().__init__(sram, spfile, corner)
# self.targ_read_ports = [] # self.targ_read_ports = []
# self.targ_write_ports = [] # self.targ_write_ports = []
# self.period = 0 # self.period = 0
# if self.write_size: # if self.write_size:
# self.num_wmasks = int(math.ceil(self.word_size / self.write_size)) # self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
# else: # else:
# self.num_wmasks = 0 # self.num_wmasks = 0
#self.set_load_slew(0, 0) #self.set_load_slew(0, 0)
self.set_corner(corner) self.set_corner(corner)
self.create_signal_names() self.create_signal_names()
self.add_graph_exclusions() self.add_graph_exclusions()
self.set_params() self.set_params()
def set_params(self): def set_params(self):
"""Set parameters specific to the corner being simulated""" """Set parameters specific to the corner being simulated"""
self.params = {} self.params = {}
# Set the specific functions to use for timing defined in the SRAM module # Set the specific functions to use for timing defined in the SRAM module
self.params["model_name"] = OPTS.model_name self.params["model_name"] = OPTS.model_name
# Only parameter right now is r_on which is dependent on Vdd # Only parameter right now is r_on which is dependent on Vdd
self.params["r_nch_on"] = self.vdd_voltage / tech.spice["i_on_n"] self.params["r_nch_on"] = self.vdd_voltage / tech.spice["i_on_n"]
self.params["r_pch_on"] = self.vdd_voltage / tech.spice["i_on_p"] self.params["r_pch_on"] = self.vdd_voltage / tech.spice["i_on_p"]
def get_lib_values(self, load_slews): def get_lib_values(self, load_slews):
""" """
Return the analytical model results for the SRAM. Return the analytical model results for the SRAM.
""" """
if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0: if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0:
debug.warning("In analytical mode, all ports have the timing of the first read port.") debug.warning("In analytical mode, all ports have the timing of the first read port.")
# Probe set to 0th bit, does not matter for analytical delay. # Probe set to 0th bit, does not matter for analytical delay.
self.set_probe('0' * self.addr_size, 0) self.set_probe('0' * self.addr_size, 0)
self.create_graph() self.create_graph()
self.set_internal_spice_names() self.set_internal_spice_names()
self.create_measurement_names() self.create_measurement_names()
port = self.read_ports[0] port = self.read_ports[0]
self.graph.get_all_paths('{}{}'.format("clk", port), self.graph.get_all_paths('{}{}'.format("clk", port),
'{}{}_{}'.format(self.dout_name, port, self.probe_data)) '{}{}_{}'.format(self.dout_name, port, self.probe_data))
# Select the path with the bitline (bl) # Select the path with the bitline (bl)
bl_name, br_name = self.get_bl_name(self.graph.all_paths, port) bl_name, br_name = self.get_bl_name(self.graph.all_paths, port)
bl_path = [path for path in self.graph.all_paths if bl_name in path][0] bl_path = [path for path in self.graph.all_paths if bl_name in path][0]
# Set delay/power for slews and loads # Set delay/power for slews and loads
port_data = self.get_empty_measure_data_dict() port_data = self.get_empty_measure_data_dict()
power = self.analytical_power(load_slews) power = self.analytical_power(load_slews)
debug.info(1, 'Slew (ns), Load (fF), Delay(ns), Slew(ns)') debug.info(1, 'Slew (ns), Load (fF), Delay(ns), Slew(ns)')
max_delay = 0.0 max_delay = 0.0
for load,slew in load_slews: for load,slew in load_slews:
# Calculate delay based on slew and load # Calculate delay based on slew and load
# Calculations expect Farad, input is Femto-Farad # Calculations expect Farad, input is Femto-Farad
load_farad = load*1e-12 load_farad = load*1e-12
path_delays = self.graph.get_timing(bl_path, self.corner, slew, load_farad, self.params) load_farad = 0.052275e-12
slew = 0
total_delay = self.sum_delays(path_delays) path_delays = self.graph.get_timing(bl_path, self.corner, slew, load_farad, self.params)
delay_ns = total_delay.delay/1e-9
slew_ns = total_delay.slew/1e-9 total_delay = self.sum_delays(path_delays)
max_delay = max(max_delay, total_delay.delay) debug.info(0, "total_delay={}".format(total_delay))
debug.info(1,'{}, {}, {}, {}'.format(slew, sys.exit()
load, delay_ns = total_delay.delay/1e-9
delay_ns, slew_ns = total_delay.slew/1e-9
slew_ns)) max_delay = max(max_delay, total_delay.delay)
# Delay is only calculated on a single port and replicated for now. debug.info(1,'{}, {}, {}, {}'.format(slew,
for port in self.all_ports: load,
for mname in self.delay_meas_names + self.power_meas_names: delay_ns,
if "power" in mname: slew_ns))
port_data[port][mname].append(power.dynamic) # Delay is only calculated on a single port and replicated for now.
elif "delay" in mname and port in self.read_ports: for port in self.all_ports:
port_data[port][mname].append(total_delay.delay / 1e3) for mname in self.delay_meas_names + self.power_meas_names:
elif "slew" in mname and port in self.read_ports: if "power" in mname:
port_data[port][mname].append(total_delay.slew / 1e3) port_data[port][mname].append(power.dynamic)
elif "delay" in mname and port in self.read_ports:
# Margin for error in period. Calculated by averaging required margin for a small and large port_data[port][mname].append(total_delay.delay / 1e3)
# memory. FIXME: margin is quite large, should be looked into. elif "slew" in mname and port in self.read_ports:
period_margin = 1.85 port_data[port][mname].append(total_delay.slew / 1e3)
sram_data = {"min_period": (max_delay / 1e3) * 2 * period_margin,
"leakage_power": power.leakage} # Margin for error in period. Calculated by averaging required margin for a small and large
# memory. FIXME: margin is quite large, should be looked into.
debug.info(2, "SRAM Data:\n{}".format(sram_data)) period_margin = 1.85
debug.info(2, "Port Data:\n{}".format(port_data)) sram_data = {"min_period": (max_delay / 1e3) * 2 * period_margin,
"leakage_power": power.leakage}
return (sram_data, port_data)
debug.info(2, "SRAM Data:\n{}".format(sram_data))
def analytical_power(self, load_slews): debug.info(2, "Port Data:\n{}".format(port_data))
"""Get the dynamic and leakage power from the SRAM"""
return (sram_data, port_data)
# slews unused, only last load is used
load = load_slews[-1][0] def analytical_power(self, load_slews):
power = self.sram.analytical_power(self.corner, load) """Get the dynamic and leakage power from the SRAM"""
# convert from nW to mW
power.dynamic /= 1e6 # slews unused, only last load is used
power.leakage /= 1e6 load = load_slews[-1][0]
debug.info(1, "Dynamic Power: {0} mW".format(power.dynamic)) power = self.sram.analytical_power(self.corner, load)
debug.info(1, "Leakage Power: {0} mW".format(power.leakage)) # convert from nW to mW
return power power.dynamic /= 1e6
power.leakage /= 1e6
debug.info(1, "Dynamic Power: {0} mW".format(power.dynamic))
debug.info(1, "Leakage Power: {0} mW".format(power.leakage))
return power

View File

@ -1,102 +1,109 @@
# See LICENSE for licensing information. # See LICENSE for licensing information.
# #
# Copyright (c) 2016-2019 Regents of the University of California and The Board # Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College # of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
from .simulation import simulation from .simulation import simulation
from globals import OPTS from globals import OPTS
import debug import debug
class elmore(simulation): class elmore(simulation):
""" """
Delay model for the SRAM which calculates Elmore delays along the SRAM critical path. Delay model for the SRAM which calculates Elmore delays along the SRAM critical path.
""" """
def __init__(self, sram, spfile, corner): def __init__(self, sram, spfile, corner):
super().__init__(sram, spfile, corner) super().__init__(sram, spfile, corner)
# self.targ_read_ports = [] # self.targ_read_ports = []
# self.targ_write_ports = [] # self.targ_write_ports = []
# self.period = 0 # self.period = 0
# if self.write_size: # if self.write_size:
# self.num_wmasks = int(math.ceil(self.word_size / self.write_size)) # self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
# else: # else:
# self.num_wmasks = 0 # self.num_wmasks = 0
#self.set_load_slew(0, 0) #self.set_load_slew(0, 0)
self.set_corner(corner) self.set_params()
self.create_signal_names() self.set_corner(corner)
self.add_graph_exclusions() self.create_signal_names()
self.add_graph_exclusions()
def get_lib_values(self, load_slews):
""" def set_params(self):
Return the analytical model results for the SRAM. """Set parameters specific to the corner being simulated"""
""" self.params = {}
if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0: # Set the specific functions to use for timing defined in the SRAM module
debug.warning("In analytical mode, all ports have the timing of the first read port.") self.params["model_name"] = OPTS.model_name
# Probe set to 0th bit, does not matter for analytical delay. def get_lib_values(self, load_slews):
self.set_probe('0' * self.addr_size, 0) """
self.create_graph() Return the analytical model results for the SRAM.
self.set_internal_spice_names() """
self.create_measurement_names() if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0:
debug.warning("In analytical mode, all ports have the timing of the first read port.")
port = self.read_ports[0]
self.graph.get_all_paths('{}{}'.format("clk", port), # Probe set to 0th bit, does not matter for analytical delay.
'{}{}_{}'.format(self.dout_name, port, self.probe_data)) self.set_probe('0' * self.addr_size, 0)
self.create_graph()
# Select the path with the bitline (bl) self.set_internal_spice_names()
bl_name, br_name = self.get_bl_name(self.graph.all_paths, port) self.create_measurement_names()
bl_path = [path for path in self.graph.all_paths if bl_name in path][0]
port = self.read_ports[0]
# Set delay/power for slews and loads self.graph.get_all_paths('{}{}'.format("clk", port),
port_data = self.get_empty_measure_data_dict() '{}{}_{}'.format(self.dout_name, port, self.probe_data))
power = self.analytical_power(load_slews)
debug.info(1, 'Slew, Load, Delay(ns), Slew(ns)') # Select the path with the bitline (bl)
max_delay = 0.0 bl_name, br_name = self.get_bl_name(self.graph.all_paths, port)
for load,slew in load_slews: bl_path = [path for path in self.graph.all_paths if bl_name in path][0]
# Calculate delay based on slew and load
path_delays = self.graph.get_timing(bl_path, self.corner, slew, load) # Set delay/power for slews and loads
port_data = self.get_empty_measure_data_dict()
total_delay = self.sum_delays(path_delays) power = self.analytical_power(load_slews)
max_delay = max(max_delay, total_delay.delay) debug.info(1, 'Slew, Load, Delay(ns), Slew(ns)')
debug.info(1, max_delay = 0.0
'{}, {}, {}, {}'.format(slew, for load,slew in load_slews:
load, # Calculate delay based on slew and load
total_delay.delay / 1e3, path_delays = self.graph.get_timing(bl_path, self.corner, slew, load, self.params)
total_delay.slew / 1e3))
# Delay is only calculated on a single port and replicated for now. total_delay = self.sum_delays(path_delays)
for port in self.all_ports: max_delay = max(max_delay, total_delay.delay)
for mname in self.delay_meas_names + self.power_meas_names: debug.info(1,
if "power" in mname: '{}, {}, {}, {}'.format(slew,
port_data[port][mname].append(power.dynamic) load,
elif "delay" in mname and port in self.read_ports: total_delay.delay / 1e3,
port_data[port][mname].append(total_delay.delay / 1e3) total_delay.slew / 1e3))
elif "slew" in mname and port in self.read_ports: # Delay is only calculated on a single port and replicated for now.
port_data[port][mname].append(total_delay.slew / 1e3) for port in self.all_ports:
for mname in self.delay_meas_names + self.power_meas_names:
# Margin for error in period. Calculated by averaging required margin for a small and large if "power" in mname:
# memory. FIXME: margin is quite large, should be looked into. port_data[port][mname].append(power.dynamic)
period_margin = 1.85 elif "delay" in mname and port in self.read_ports:
sram_data = {"min_period": (max_delay / 1e3) * 2 * period_margin, port_data[port][mname].append(total_delay.delay / 1e3)
"leakage_power": power.leakage} elif "slew" in mname and port in self.read_ports:
port_data[port][mname].append(total_delay.slew / 1e3)
debug.info(2, "SRAM Data:\n{}".format(sram_data))
debug.info(2, "Port Data:\n{}".format(port_data)) # Margin for error in period. Calculated by averaging required margin for a small and large
# memory. FIXME: margin is quite large, should be looked into.
return (sram_data, port_data) period_margin = 1.85
sram_data = {"min_period": (max_delay / 1e3) * 2 * period_margin,
def analytical_power(self, load_slews): "leakage_power": power.leakage}
"""Get the dynamic and leakage power from the SRAM"""
debug.info(2, "SRAM Data:\n{}".format(sram_data))
# slews unused, only last load is used debug.info(2, "Port Data:\n{}".format(port_data))
load = load_slews[-1][0]
power = self.sram.analytical_power(self.corner, load) return (sram_data, port_data)
# convert from nW to mW
power.dynamic /= 1e6 def analytical_power(self, load_slews):
power.leakage /= 1e6 """Get the dynamic and leakage power from the SRAM"""
debug.info(1, "Dynamic Power: {0} mW".format(power.dynamic))
debug.info(1, "Leakage Power: {0} mW".format(power.leakage)) # slews unused, only last load is used
load = load_slews[-1][0]
power = self.sram.analytical_power(self.corner, load)
# convert from nW to mW
power.dynamic /= 1e6
power.leakage /= 1e6
debug.info(1, "Dynamic Power: {0} mW".format(power.dynamic))
debug.info(1, "Leakage Power: {0} mW".format(power.leakage))
return power return power