mirror of https://github.com/VLSIDA/OpenRAM.git
Merge remote-tracking branch 'public/dev' into dev
This commit is contained in:
commit
4d6d6af0a1
|
|
@ -8,3 +8,5 @@
|
||||||
*.toc
|
*.toc
|
||||||
*.synctex.gz
|
*.synctex.gz
|
||||||
**/model_data
|
**/model_data
|
||||||
|
outputs
|
||||||
|
technology/freepdk45/ncsu_basekit
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ class delay(simulation):
|
||||||
""" Create measurement names. The names themselves currently define the type of measurement """
|
""" Create measurement names. The names themselves currently define the type of measurement """
|
||||||
|
|
||||||
self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"]
|
self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"]
|
||||||
self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power"]
|
self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power",
|
||||||
|
"disabled_read0_power", "disabled_read1_power", "disabled_write0_power", "disabled_write1_power"]
|
||||||
# self.voltage_when_names = ["volt_bl", "volt_br"]
|
# self.voltage_when_names = ["volt_bl", "volt_br"]
|
||||||
# self.bitline_delay_names = ["delay_bl", "delay_br"]
|
# self.bitline_delay_names = ["delay_bl", "delay_br"]
|
||||||
|
|
||||||
|
|
@ -108,6 +109,11 @@ class delay(simulation):
|
||||||
self.read_lib_meas.append(power_measure("read0_power", "FALL", measure_scale=1e3))
|
self.read_lib_meas.append(power_measure("read0_power", "FALL", measure_scale=1e3))
|
||||||
self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO
|
self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO
|
||||||
|
|
||||||
|
self.read_lib_meas.append(power_measure("disabled_read1_power", "RISE", measure_scale=1e3))
|
||||||
|
self.read_lib_meas[-1].meta_str = "disabled_read1"
|
||||||
|
self.read_lib_meas.append(power_measure("disabled_read0_power", "FALL", measure_scale=1e3))
|
||||||
|
self.read_lib_meas[-1].meta_str = "disabled_read0"
|
||||||
|
|
||||||
# This will later add a half-period to the spice time delay. Only for reading 0.
|
# This will later add a half-period to the spice time delay. Only for reading 0.
|
||||||
for obj in self.read_lib_meas:
|
for obj in self.read_lib_meas:
|
||||||
if obj.meta_str is sram_op.READ_ZERO:
|
if obj.meta_str is sram_op.READ_ZERO:
|
||||||
|
|
@ -156,6 +162,11 @@ class delay(simulation):
|
||||||
self.write_lib_meas.append(power_measure("write0_power", "FALL", measure_scale=1e3))
|
self.write_lib_meas.append(power_measure("write0_power", "FALL", measure_scale=1e3))
|
||||||
self.write_lib_meas[-1].meta_str = sram_op.WRITE_ZERO
|
self.write_lib_meas[-1].meta_str = sram_op.WRITE_ZERO
|
||||||
|
|
||||||
|
self.write_lib_meas.append(power_measure("disabled_write1_power", "RISE", measure_scale=1e3))
|
||||||
|
self.write_lib_meas[-1].meta_str = "disabled_write1"
|
||||||
|
self.write_lib_meas.append(power_measure("disabled_write0_power", "FALL", measure_scale=1e3))
|
||||||
|
self.write_lib_meas[-1].meta_str = "disabled_write0"
|
||||||
|
|
||||||
write_measures = []
|
write_measures = []
|
||||||
write_measures.append(self.write_lib_meas)
|
write_measures.append(self.write_lib_meas)
|
||||||
write_measures.append(self.create_write_bit_measures())
|
write_measures.append(self.create_write_bit_measures())
|
||||||
|
|
@ -1198,6 +1209,9 @@ class delay(simulation):
|
||||||
write_port)
|
write_port)
|
||||||
self.measure_cycles[write_port][sram_op.WRITE_ZERO] = len(self.cycle_times)-1
|
self.measure_cycles[write_port][sram_op.WRITE_ZERO] = len(self.cycle_times)-1
|
||||||
|
|
||||||
|
self.add_noop_clock_one_port(write_port)
|
||||||
|
self.measure_cycles[write_port]["disabled_write0"] = len(self.cycle_times)-1
|
||||||
|
|
||||||
# This also ensures we will have a H->L transition on the next read
|
# This also ensures we will have a H->L transition on the next read
|
||||||
self.add_read("R data 1 address {} to set dout caps".format(inverse_address),
|
self.add_read("R data 1 address {} to set dout caps".format(inverse_address),
|
||||||
inverse_address,
|
inverse_address,
|
||||||
|
|
@ -1208,6 +1222,10 @@ class delay(simulation):
|
||||||
read_port)
|
read_port)
|
||||||
self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1
|
self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1
|
||||||
|
|
||||||
|
self.add_noop_clock_one_port(read_port)
|
||||||
|
self.measure_cycles[read_port]["disabled_read0"] = len(self.cycle_times) - 1
|
||||||
|
|
||||||
|
|
||||||
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)")
|
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)")
|
||||||
|
|
||||||
self.add_write("W data 1 address {} to write value".format(self.probe_address),
|
self.add_write("W data 1 address {} to write value".format(self.probe_address),
|
||||||
|
|
@ -1217,12 +1235,19 @@ class delay(simulation):
|
||||||
write_port)
|
write_port)
|
||||||
self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1
|
self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1
|
||||||
|
|
||||||
|
self.add_noop_clock_one_port(write_port)
|
||||||
|
self.measure_cycles[write_port]["disabled_write1"] = len(self.cycle_times)-1
|
||||||
|
|
||||||
self.add_write("W data 0 address {} to clear din caps".format(inverse_address),
|
self.add_write("W data 0 address {} to clear din caps".format(inverse_address),
|
||||||
inverse_address,
|
inverse_address,
|
||||||
data_zeros,
|
data_zeros,
|
||||||
wmask_ones,
|
wmask_ones,
|
||||||
write_port)
|
write_port)
|
||||||
|
|
||||||
|
self.add_noop_clock_one_port(read_port)
|
||||||
|
self.measure_cycles[read_port]["disabled_read1"] = len(self.cycle_times) - 1
|
||||||
|
|
||||||
|
|
||||||
# This also ensures we will have a L->H transition on the next read
|
# This also ensures we will have a L->H transition on the next read
|
||||||
self.add_read("R data 0 address {} to clear dout caps".format(inverse_address),
|
self.add_read("R data 0 address {} to clear dout caps".format(inverse_address),
|
||||||
inverse_address,
|
inverse_address,
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,8 @@ class lib:
|
||||||
self.lib.write(" dont_touch : true;\n")
|
self.lib.write(" dont_touch : true;\n")
|
||||||
self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height))
|
self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height))
|
||||||
|
|
||||||
|
self.write_pg_pin()
|
||||||
|
|
||||||
#Build string of all control signals.
|
#Build string of all control signals.
|
||||||
control_str = 'csb0' #assume at least 1 port
|
control_str = 'csb0' #assume at least 1 port
|
||||||
for i in range(1, self.total_port_num):
|
for i in range(1, self.total_port_num):
|
||||||
|
|
@ -188,10 +190,11 @@ class lib:
|
||||||
|
|
||||||
# Leakage is included in dynamic when macro is enabled
|
# Leakage is included in dynamic when macro is enabled
|
||||||
self.lib.write(" leakage_power () {\n")
|
self.lib.write(" leakage_power () {\n")
|
||||||
self.lib.write(" when : \"{0}\";\n".format(control_str))
|
# 'when' condition unnecessary when cs pin does not turn power to devices
|
||||||
|
# self.lib.write(" when : \"{0}\";\n".format(control_str))
|
||||||
self.lib.write(" value : {};\n".format(self.char_sram_results["leakage_power"]))
|
self.lib.write(" value : {};\n".format(self.char_sram_results["leakage_power"]))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" cell_leakage_power : {};\n".format(0))
|
self.lib.write(" cell_leakage_power : {};\n".format(self.char_sram_results["leakage_power"]))
|
||||||
|
|
||||||
|
|
||||||
def write_units(self):
|
def write_units(self):
|
||||||
|
|
@ -240,6 +243,9 @@ class lib:
|
||||||
self.lib.write(" default_max_fanout : 4.0 ;\n")
|
self.lib.write(" default_max_fanout : 4.0 ;\n")
|
||||||
self.lib.write(" default_connection_class : universal ;\n\n")
|
self.lib.write(" default_connection_class : universal ;\n\n")
|
||||||
|
|
||||||
|
self.lib.write(" voltage_map ( VDD, {} );\n".format(tech.spice["nom_supply_voltage"]))
|
||||||
|
self.lib.write(" voltage_map ( GND, 0 );\n\n")
|
||||||
|
|
||||||
def create_list(self,values):
|
def create_list(self,values):
|
||||||
""" Helper function to create quoted, line wrapped list """
|
""" Helper function to create quoted, line wrapped list """
|
||||||
list_values = ", ".join(str(v) for v in values)
|
list_values = ", ".join(str(v) for v in values)
|
||||||
|
|
@ -516,41 +522,68 @@ class lib:
|
||||||
if port in self.write_ports:
|
if port in self.write_ports:
|
||||||
if port in self.read_ports:
|
if port in self.read_ports:
|
||||||
web_name = " & !web{0}".format(port)
|
web_name = " & !web{0}".format(port)
|
||||||
avg_write_power = np.mean(self.char_port_results[port]["write1_power"] + self.char_port_results[port]["write0_power"])
|
write1_power = np.mean(self.char_port_results[port]["write1_power"])
|
||||||
|
write0_power = np.mean(self.char_port_results[port]["write0_power"])
|
||||||
self.lib.write(" internal_power(){\n")
|
self.lib.write(" internal_power(){\n")
|
||||||
self.lib.write(" when : \"!csb{0} & clk{0}{1}\"; \n".format(port, web_name))
|
self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name))
|
||||||
self.lib.write(" rise_power(scalar){\n")
|
self.lib.write(" rise_power(scalar){\n")
|
||||||
self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0))
|
self.lib.write(" values(\"{0:.6e}\");\n".format(write1_power))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" fall_power(scalar){\n")
|
self.lib.write(" fall_power(scalar){\n")
|
||||||
self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0))
|
self.lib.write(" values(\"{0:.6e}\");\n".format(write0_power))
|
||||||
|
self.lib.write(" }\n")
|
||||||
|
self.lib.write(" }\n")
|
||||||
|
|
||||||
|
# Disabled power.
|
||||||
|
disabled_write1_power = np.mean(self.char_port_results[port]["disabled_write1_power"])
|
||||||
|
disabled_write0_power = np.mean(self.char_port_results[port]["disabled_write0_power"])
|
||||||
|
self.lib.write(" internal_power(){\n")
|
||||||
|
self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name))
|
||||||
|
self.lib.write(" rise_power(scalar){\n")
|
||||||
|
self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write1_power))
|
||||||
|
self.lib.write(" }\n")
|
||||||
|
self.lib.write(" fall_power(scalar){\n")
|
||||||
|
self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write0_power))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
|
|
||||||
if port in self.read_ports:
|
if port in self.read_ports:
|
||||||
if port in self.write_ports:
|
if port in self.write_ports:
|
||||||
web_name = " & web{0}".format(port)
|
web_name = " & web{0}".format(port)
|
||||||
avg_read_power = np.mean(self.char_port_results[port]["read1_power"] + self.char_port_results[port]["read0_power"])
|
read1_power = np.mean(self.char_port_results[port]["read1_power"])
|
||||||
|
read0_power = np.mean(self.char_port_results[port]["read0_power"])
|
||||||
self.lib.write(" internal_power(){\n")
|
self.lib.write(" internal_power(){\n")
|
||||||
self.lib.write(" when : \"!csb{0} & !clk{0}{1}\"; \n".format(port, web_name))
|
self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name))
|
||||||
self.lib.write(" rise_power(scalar){\n")
|
self.lib.write(" rise_power(scalar){\n")
|
||||||
self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0))
|
self.lib.write(" values(\"{0:.6e}\");\n".format(read1_power))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" fall_power(scalar){\n")
|
self.lib.write(" fall_power(scalar){\n")
|
||||||
self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0))
|
self.lib.write(" values(\"{0:.6e}\");\n".format(read0_power))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
|
|
||||||
# Have 0 internal power when disabled, this will be represented as leakage power.
|
# Disabled power.
|
||||||
self.lib.write(" internal_power(){\n")
|
disabled_read1_power = np.mean(self.char_port_results[port]["disabled_read1_power"])
|
||||||
self.lib.write(" when : \"csb{0}\"; \n".format(port))
|
disabled_read0_power = np.mean(self.char_port_results[port]["disabled_read0_power"])
|
||||||
self.lib.write(" rise_power(scalar){\n")
|
self.lib.write(" internal_power(){\n")
|
||||||
self.lib.write(" values(\"0\");\n")
|
self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" rise_power(scalar){\n")
|
||||||
self.lib.write(" fall_power(scalar){\n")
|
self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read1_power))
|
||||||
self.lib.write(" values(\"0\");\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" fall_power(scalar){\n")
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read0_power))
|
||||||
|
self.lib.write(" }\n")
|
||||||
|
self.lib.write(" }\n")
|
||||||
|
|
||||||
|
def write_pg_pin(self):
|
||||||
|
self.lib.write(" pg_pin(vdd) {\n")
|
||||||
|
self.lib.write(" voltage_name : VDD;\n")
|
||||||
|
self.lib.write(" pg_type : primary_power;\n")
|
||||||
|
self.lib.write(" }\n\n")
|
||||||
|
self.lib.write(" pg_pin(gnd) {\n")
|
||||||
|
self.lib.write(" voltage_name : GND;\n")
|
||||||
|
self.lib.write(" pg_type : primary_ground;\n")
|
||||||
|
self.lib.write(" }\n\n")
|
||||||
|
|
||||||
def compute_delay(self):
|
def compute_delay(self):
|
||||||
"""Compute SRAM delays for current corner"""
|
"""Compute SRAM delays for current corner"""
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,23 @@ class simulation():
|
||||||
except:
|
except:
|
||||||
self.add_wmask("0"*self.num_wmasks, port)
|
self.add_wmask("0"*self.num_wmasks, port)
|
||||||
|
|
||||||
|
def add_noop_clock_one_port(self, port):
|
||||||
|
""" Add the control values for a noop to a single port. Increments the period. """
|
||||||
|
debug.info(2, 'Clock only on port {}'.format(port))
|
||||||
|
self.fn_cycle_comments.append('Clock only on port {}'.format(port))
|
||||||
|
self.append_cycle_comment(port, 'Clock only on port {}'.format(port))
|
||||||
|
|
||||||
|
self.cycle_times.append(self.t_current)
|
||||||
|
self.t_current += self.period
|
||||||
|
|
||||||
|
self.add_noop_one_port(port)
|
||||||
|
|
||||||
|
#Add noops to all other ports.
|
||||||
|
for unselected_port in self.all_ports:
|
||||||
|
if unselected_port != port:
|
||||||
|
self.add_noop_one_port(unselected_port)
|
||||||
|
|
||||||
|
|
||||||
def append_cycle_comment(self, port, comment):
|
def append_cycle_comment(self, port, comment):
|
||||||
"""Add comment to list to be printed in stimulus file"""
|
"""Add comment to list to be printed in stimulus file"""
|
||||||
#Clean up time before appending. Make spacing dynamic as well.
|
#Clean up time before appending. Make spacing dynamic as well.
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import re
|
||||||
import copy
|
import copy
|
||||||
import importlib
|
import importlib
|
||||||
|
|
||||||
VERSION = "1.1.4"
|
VERSION = "1.1.5"
|
||||||
NAME = "OpenRAM v{}".format(VERSION)
|
NAME = "OpenRAM v{}".format(VERSION)
|
||||||
USAGE = "openram.py [options] <config file>\nUse -h for help.\n"
|
USAGE = "openram.py [options] <config file>\nUse -h for help.\n"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue