mirror of https://github.com/VLSIDA/OpenRAM.git
Remove setup/hold measure and compute it directly.
This commit is contained in:
parent
d43edd95e4
commit
9555b52aaa
|
|
@ -76,10 +76,10 @@ class setup_hold():
|
||||||
self.stim.write_supply()
|
self.stim.write_supply()
|
||||||
|
|
||||||
def write_data(self, mode, target_time, correct_value):
|
def write_data(self, mode, target_time, correct_value):
|
||||||
"""Create the data signals for setup/hold analysis. First period is to
|
"""
|
||||||
|
Create the data signals for setup/hold analysis. First period is to
|
||||||
initialize it to the opposite polarity. Second period is used for
|
initialize it to the opposite polarity. Second period is used for
|
||||||
characterization.
|
characterization.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.sf.write("\n* Generation of the data and clk signals\n")
|
self.sf.write("\n* Generation of the data and clk signals\n")
|
||||||
if correct_value == 1:
|
if correct_value == 1:
|
||||||
|
|
@ -106,8 +106,11 @@ class setup_hold():
|
||||||
setup=0)
|
setup=0)
|
||||||
|
|
||||||
def write_clock(self):
|
def write_clock(self):
|
||||||
""" Create the clock signal for setup/hold analysis. First period initializes the FF
|
"""
|
||||||
while the second is used for characterization."""
|
Create the clock signal for setup/hold analysis.
|
||||||
|
First period initializes the FF
|
||||||
|
while the second is used for characterization.
|
||||||
|
"""
|
||||||
|
|
||||||
self.stim.gen_pwl(sig_name="clk",
|
self.stim.gen_pwl(sig_name="clk",
|
||||||
# initial clk edge is right after the 0 time to initialize a flop
|
# initial clk edge is right after the 0 time to initialize a flop
|
||||||
|
|
@ -128,16 +131,6 @@ class setup_hold():
|
||||||
else:
|
else:
|
||||||
dout_rise_or_fall = "FALL"
|
dout_rise_or_fall = "FALL"
|
||||||
|
|
||||||
# in SETUP mode, the input mirrors what the output should be
|
|
||||||
if mode == "SETUP":
|
|
||||||
din_rise_or_fall = dout_rise_or_fall
|
|
||||||
else:
|
|
||||||
# in HOLD mode, however, the input should be opposite of the output
|
|
||||||
if correct_value == 1:
|
|
||||||
din_rise_or_fall = "FALL"
|
|
||||||
else:
|
|
||||||
din_rise_or_fall = "RISE"
|
|
||||||
|
|
||||||
self.sf.write("\n* Measure statements for pass/fail verification\n")
|
self.sf.write("\n* Measure statements for pass/fail verification\n")
|
||||||
trig_name = "clk"
|
trig_name = "clk"
|
||||||
targ_name = "Q"
|
targ_name = "Q"
|
||||||
|
|
@ -153,19 +146,6 @@ class setup_hold():
|
||||||
trig_td=1.9 * self.period,
|
trig_td=1.9 * self.period,
|
||||||
targ_td=1.9 * self.period)
|
targ_td=1.9 * self.period)
|
||||||
|
|
||||||
targ_name = "D"
|
|
||||||
# Start triggers right after initialize value is returned to normal
|
|
||||||
# at one period
|
|
||||||
self.stim.gen_meas_delay(meas_name="setup_hold_time",
|
|
||||||
trig_name=trig_name,
|
|
||||||
targ_name=targ_name,
|
|
||||||
trig_val=trig_val,
|
|
||||||
targ_val=targ_val,
|
|
||||||
trig_dir="RISE",
|
|
||||||
targ_dir=din_rise_or_fall,
|
|
||||||
trig_td=1.2 * self.period,
|
|
||||||
targ_td=1.2 * self.period)
|
|
||||||
|
|
||||||
def bidir_search(self, correct_value, mode):
|
def bidir_search(self, correct_value, mode):
|
||||||
""" This will perform a bidirectional search for either setup or hold times.
|
""" This will perform a bidirectional search for either setup or hold times.
|
||||||
It starts with the feasible priod and looks a half period beyond or before it
|
It starts with the feasible priod and looks a half period beyond or before it
|
||||||
|
|
@ -189,21 +169,24 @@ class setup_hold():
|
||||||
correct_value=correct_value)
|
correct_value=correct_value)
|
||||||
self.stim.run_sim(self.stim_sp)
|
self.stim.run_sim(self.stim_sp)
|
||||||
ideal_clk_to_q = convert_to_float(parse_spice_list("timing", "clk2q_delay"))
|
ideal_clk_to_q = convert_to_float(parse_spice_list("timing", "clk2q_delay"))
|
||||||
setuphold_time = convert_to_float(parse_spice_list("timing", "setup_hold_time"))
|
# We use a 1/2 speed clock for some reason...
|
||||||
debug.info(2,"*** {0} CHECK: {1} Ideal Clk-to-Q: {2} Setup/Hold: {3}".format(mode, correct_value,ideal_clk_to_q,setuphold_time))
|
setuphold_time = (feasible_bound - 2 * self.period) / 1e9
|
||||||
|
if mode == "SETUP": # SETUP is clk-din, not din-clk
|
||||||
|
passing_setuphold_time = -1e9 * setuphold_time
|
||||||
|
else:
|
||||||
|
passing_setuphold_time = 1e9 * 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:
|
||||||
debug.error("Initial hold time fails for data value feasible bound {0} Clk-to-Q {1} Setup/Hold {2}".format(feasible_bound,
|
debug.error("Initial hold time fails for data value feasible "
|
||||||
|
"bound {0} Clk-to-Q {1} Setup/Hold {2}".format(feasible_bound,
|
||||||
ideal_clk_to_q,
|
ideal_clk_to_q,
|
||||||
setuphold_time),
|
setuphold_time),
|
||||||
2)
|
2)
|
||||||
|
|
||||||
if mode == "SETUP": # SETUP is clk-din, not din-clk
|
|
||||||
setuphold_time *= -1e9
|
|
||||||
else:
|
|
||||||
setuphold_time *= 1e9
|
|
||||||
|
|
||||||
passing_setuphold_time = setuphold_time
|
|
||||||
debug.info(2, "Checked initial {0} time {1}, data at {2}, clock at {3} ".format(mode,
|
debug.info(2, "Checked initial {0} time {1}, data at {2}, clock at {3} ".format(mode,
|
||||||
setuphold_time,
|
setuphold_time,
|
||||||
feasible_bound,
|
feasible_bound,
|
||||||
|
|
@ -224,15 +207,14 @@ class setup_hold():
|
||||||
|
|
||||||
self.stim.run_sim(self.stim_sp)
|
self.stim.run_sim(self.stim_sp)
|
||||||
clk_to_q = convert_to_float(parse_spice_list("timing", "clk2q_delay"))
|
clk_to_q = convert_to_float(parse_spice_list("timing", "clk2q_delay"))
|
||||||
setuphold_time = convert_to_float(parse_spice_list("timing", "setup_hold_time"))
|
# We use a 1/2 speed clock for some reason...
|
||||||
if type(clk_to_q) == float and (clk_to_q < 1.1 * ideal_clk_to_q) and type(setuphold_time)==float:
|
setuphold_time = (target_time - 2 * self.period) / 1e9
|
||||||
if mode == "SETUP": # SETUP is clk-din, not din-clk
|
if mode == "SETUP": # SETUP is clk-din, not din-clk
|
||||||
setuphold_time *= -1e9
|
passing_setuphold_time = -1e9 * setuphold_time
|
||||||
else:
|
else:
|
||||||
setuphold_time *= 1e9
|
passing_setuphold_time = 1e9 * setuphold_time
|
||||||
|
if type(clk_to_q) == float and (clk_to_q < 1.1 * ideal_clk_to_q):
|
||||||
debug.info(2, "PASS Clk-to-Q: {0} Setup/Hold: {1}".format(clk_to_q, setuphold_time))
|
debug.info(2, "PASS Clk-to-Q: {0} Setup/Hold: {1}".format(clk_to_q, setuphold_time))
|
||||||
passing_setuphold_time = setuphold_time
|
|
||||||
feasible_bound = target_time
|
feasible_bound = target_time
|
||||||
else:
|
else:
|
||||||
debug.info(2, "FAIL Clk-to-Q: {0} Setup/Hold: {1}".format(clk_to_q, setuphold_time))
|
debug.info(2, "FAIL Clk-to-Q: {0} Setup/Hold: {1}".format(clk_to_q, setuphold_time))
|
||||||
|
|
@ -242,7 +224,6 @@ class setup_hold():
|
||||||
debug.info(3, "CONVERGE {0} vs {1}".format(feasible_bound, infeasible_bound))
|
debug.info(3, "CONVERGE {0} vs {1}".format(feasible_bound, infeasible_bound))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
debug.info(2, "Converged on {0} time {1}.".format(mode, passing_setuphold_time))
|
debug.info(2, "Converged on {0} time {1}.".format(mode, passing_setuphold_time))
|
||||||
return passing_setuphold_time
|
return passing_setuphold_time
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue