From a732405836678aafd9cc9de3b64131ea275bf80c Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 26 Feb 2018 08:54:35 -0800 Subject: [PATCH] Add utility script gen_stimulus.py to help create simulations for debugging. --- compiler/characterizer/delay.py | 23 +++--- compiler/gen_stimulus.py | 86 +++++++++++++++++++++ compiler/globals.py | 3 +- compiler/openram.py | 2 + compiler/tests/00_code_format_check_test.py | 2 + 5 files changed, 105 insertions(+), 11 deletions(-) create mode 100755 compiler/gen_stimulus.py diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 9e9de9eb..15e0090e 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -37,16 +37,18 @@ class delay(): # These are the member variables for a simulation self.period = 0 - self.load = 0 - self.slew = 0 - + self.set_load_slew(0,0) self.set_corner(corner) - + def set_corner(self,corner): """ Set the corner values """ self.corner = corner (self.process, self.vdd_voltage, self.temperature) = corner + def set_load_slew(self,load,slew): + """ Set the load and slew """ + self.load = load + self.slew = slew def check_arguments(self): """Checks if arguments given for write_stimulus() meets requirements""" @@ -578,8 +580,9 @@ class delay(): (full_array_leakage, trim_array_leakage)=self.run_power_simulation() char_data["leakage_power"]=full_array_leakage - for self.slew in slews: - for self.load in loads: + 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)) @@ -593,8 +596,7 @@ class delay(): # 3) Finds the minimum period without degrading the delays by X% - self.load=max(loads) - self.slew=max(slews) + 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)) @@ -710,8 +712,9 @@ class delay(): delay_hl = [] slew_lh = [] slew_hl = [] - for self.slew in slews: - for self.load in loads: + for slew in slews: + for load in loads: + self.set_load_slew(load,slew) bank_delay = sram.analytical_delay(self.slew,self.load) # Convert from ps to ns delay_lh.append(bank_delay.delay/1e3) diff --git a/compiler/gen_stimulus.py b/compiler/gen_stimulus.py new file mode 100755 index 00000000..b676a07c --- /dev/null +++ b/compiler/gen_stimulus.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python2.7 +""" +This script will generate a stimulus file for a given period, load, and slew input +for the given dimension SRAM. It is useful for debugging after an SRAM has been +created without re-running the entire process. Right now, it assumes the nominal +corner, but should probably be extended. +""" + +import sys,os +import datetime +import re +import importlib +from globals import * + +(OPTS, args) = parse_args() + +# Override the usage +USAGE = "Usage: {} [options] \nUse -h for help.\n".format(__file__) + +# Check that we are left with a single configuration file as argument. +if len(args) != 4: + print(USAGE) + sys.exit(2) + + +# We need to get the: +# config file +config_file = args[0] +# period +period = float(args[1]) +# load +load = float(args[2]) +# slew +slew = float(args[3]) + +# These depend on arguments, so don't load them until now. +import debug + +init_openram(config_file=config_file, is_unit_test=False) +OPTS.check_lvsdrc = False +# Put the temp output in the output path since it is what we want to generate! +old_openram_temp = OPTS.openram_temp +OPTS.openram_temp = OPTS.output_path + + + +import sram +class fake_sram(sram.sram): + """ This is an SRAM that doesn't actually create itself, just computes + the sizes. """ + def __init__(self, word_size, num_words, num_banks, name): + self.name = name + self.word_size = word_size + self.num_words = num_words + self.num_banks = num_banks + c = reload(__import__(OPTS.bitcell)) + self.mod_bitcell = getattr(c, OPTS.bitcell) + self.bitcell = self.mod_bitcell() + # to get the row, col, etc. + self.compute_sizes() + +sram = fake_sram(OPTS.word_size, OPTS.num_words, OPTS.num_banks, OPTS.output_name) +sp_file = OPTS.output_path+OPTS.output_name + ".sp" + +from characterizer import delay +import tech +# Set up the delay and set to the nominal corner +d = delay.delay(sram, sp_file, ("TT", tech.spice["nom_supply_voltage"], tech.spice["nom_temperature"])) +# Set the period +d.period = period +# Set the load of outputs and slew of inputs +d.set_load_slew(load,slew) +# Set the probe address/bit +probe_address = "1" * sram.addr_size +probe_data = sram.word_size - 1 +d.set_probe(probe_address, probe_data) + +d.write_delay_stimulus() + +# Output info about this run +report_status() +print("Output files are:\n{0}stim.sp\n{0}sram.sp\n{0}reduced.sp".format(OPTS.output_path)) +OPTS.openram_temp = old_openram_temp +# Delete temp files, remove the dir, etc. +end_openram() + diff --git a/compiler/globals.py b/compiler/globals.py index 4023f927..84fda0c1 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -167,6 +167,8 @@ def read_config(config_file, is_unit_test=True): if not OPTS.output_path.endswith('/'): OPTS.output_path += "/" + if not OPTS.output_path.startswith('/'): + OPTS.output_path = os.getcwd() + "/" + OPTS.output_path debug.info(1, "Output saved in " + OPTS.output_path) OPTS.is_unit_test=is_unit_test @@ -321,7 +323,6 @@ def report_status(): if not OPTS.tech_name: debug.error("Tech name must be specified in config file.") - print("Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)") print("Technology: {0}".format(OPTS.tech_name)) print("Word size: {0}\nWords: {1}\nBanks: {2}".format(OPTS.word_size, OPTS.num_words, diff --git a/compiler/openram.py b/compiler/openram.py index f1660477..5cbe4387 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -40,6 +40,8 @@ report_status() import verify import sram +print("Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)") + # Keep track of running stats start_time = datetime.datetime.now() print_time("Start",start_time) diff --git a/compiler/tests/00_code_format_check_test.py b/compiler/tests/00_code_format_check_test.py index 41b27d9a..fa1818dc 100644 --- a/compiler/tests/00_code_format_check_test.py +++ b/compiler/tests/00_code_format_check_test.py @@ -35,6 +35,8 @@ class code_format_test(openram_test): continue if re.search("openram.py$", code): continue + if re.search("gen_stimulus.py$", code): + continue errors += check_print_output(code) # fails if there are any tabs in any files