Exemplo n.º 1
0
 def write_clk(self, data):
     """ Adds clk pin timing results."""
     
     self.lib.write("    pin(clk){\n")
     self.lib.write("        clock             : true;\n")
     self.lib.write("        direction  : input; \n")
     self.lib.write("        capacitance : {0};  \n".format(tech.spice["FF_in_cap"]))
     self.lib.write("        min_pulse_width_high : {0} ; \n".format(ch.round_time(data["min_period1"])))
     self.lib.write("        min_pulse_width_low : {0} ; \n".format(ch.round_time(data["min_period0"])))
     self.lib.write("        timing(){ \n")
     self.lib.write("            timing_type :\"min_pulse_width\"; \n")
     self.lib.write("            related_pin  : clk; \n")
     self.lib.write("            rise_constraint(CLK_TRAN) {\n")
     self.lib.write("                values(\"0\"); \n")
     self.lib.write("            }\n")
     self.lib.write("            fall_constraint(CLK_TRAN) {\n")
     self.lib.write("                values(\"0\"); \n")
     self.lib.write("            }\n")
     self.lib.write("         }\n")
     self.lib.write("        timing(){ \n")
     self.lib.write("            timing_type :\"minimum_period\"; \n")
     self.lib.write("            related_pin  : clk; \n")
     self.lib.write("            rise_constraint(CLK_TRAN) {\n")
     self.lib.write("                values(\"0\"); \n")
     self.lib.write("            }\n")
     self.lib.write("            fall_constraint(CLK_TRAN) {\n")
     self.lib.write("                values(\"0\"); \n")
     self.lib.write("            }\n")
     self.lib.write("         }\n")
     self.lib.write("    }\n")
     self.lib.write("    }\n")
     self.lib.write("}\n")
Exemplo n.º 2
0
    def __init__(self, libname, sram, spfile):
        self.name = sram.name
        self.num_words = sram.num_words
        self.word_size = sram.word_size
        self.addr_size = sram.addr_size

        self.sh = setup_hold.setup_hold()
        self.d = delay.delay(sram, spfile)

        debug.info(1,"Writing to {0}".format(libname))
        self.lib = open(libname, "w")

        self.lib.write("library ({0}_lib)".format(self.name))
        self.lib.write("{\n")
        self.lib.write("    delay_model : \"table_lookup\";\n")
        
        self.write_units()
        self.write_defaults()
        self.write_LUT()

        self.lib.write("    default_operating_conditions : TT; \n")
        
        self.write_bus()

        self.lib.write("cell ({0})".format(self.name))
        self.lib.write("{\n")
        self.lib.write("    memory(){ \n")
        self.lib.write("    type : ram;\n")
        self.lib.write("    address_width : {0};\n".format(self.addr_size))
        self.lib.write("    word_width : {0};\n".format(self.word_size))
        self.lib.write("    }\n")
        self.lib.write("    interface_timing : true;\n")
        self.lib.write("    dont_use  : true;\n")
        self.lib.write("    map_only   : true;\n")
        self.lib.write("    dont_touch : true;\n")
        self.lib.write("    area : {0};\n\n".format(sram.width * sram.height))

        times = self.sh.analyze()
        
        for i in times.keys():
            times[i] = ch.round_time(times[i])


        probe_address = "1" * self.addr_size
        probe_data = self.word_size - 1

        data = self.d.analyze(probe_address, probe_data)
        for i in data.keys():
            data[i] = ch.round_time(data[i])

      
        self.write_data_bus(data, times)
        self.write_addr_bus(times)
        self.write_control_pins(times)
        self.write_clk(data)
        
        self.lib.close()
Exemplo n.º 3
0
    def analyze(self, probe_address, probe_data, slews, loads):
        """main function to calculate the min period for a low_to_high
        transistion and a high_to_low transistion returns a dictionary
        that contains all both the min period and associated delays
        Dictionary Keys: min_period1, delay1, min_period0, delay0
        """

        self.set_probe(probe_address, probe_data)

        (feasible_period, feasible_delay1,
         feasible_delay0) = self.find_feasible_period(max(loads), max(slews))
        debug.check(feasible_delay1 > 0, "Negative delay may not be possible")
        debug.check(feasible_delay0 > 0, "Negative delay may not be possible")

        # The power variables are just scalars. These use the final feasible period simulation
        # which should have worked.
        read0_power = ch.convert_to_float(
            ch.parse_output("timing", "read0_power"))
        write0_power = ch.convert_to_float(
            ch.parse_output("timing", "write0_power"))
        read1_power = ch.convert_to_float(
            ch.parse_output("timing", "read1_power"))
        write1_power = ch.convert_to_float(
            ch.parse_output("timing", "write1_power"))

        LH_delay = []
        HL_delay = []
        LH_slew = []
        HL_slew = []
        for slew in slews:
            for load in loads:
                (success, delay1, slew1, delay0,
                 slew0) = self.run_simulation(feasible_period, load, slew)
                debug.check(success, "Couldn't run a simulation properly.\n")
                LH_delay.append(delay1)
                HL_delay.append(delay0)
                LH_slew.append(slew1)
                HL_slew.append(slew0)

        # finds the minimum period without degrading the delays by X%
        min_period = self.find_min_period(feasible_period, max(loads),
                                          max(slews), feasible_delay1,
                                          feasible_delay0)
        debug.check(type(min_period) == float, "Couldn't find minimum period.")
        debug.info(
            1, "Min Period: {0}n with a delay of {1}".format(
                min_period, feasible_delay1))

        data = {
            "min_period": ch.round_time(min_period),
            "delay1": LH_delay,
            "delay0": HL_delay,
            "slew1": LH_slew,
            "slew0": HL_slew,
            "read0_power": read0_power * 1e3,
            "read1_power": read1_power * 1e3,
            "write0_power": write0_power * 1e3,
            "write1_power": write1_power * 1e3
        }
        return data
Exemplo n.º 4
0
    def write_clk(self):
        """ Adds clk pin timing results."""

        self.compute_delay()

        self.lib.write("    pin(clk){\n")
        self.lib.write("        clock             : true;\n")
        self.lib.write("        direction  : input; \n")
        self.lib.write("        capacitance : {0};  \n".format(
            tech.spice["FF_in_cap"]))
        min_pulse_width = ch.round_time(self.delay["min_period"]) / 2.0
        min_period = ch.round_time(self.delay["min_period"])
        self.lib.write("        timing(){ \n")
        self.lib.write("            timing_type :\"min_pulse_width\"; \n")
        self.lib.write("            related_pin  : clk; \n")
        self.lib.write("            rise_constraint(scalar) {\n")
        self.lib.write(
            "                values(\"{0}\"); \n".format(min_pulse_width))
        self.lib.write("            }\n")
        self.lib.write("            fall_constraint(scalar) {\n")
        self.lib.write(
            "                values(\"{0}\"); \n".format(min_pulse_width))
        self.lib.write("            }\n")
        self.lib.write("         }\n")
        self.lib.write("        timing(){ \n")
        self.lib.write("            timing_type :\"minimum_period\"; \n")
        self.lib.write("            related_pin  : clk; \n")
        self.lib.write("            rise_constraint(scalar) {\n")
        self.lib.write(
            "                values(\"{0}\"); \n".format(min_period))
        self.lib.write("            }\n")
        self.lib.write("            fall_constraint(scalar) {\n")
        self.lib.write(
            "                values(\"{0}\"); \n".format(min_period))
        self.lib.write("            }\n")
        self.lib.write("         }\n")
        self.lib.write("    }\n")
        self.lib.write("    }\n")
        self.lib.write("}\n")
Exemplo n.º 5
0
    def analyze(self, probe_address, probe_data, slews, loads):
        """
        Main function to characterize an SRAM for a table. Computes both delay and power characterization.
        """

        self.set_probe(probe_address, probe_data)

        # This is for debugging a full simulation
        # debug.info(0,"Debug simulation running...")
        # target_period=50.0
        # feasible_delay_lh=0.059083183
        # feasible_delay_hl=0.17953789
        # load=1.6728
        # slew=0.04
        # self.try_period(target_period, feasible_delay_lh, feasible_delay_hl)
        # sys.exit(1)

        # 1) Find a feasible period and it's corresponding delays using the trimmed array.
        self.load = max(loads)
        self.slew = max(slews)
        (feasible_delay_lh, feasible_delay_hl) = self.find_feasible_period()
        debug.check(feasible_delay_lh > 0,
                    "Negative delay may not be possible")
        debug.check(feasible_delay_hl > 0,
                    "Negative delay may not be possible")

        # 2) Measure the delay, slew and power for all slew/load pairs.
        # Make a list for each type of measurement to append results to
        char_data = {}
        for m in [
                "delay_lh", "delay_hl", "slew_lh", "slew_hl", "read0_power",
                "read1_power", "write0_power", "write1_power", "leakage_power"
        ]:
            char_data[m] = []

        # 2a) Find the leakage power of the trimmmed and  UNtrimmed arrays.
        (full_array_leakage, trim_array_leakage) = self.run_power_simulation()
        char_data["leakage_power"] = full_array_leakage

        for slew in slews:
            for load in loads:
                self.set_load_slew(load, slew)
                # 2c) Find the delay, dynamic power, and leakage power of the trimmed array.
                (success, delay_results) = self.run_delay_simulation()
                debug.check(
                    success,
                    "Couldn't run a simulation. slew={0} load={1}\n".format(
                        self.slew, self.load))
                for k, v in delay_results.items():
                    if "power" in k:
                        # Subtract partial array leakage and add full array leakage for the power measures
                        char_data[k].append(v - trim_array_leakage +
                                            full_array_leakage)
                    else:
                        char_data[k].append(v)

        # 3) Finds the minimum period without degrading the delays by X%
        self.set_load_slew(max(loads), max(slews))
        min_period = self.find_min_period(feasible_delay_lh, feasible_delay_hl)
        debug.check(type(min_period) == float, "Couldn't find minimum period.")
        debug.info(
            1, "Min Period: {0}n with a delay of {1} / {2}".format(
                min_period, feasible_delay_lh, feasible_delay_hl))

        # 4) Pack up the final measurements
        char_data["min_period"] = ch.round_time(min_period)

        return char_data
Exemplo n.º 6
0
    def write_clk(self):
        """ Adds clk pin timing results."""

        self.lib.write("    pin(clk){\n")
        self.lib.write("        clock             : true;\n")
        self.lib.write("        direction  : input; \n")
        # This should actually be a min inverter cap, but ok...
        self.lib.write("        capacitance : {0};  \n".format(
            tech.spice["dff_in_cap"]))

        # Find the average power of 1 and 0 bits for writes and reads over all loads/slews
        # Could make it a table, but this is fine for now.
        avg_write_power = np.mean(self.char_results["write1_power"] +
                                  self.char_results["write0_power"])
        avg_read_power = np.mean(self.char_results["read1_power"] +
                                 self.char_results["read0_power"])

        # Equally divide read/write power between first and second half of clock period
        self.lib.write("        internal_power(){\n")
        self.lib.write("            when : \"!CSb & clk & !WEb\"; \n")
        self.lib.write("            rise_power(scalar){\n")
        self.lib.write("                values(\"{0}\");\n".format(
            avg_write_power / 2.0))
        self.lib.write("            }\n")
        self.lib.write("            fall_power(scalar){\n")
        self.lib.write("                values(\"{0}\");\n".format(
            avg_write_power / 2.0))
        self.lib.write("            }\n")
        self.lib.write("        }\n")

        self.lib.write("        internal_power(){\n")
        self.lib.write("            when : \"!CSb & !clk & WEb\"; \n")
        self.lib.write("            rise_power(scalar){\n")
        self.lib.write("                values(\"{0}\");\n".format(
            avg_read_power / 2.0))
        self.lib.write("            }\n")
        self.lib.write("            fall_power(scalar){\n")
        self.lib.write("                values(\"{0}\");\n".format(
            avg_read_power / 2.0))
        self.lib.write("            }\n")
        self.lib.write("        }\n")
        # Have 0 internal power when disabled, this will be represented as leakage power.
        self.lib.write("        internal_power(){\n")
        self.lib.write("            when : \"CSb\"; \n")
        self.lib.write("            rise_power(scalar){\n")
        self.lib.write("                values(\"0\");\n")
        self.lib.write("            }\n")
        self.lib.write("            fall_power(scalar){\n")
        self.lib.write("                values(\"0\");\n")
        self.lib.write("            }\n")
        self.lib.write("        }\n")

        min_pulse_width = ch.round_time(self.char_results["min_period"]) / 2.0
        min_period = ch.round_time(self.char_results["min_period"])
        self.lib.write("        timing(){ \n")
        self.lib.write("            timing_type :\"min_pulse_width\"; \n")
        self.lib.write("            related_pin  : clk; \n")
        self.lib.write("            rise_constraint(scalar) {\n")
        self.lib.write(
            "                values(\"{0}\"); \n".format(min_pulse_width))
        self.lib.write("            }\n")
        self.lib.write("            fall_constraint(scalar) {\n")
        self.lib.write(
            "                values(\"{0}\"); \n".format(min_pulse_width))
        self.lib.write("            }\n")
        self.lib.write("         }\n")
        self.lib.write("        timing(){ \n")
        self.lib.write("            timing_type :\"minimum_period\"; \n")
        self.lib.write("            related_pin  : clk; \n")
        self.lib.write("            rise_constraint(scalar) {\n")
        self.lib.write(
            "                values(\"{0}\"); \n".format(min_period))
        self.lib.write("            }\n")
        self.lib.write("            fall_constraint(scalar) {\n")
        self.lib.write(
            "                values(\"{0}\"); \n".format(min_period))
        self.lib.write("            }\n")
        self.lib.write("         }\n")
        self.lib.write("    }\n")
        self.lib.write("    }\n")