mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' of https://github.com/VLSIDA/PrivateRAM into multiport
This commit is contained in:
commit
82eeb297dd
|
|
@ -40,10 +40,12 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
|
||||||
'hierarchical_predecode3x8']
|
'hierarchical_predecode3x8']
|
||||||
if name not in design.name_map:
|
if name not in design.name_map:
|
||||||
design.name_map.append(name)
|
design.name_map.append(name)
|
||||||
elif self.__class__.__name__ in ok_list:
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
debug.error("Duplicate layout reference name {0} of class {1}. GDS2 requires names be unique.".format(name,self.__class__),-1)
|
for ok_names in ok_list:
|
||||||
|
if ok_names in self.__class__.__name__:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
debug.error("Duplicate layout reference name {0} of class {1}. GDS2 requires names be unique.".format(name,self.__class__),-1)
|
||||||
|
|
||||||
def setup_drc_constants(self):
|
def setup_drc_constants(self):
|
||||||
""" These are some DRC constants used in many places in the compiler."""
|
""" These are some DRC constants used in many places in the compiler."""
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ def relative_compare(value1,value2,error_tolerance=0.001):
|
||||||
return (abs(value1 - value2) / max(value1,value2) <= error_tolerance)
|
return (abs(value1 - value2) / max(value1,value2) <= error_tolerance)
|
||||||
|
|
||||||
|
|
||||||
def parse_output(filename, key):
|
def parse_spice_list(filename, key):
|
||||||
"""Parses a hspice output.lis file for a key value"""
|
"""Parses a hspice output.lis file for a key value"""
|
||||||
if OPTS.spice_name == "xa" :
|
if OPTS.spice_name == "xa" :
|
||||||
# customsim has a different output file name
|
# customsim has a different output file name
|
||||||
|
|
@ -22,6 +22,7 @@ def parse_output(filename, key):
|
||||||
except IOError:
|
except IOError:
|
||||||
debug.error("Unable to open spice output file: {0}".format(full_filename),1)
|
debug.error("Unable to open spice output file: {0}".format(full_filename),1)
|
||||||
contents = f.read()
|
contents = f.read()
|
||||||
|
f.close()
|
||||||
# val = re.search(r"{0}\s*=\s*(-?\d+.?\d*\S*)\s+.*".format(key), contents)
|
# val = re.search(r"{0}\s*=\s*(-?\d+.?\d*\S*)\s+.*".format(key), contents)
|
||||||
val = re.search(r"{0}\s*=\s*(-?\d+.?\d*[e]?[-+]?[0-9]*\S*)\s+.*".format(key), contents)
|
val = re.search(r"{0}\s*=\s*(-?\d+.?\d*[e]?[-+]?[0-9]*\S*)\s+.*".format(key), contents)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -339,16 +339,16 @@ class delay():
|
||||||
# Checking from not data_value to data_value
|
# Checking from not data_value to data_value
|
||||||
self.write_delay_stimulus()
|
self.write_delay_stimulus()
|
||||||
self.stim.run_sim()
|
self.stim.run_sim()
|
||||||
delay_hl = parse_output("timing", "delay_hl")
|
delay_hl = parse_spice_list("timing", "delay_hl")
|
||||||
delay_lh = parse_output("timing", "delay_lh")
|
delay_lh = parse_spice_list("timing", "delay_lh")
|
||||||
slew_hl = parse_output("timing", "slew_hl")
|
slew_hl = parse_spice_list("timing", "slew_hl")
|
||||||
slew_lh = parse_output("timing", "slew_lh")
|
slew_lh = parse_spice_list("timing", "slew_lh")
|
||||||
delays = (delay_hl, delay_lh, slew_hl, slew_lh)
|
delays = (delay_hl, delay_lh, slew_hl, slew_lh)
|
||||||
|
|
||||||
read0_power=parse_output("timing", "read0_power")
|
read0_power=parse_spice_list("timing", "read0_power")
|
||||||
write0_power=parse_output("timing", "write0_power")
|
write0_power=parse_spice_list("timing", "write0_power")
|
||||||
read1_power=parse_output("timing", "read1_power")
|
read1_power=parse_spice_list("timing", "read1_power")
|
||||||
write1_power=parse_output("timing", "write1_power")
|
write1_power=parse_spice_list("timing", "write1_power")
|
||||||
|
|
||||||
if not self.check_valid_delays(delays):
|
if not self.check_valid_delays(delays):
|
||||||
return (False,{})
|
return (False,{})
|
||||||
|
|
@ -378,13 +378,13 @@ class delay():
|
||||||
|
|
||||||
self.write_power_stimulus(trim=False)
|
self.write_power_stimulus(trim=False)
|
||||||
self.stim.run_sim()
|
self.stim.run_sim()
|
||||||
leakage_power=parse_output("timing", "leakage_power")
|
leakage_power=parse_spice_list("timing", "leakage_power")
|
||||||
debug.check(leakage_power!="Failed","Could not measure leakage power.")
|
debug.check(leakage_power!="Failed","Could not measure leakage power.")
|
||||||
|
|
||||||
|
|
||||||
self.write_power_stimulus(trim=True)
|
self.write_power_stimulus(trim=True)
|
||||||
self.stim.run_sim()
|
self.stim.run_sim()
|
||||||
trim_leakage_power=parse_output("timing", "leakage_power")
|
trim_leakage_power=parse_spice_list("timing", "leakage_power")
|
||||||
debug.check(trim_leakage_power!="Failed","Could not measure leakage power.")
|
debug.check(trim_leakage_power!="Failed","Could not measure leakage power.")
|
||||||
|
|
||||||
# For debug, you sometimes want to inspect each simulation.
|
# For debug, you sometimes want to inspect each simulation.
|
||||||
|
|
@ -473,10 +473,10 @@ class delay():
|
||||||
# Checking from not data_value to data_value
|
# Checking from not data_value to data_value
|
||||||
self.write_delay_stimulus()
|
self.write_delay_stimulus()
|
||||||
self.stim.run_sim()
|
self.stim.run_sim()
|
||||||
delay_hl = parse_output("timing", "delay_hl")
|
delay_hl = parse_spice_list("timing", "delay_hl")
|
||||||
delay_lh = parse_output("timing", "delay_lh")
|
delay_lh = parse_spice_list("timing", "delay_lh")
|
||||||
slew_hl = parse_output("timing", "slew_hl")
|
slew_hl = parse_spice_list("timing", "slew_hl")
|
||||||
slew_lh = parse_output("timing", "slew_lh")
|
slew_lh = parse_spice_list("timing", "slew_lh")
|
||||||
# if it failed or the read was longer than a period
|
# if it failed or the read was longer than a period
|
||||||
if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float:
|
if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float:
|
||||||
debug.info(2,"Invalid measures: Period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
|
debug.info(2,"Invalid measures: Period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
|
||||||
|
|
|
||||||
|
|
@ -186,8 +186,8 @@ class setup_hold():
|
||||||
target_time=feasible_bound,
|
target_time=feasible_bound,
|
||||||
correct_value=correct_value)
|
correct_value=correct_value)
|
||||||
self.stim.run_sim()
|
self.stim.run_sim()
|
||||||
ideal_clk_to_q = convert_to_float(parse_output("timing", "clk2q_delay"))
|
ideal_clk_to_q = convert_to_float(parse_spice_list("timing", "clk2q_delay"))
|
||||||
setuphold_time = convert_to_float(parse_output("timing", "setup_hold_time"))
|
setuphold_time = convert_to_float(parse_spice_list("timing", "setup_hold_time"))
|
||||||
debug.info(2,"*** {0} CHECK: {1} Ideal Clk-to-Q: {2} Setup/Hold: {3}".format(mode, correct_value,ideal_clk_to_q,setuphold_time))
|
debug.info(2,"*** {0} CHECK: {1} Ideal Clk-to-Q: {2} Setup/Hold: {3}".format(mode, correct_value,ideal_clk_to_q,setuphold_time))
|
||||||
|
|
||||||
if type(ideal_clk_to_q)!=float or type(setuphold_time)!=float:
|
if type(ideal_clk_to_q)!=float or type(setuphold_time)!=float:
|
||||||
|
|
@ -219,8 +219,8 @@ class setup_hold():
|
||||||
|
|
||||||
|
|
||||||
self.stim.run_sim()
|
self.stim.run_sim()
|
||||||
clk_to_q = convert_to_float(parse_output("timing", "clk2q_delay"))
|
clk_to_q = convert_to_float(parse_spice_list("timing", "clk2q_delay"))
|
||||||
setuphold_time = convert_to_float(parse_output("timing", "setup_hold_time"))
|
setuphold_time = convert_to_float(parse_spice_list("timing", "setup_hold_time"))
|
||||||
if type(clk_to_q)==float and (clk_to_q<1.1*ideal_clk_to_q) and type(setuphold_time)==float:
|
if type(clk_to_q)==float and (clk_to_q<1.1*ideal_clk_to_q) and type(setuphold_time)==float:
|
||||||
if mode == "SETUP": # SETUP is clk-din, not din-clk
|
if mode == "SETUP": # SETUP is clk-din, not din-clk
|
||||||
setuphold_time *= -1e9
|
setuphold_time *= -1e9
|
||||||
|
|
|
||||||
|
|
@ -89,11 +89,13 @@ def print_banner():
|
||||||
def check_versions():
|
def check_versions():
|
||||||
""" Run some checks of required software versions. """
|
""" Run some checks of required software versions. """
|
||||||
|
|
||||||
# Now require python >=3.6
|
# Now require python >=3.5
|
||||||
major_python_version = sys.version_info.major
|
major_python_version = sys.version_info.major
|
||||||
minor_python_version = sys.version_info.minor
|
minor_python_version = sys.version_info.minor
|
||||||
if not (major_python_version == 3 and minor_python_version >= 6):
|
major_required = 3
|
||||||
debug.error("Python 3.6 or greater is required.",-1)
|
minor_required = 5
|
||||||
|
if not (major_python_version == major_required and minor_python_version >= minor_required):
|
||||||
|
debug.error("Python {0}.{1} or greater is required.".format(major_required,minor_required),-1)
|
||||||
|
|
||||||
# FIXME: Check versions of other tools here??
|
# FIXME: Check versions of other tools here??
|
||||||
# or, this could be done in each module (e.g. verify, characterizer, etc.)
|
# or, this could be done in each module (e.g. verify, characterizer, etc.)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ class timing_sram_test(openram_test):
|
||||||
debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data))
|
debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data))
|
||||||
|
|
||||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
d = delay.delay(s,tempspice,corner)
|
d = delay(s,tempspice,corner)
|
||||||
import tech
|
import tech
|
||||||
loads = [tech.spice["msflop_in_cap"]*4]
|
loads = [tech.spice["msflop_in_cap"]*4]
|
||||||
slews = [tech.spice["rise_time"]*2]
|
slews = [tech.spice["rise_time"]*2]
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class timing_setup_test(openram_test):
|
||||||
slews = [tech.spice["rise_time"]*2]
|
slews = [tech.spice["rise_time"]*2]
|
||||||
|
|
||||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
sh = setup_hold.setup_hold(corner)
|
sh = setup_hold(corner)
|
||||||
data = sh.analyze(slews,slews)
|
data = sh.analyze(slews,slews)
|
||||||
#print data
|
#print data
|
||||||
if OPTS.tech_name == "freepdk45":
|
if OPTS.tech_name == "freepdk45":
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class timing_sram_test(openram_test):
|
||||||
debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data))
|
debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data))
|
||||||
|
|
||||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
d = delay.delay(s,tempspice,corner)
|
d = delay(s,tempspice,corner)
|
||||||
import tech
|
import tech
|
||||||
loads = [tech.spice["msflop_in_cap"]*4]
|
loads = [tech.spice["msflop_in_cap"]*4]
|
||||||
slews = [tech.spice["rise_time"]*2]
|
slews = [tech.spice["rise_time"]*2]
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class timing_setup_test(openram_test):
|
||||||
slews = [tech.spice["rise_time"]*2]
|
slews = [tech.spice["rise_time"]*2]
|
||||||
|
|
||||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
sh = setup_hold.setup_hold(corner)
|
sh = setup_hold(corner)
|
||||||
data = sh.analyze(slews,slews)
|
data = sh.analyze(slews,slews)
|
||||||
#print data
|
#print data
|
||||||
if OPTS.tech_name == "freepdk45":
|
if OPTS.tech_name == "freepdk45":
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue