Ejemplo n.º 1
0
    def run_simulation(self, period, load, slew):
        """ This tries to simulate a period and checks if the result
        works. If so, it returns True and the delays and slews."""

        # Checking from not data_value to data_value
        self.write_stimulus(period, load, slew)
        stimuli.run_sim()
        delay0 = ch.convert_to_float(ch.parse_output("timing", "delay0"))
        delay1 = ch.convert_to_float(ch.parse_output("timing", "delay1"))
        slew0 = ch.convert_to_float(ch.parse_output("timing", "slew0"))
        slew1 = ch.convert_to_float(ch.parse_output("timing", "slew1"))

        # if it failed or the read was longer than a period
        if type(delay0) != float or type(delay1) != float or type(
                slew1) != float or type(slew0) != float:
            return (False, 0, 0, 0, 0)
        delay0 *= 1e9
        delay1 *= 1e9
        slew0 *= 1e9
        slew1 *= 1e9
        if delay0 > period or delay1 > period or slew0 > period or slew1 > period:
            return (False, 0, 0, 0, 0)
        else:
            debug.info(
                2,
                "Successful simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n"
                .format(period, load, slew, delay0, delay1, slew0, slew1))
        #key=raw_input("press return to continue")

        # The delay is from the negative edge for our SRAM
        return (True, delay1, slew1, delay0, slew0)
Ejemplo n.º 2
0
    def try_period(self, period, load, slew, feasible_delay1, feasible_delay0):
        """ This tries to simulate a period and checks if the result
        works. If it does and the delay is within 5% still, it returns True."""

        # Checking from not data_value to data_value
        self.write_stimulus(period,load,slew)
        stimuli.run_sim()
        delay0 = ch.convert_to_float(ch.parse_output("timing", "delay0"))
        delay1 = ch.convert_to_float(ch.parse_output("timing", "delay1"))
        slew0 = ch.convert_to_float(ch.parse_output("timing", "slew0"))
        slew1 = ch.convert_to_float(ch.parse_output("timing", "slew1"))
        # if it failed or the read was longer than a period
        if type(delay0)!=float or type(delay1)!=float or type(slew1)!=float or type(slew0)!=float:
            debug.info(2,"Invalid measures: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
            return False
        delay0 *= 1e9
        delay1 *= 1e9
        slew0 *= 1e9
        slew1 *= 1e9
        if delay0>period or delay1>period or slew0>period or slew1>period:
            debug.info(2,"Too long delay/slew: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
            return False
        else:
            if not ch.relative_compare(delay1,feasible_delay1,error_tolerance=0.05):
                debug.info(2,"Delay too big {0} vs {1}".format(delay1,feasible_delay1))
                return False
            elif not ch.relative_compare(delay0,feasible_delay0,error_tolerance=0.05):
                debug.info(2,"Delay too big {0} vs {1}".format(delay0,feasible_delay0))
                return False


        #key=raw_input("press return to continue")

        debug.info(2,"Successful period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
        return True
Ejemplo n.º 3
0
    def try_period(self, period, load, slew, feasible_delay1, feasible_delay0):
        """ This tries to simulate a period and checks if the result
        works. If it does and the delay is within 5% still, it returns True."""

        # Checking from not data_value to data_value
        self.write_stimulus(period,load,slew)
        stimuli.run_sim()
        delay0 = ch.convert_to_float(ch.parse_output("timing", "delay0"))
        delay1 = ch.convert_to_float(ch.parse_output("timing", "delay1"))
        if type(delay0)==float:
            delay0 *= 1e9
        if type(delay1)==float:
            delay1 *= 1e9
        debug.info(2,"Period {0}, delay0={1}ns, delay1={2}ns".format(period,delay0, delay1))
        # if it failed or the read was longer than a period
        if type(delay0)!=float or type(delay1)!=float:
            return False
        else:
            if ch.relative_compare(delay1*1e9,feasible_delay1,error_tolerance=0.05):
                return False
            elif ch.relative_compare(delay0*1e9,feasible_delay0,error_tolerance=0.05):
                return False


        #key=raw_input("press return to continue")

        return True
Ejemplo n.º 4
0
    def try_period(self, feasible_period, target_period, data_value):
        """ This tries to simulate a period and checks if the result
        works. If so, it returns True.  If not, it it doubles the
        period and returns False."""

        # Checking from not data_value to data_value
        self.write_stimulus(feasible_period, target_period, data_value)
        stimuli.run_sim()
        delay_value = ch.convert_to_float(ch.parse_output("timing", "delay"))
        
        # if it failed or the read was longer than a period
        if type(delay_value)!=float or delay_value*1e9>target_period:
            debug.info(2,"Infeasible period " + str(target_period) + " delay " + str(delay_value*1e9) + "ns")
            return (False, "NA")
        else:
            debug.info(2,"Feasible period " + str(feasible_period) \
                           + ", target period " + str(target_period) \
                           + ", read/write of " + str(data_value) \
                           + ", delay=" + str(delay_value*1e9) + "ns")
        #key=raw_input("press return to continue")

        return (True, delay_value*1e9)
Ejemplo n.º 5
0
    def bidir_search(self, correct_value, mode):
        """ 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
        depending on whether we are doing setup or hold. 
        """

        # NOTE: The feasible bound is always feasible. This is why they are different for setup and hold.
        # The clock will always be offset by 2*period from the start, so we want to look before and after
        # this time. They are also unbalanced so that the average won't be right on the clock edge in the
        # first iteration.
        if mode == "SETUP":
            feasible_bound = 1.25*self.period
            infeasible_bound = 2.5*self.period
        else:
            infeasible_bound = 1.5*self.period
            feasible_bound = 2.75*self.period

        # Initial check if reference feasible bound time passes for correct_value, if not, we can't start the search!
        self.write_stimulus(mode=mode, 
                            target_time=feasible_bound, 
                            correct_value=correct_value)
        stimuli.run_sim()
        ideal_clk_to_q = ch.convert_to_float(ch.parse_output("timing", "clk2q_delay"))
        setuphold_time = ch.convert_to_float(ch.parse_output("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))

        if type(ideal_clk_to_q)!=float or type(setuphold_time)!=float:
            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,setuphold_time),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,
                                                                                       setuphold_time,
                                                                                       feasible_bound,
                                                                                       2*self.period))
        #raw_input("Press Enter to continue...")
            
        while True:
            target_time = (feasible_bound + infeasible_bound)/2
            self.write_stimulus(mode=mode, 
                                target_time=target_time, 
                                correct_value=correct_value)

            debug.info(2,"{0} value: {1} Target time: {2} Infeasible: {3} Feasible: {4}".format(mode,
                                                                                                correct_value,
                                                                                                target_time,
                                                                                                infeasible_bound,
                                                                                                feasible_bound))


            stimuli.run_sim()
            clk_to_q = ch.convert_to_float(ch.parse_output("timing", "clk2q_delay"))
            setuphold_time = ch.convert_to_float(ch.parse_output("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 mode == "SETUP": # SETUP is clk-din, not din-clk
                    setuphold_time *= -1e9
                else:
                    setuphold_time *= 1e9

                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
            else:
                debug.info(2,"FAIL Clk-to-Q: {0} Setup/Hold: {1}".format(clk_to_q,setuphold_time))
                infeasible_bound = target_time

            #raw_input("Press Enter to continue...")
            if ch.relative_compare(feasible_bound, infeasible_bound, error_tolerance=0.001):
                debug.info(3,"CONVERGE {0} vs {1}".format(feasible_bound,infeasible_bound))
                break
            

        debug.info(2,"Converged on {0} time {1}.".format(mode,passing_setuphold_time))
        return passing_setuphold_time
Ejemplo n.º 6
0
    def bidir_search(self, correct_value, noise_margin, measure_name, mode):
        """ 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
        depending on whether we are doing setup or hold. 
        """
        period = tech.spice["feasible_period"]

        # The clock will start being offset by a period, so we want to look before and after
        # theis time.
        if mode == "HOLD":
            target_time = 1.5 * period
            lower_bound = 0.5 * period
            upper_bound = 1.5 * period
        else:
            target_time = 0.5 * period
            lower_bound = 0.5 * period
            upper_bound = 1.5 * period

        previous_time = target_time
        # Initial Check if reference setup time passes for correct_value
        self.write_stimulus(mode=mode,
                            target_time=target_time,
                            correct_value=correct_value,
                            period=period,
                            noise_margin=noise_margin)
        stimuli.run_sim()
        output_value = ch.convert_to_float(
            ch.parse_output("timing", measure_name))
        debug.info(
            3,
            "Correct: {0} Output: {1} NM: {2}".format(correct_value,
                                                      output_value,
                                                      noise_margin))
        if mode == "HOLD":
            setuphold_time = target_time - period
        else:
            setuphold_time = period - target_time
        debug.info(
            3, "Target time: {0} Low: {1} Up: {2} Measured: {3}".format(
                target_time, lower_bound, upper_bound, setuphold_time))
        if not self.pass_fail_test(output_value, correct_value, noise_margin):
            debug.error("Initial period/target hold time fails for data value",
                        2)

        # We already found it feasible, so advance one step first thing.
        if mode == "HOLD":
            target_time -= 0.5 * (upper_bound - lower_bound)
        else:
            target_time += 0.5 * (upper_bound - lower_bound)
        while True:
            self.write_stimulus(mode=mode,
                                target_time=target_time,
                                correct_value=correct_value,
                                period=period,
                                noise_margin=noise_margin)
            if mode == "HOLD":
                setuphold_time = target_time - period
            else:
                setuphold_time = period - target_time
            debug.info(
                3, "Target time: {0} Low: {1} Up: {2} Measured: {3}".format(
                    target_time, lower_bound, upper_bound, setuphold_time))

            stimuli.run_sim()
            output_value = ch.convert_to_float(
                ch.parse_output("timing", measure_name))
            debug.info(
                3, "Correct: {0} Output: {1} NM: {2}".format(
                    correct_value, output_value, noise_margin))
            if self.pass_fail_test(output_value, correct_value, noise_margin):
                debug.info(3, "PASS")
                if ch.relative_compare(target_time, previous_time):
                    debug.info(
                        3, "CONVERGE " + str(target_time) + " " +
                        str(previous_time))
                    break
                previous_time = target_time
                if mode == "HOLD":
                    upper_bound = target_time
                    target_time -= 0.5 * (upper_bound - lower_bound)
                else:
                    lower_bound = target_time
                    target_time += 0.5 * (upper_bound - lower_bound)
            else:
                debug.info(3, "FAIL")
                if mode == "HOLD":
                    lower_bound = target_time
                    target_time += 0.5 * (upper_bound - lower_bound)
                else:
                    upper_bound = target_time
                    target_time -= 0.5 * (upper_bound - lower_bound)
            #raw_input("Press Enter to continue...")
            # the clock starts offset by one clock period,
            # so we always measure our setup or hold relative to this time
            if mode == "HOLD":
                setuphold_time = target_time - period
            else:
                setuphold_time = period - target_time
        return setuphold_time