diff --git a/ICCAD16_openram_paper/OpenRAM_ICCAD_2016_paper.pdf b/ICCAD16_openram_paper/OpenRAM_ICCAD_2016_paper.pdf new file mode 100644 index 00000000..fd3a4a65 Binary files /dev/null and b/ICCAD16_openram_paper/OpenRAM_ICCAD_2016_paper.pdf differ diff --git a/README b/README index 2c315a6f..a0a14ee7 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ BASIC SETUP -The OpenRAM compiler has very few dependencies: -1) ngspice v20 or later or HSpice I-2013.12-1 or later +1) ngspice-25 or later or HSpice I-2013.12-1 or later 2) Python 2.7 and higher (currently excludes Python 3 and up) 3) a setup script for each technology 4) a technology directory for each technology with the base cells diff --git a/compiler/TODO b/compiler/TODO index e8750fbc..5526f91a 100644 --- a/compiler/TODO +++ b/compiler/TODO @@ -29,4 +29,12 @@ hierarchical_predecode3x8 to hierarchical_predecode class Fix stimuli.py to be more readable. Change the delay measurement to be from the negative clock edge to -remove the dependency on the clock period. \ No newline at end of file +remove the dependency on the clock period. + +Remove duplicate clock inverter in MS flop. + +Make lib file have delay relative to negedge for DATA. Must update +timing code too. + +Convert characterizer into a Python package + diff --git a/compiler/calibre.py b/compiler/calibre.py index 17dd45a5..5b9e17b5 100644 --- a/compiler/calibre.py +++ b/compiler/calibre.py @@ -90,6 +90,7 @@ def run_drc(name, gds_name): f.close() # run drc + cwd = os.getcwd() os.chdir(OPTS.openram_temp) errfile = "%s%s.drc.err" % (OPTS.openram_temp, name) outfile = "%s%s.drc.out" % (OPTS.openram_temp, name) @@ -98,6 +99,7 @@ def run_drc(name, gds_name): OPTS.calibre_exe, OPTS.openram_temp, errfile, outfile) debug.info(1, cmd) os.system(cmd) + os.chdir(cwd) # check the result for these lines in the summary: # TOTAL Original Layer Geometries: 106 (157) @@ -163,6 +165,7 @@ def run_lvs(name, gds_name, sp_name): f.close() # run LVS + cwd = os.getcwd() os.chdir(OPTS.openram_temp) errfile = "%s%s.lvs.err" % (OPTS.openram_temp, name) outfile = "%s%s.lvs.out" % (OPTS.openram_temp, name) @@ -171,6 +174,7 @@ def run_lvs(name, gds_name, sp_name): OPTS.openram_temp, errfile, outfile) debug.info(2, cmd) os.system(cmd) + os.chdir(cwd) # check the result for these lines in the summary: f = open(lvs_runset['lvsReportFile'], "r") @@ -265,6 +269,7 @@ def run_pex(name, gds_name, sp_name, output=None): f.close() # run pex + cwd = os.getcwd() os.chdir(OPTS.openram_temp) errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name) outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name) @@ -275,6 +280,7 @@ def run_pex(name, gds_name, sp_name, output=None): outfile) debug.info(2, cmd) os.system(cmd) + os.chdir(cwd) # also check the output file f = open(outfile, "r") diff --git a/compiler/characterizer/charutils.py b/compiler/characterizer/charutils.py index 8f5952e7..009e1d82 100644 --- a/compiler/characterizer/charutils.py +++ b/compiler/characterizer/charutils.py @@ -27,7 +27,11 @@ def relative_compare(value1,value2): def parse_output(filename, key): """Parses a hspice output.lis file for a key value""" - f = open("{0}/{1}.lis".format(OPTS.openram_temp, filename), "r") + full_filename="{0}{1}.lis".format(OPTS.openram_temp, filename) + try: + f = open(full_filename, "r") + except IOError: + debug.error("Unable to open spice output file: {0}".format(full_filename),1) contents = f.read() val = re.search(r"{0}\s*=\s*(-?\d+.?\d*\S*)\s+.*".format(key), contents) if val != None: diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index e140ab24..d737d2c9 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -6,6 +6,7 @@ import tech import math import stimuli import charutils as ch +import utils OPTS = globals.get_opts() @@ -262,20 +263,11 @@ class delay(): # run until the last cycle time end_time = self.cycle_times[-1] self.sf.write(".TRAN 5p {0}n\n".format(end_time)) - - if OPTS.spice_version == "hspice": - # create plots for all signals - self.sf.write(".OPTIONS POST=1 PROBE\n") - self.sf.write(".probe V(*)\n") - # end the stimulus file - self.sf.write(".end\n") - self.sf.close() - else: - self.sf.write(".control\n") - self.sf.write("run\n") - self.sf.write("quit\n") - self.sf.write(".endc\n") - self.sf.write(".end\n") + self.sf.write(".OPTIONS POST=1 PROBE\n") + # create plots for all signals + self.sf.write(".probe V(*)\n") + # end the stimulus file + self.sf.write(".end\n") @@ -353,20 +345,19 @@ class delay(): target_period = 0.5 * (ub_period + lb_period) debug.info(1, "MinPeriod Search: {0}ns (ub: {1} lb: {2})".format(target_period, - ub_period, - lb_period)) + ub_period, + lb_period)) (success, delay_out) = self.try_period(feasible_period, target_period, data_value) if success: - if ch.relative_compare(ub_period, target_period): - # use the two values to compare, but only return the ub since it is guaranteed feasible - (success, delay_out) = self.try_period(feasible_period, ub_period, data_value) - return (ub_period, delay_out) - fail_flag = False ub_period = target_period else: lb_period = target_period + if ch.relative_compare(ub_period, lb_period): + # use the two values to compare, but only return the ub since it is guaranteed feasible + (success, delay_out) = self.try_period(feasible_period, ub_period, data_value) + return (ub_period, delay_out) self.error("Should not reach here.",-1) return (target_period, delay_out) diff --git a/compiler/characterizer/setup_hold.py b/compiler/characterizer/setup_hold.py index 2ce38411..999a3a95 100644 --- a/compiler/characterizer/setup_hold.py +++ b/compiler/characterizer/setup_hold.py @@ -165,20 +165,12 @@ class setup_hold(): def write_control(self, period): # transient window end_time = 2 * period - self.sf.write(".TRAN 1n {0}n\n".format(end_time)) + self.sf.write(".TRAN 5p {0}n\n".format(end_time)) self.sf.write(".OPTIONS POST=1 PROBE\n") - - if OPTS.spice_version == "hspice": - self.sf.write(".probe V(*)\n") - # end the stimulus file - self.sf.write(".end\n") - else: - self.sf.write(".control\n") - self.sf.write("run\n") - self.sf.write("quit\n") - self.sf.write(".endc\n") - self.sf.write(".end\n") - + # create plots for all signals + self.sf.write(".probe V(*)\n") + # end the stimulus file + self.sf.write(".end\n") def bidir_search(self, correct_value, noise_margin, measure_name, mode): """ This will perform a bidirectional search for either setup or hold times. @@ -186,9 +178,11 @@ class setup_hold(): depending on whether we are doing setup or hold. """ period = tech.spice["feasible_period"] - + debug.info(2,"Feasible period from technology file: {0} ".format(period)) + + # The clock will start being offset by a period, so we want to look before and after - # theis time. + # this time by half a period. if mode == "HOLD": target_time = 1.5 * period lower_bound = 0.5*period @@ -212,6 +206,8 @@ class setup_hold(): setuphold_time = target_time - period else: setuphold_time = period - target_time + debug.info(2,"Checked initial {0} time {1}, data at {2}, clock at {3} ".format(mode,setuphold_time, + target_time,period)) debug.info(3,"Target time: {0} Low: {1} Up: {2} Measured: {3}".format(target_time, lower_bound, upper_bound, @@ -220,6 +216,10 @@ class setup_hold(): debug.error("Initial period/target hold time fails for data value",2) # We already found it feasible, so advance one step first thing. + debug.info(2,"Performing bidir search on {3} time: {2} LB: {0} UB: {1} ".format(lower_bound, + upper_bound, + setuphold_time, + mode)) if mode == "HOLD": target_time -= 0.5 * (upper_bound - lower_bound) else: @@ -269,6 +269,8 @@ class setup_hold(): setuphold_time = target_time - period else: setuphold_time = period - target_time + + debug.info(2,"Converged on {0} time {1}, data at {2}, clock at {3}.".format(mode,setuphold_time,target_time,period)) return setuphold_time diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 52fd3350..6116021c 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -445,23 +445,31 @@ def write_supply(stim_file, vdd_name, gnd_name, vdd_voltage, gnd_voltage): def run_sim(): """Run hspice in batch mode and output rawfile to parse.""" temp_stim = "{0}stim.sp".format(OPTS.openram_temp) + if OPTS.spice_version == "hspice": # TODO: Should make multithreading parameter a configuration option - cmd_args = "-mt 8 -i {1} -o {2}timing 2>&1 /dev/null".format(OPTS.spice_exe, + cmd = "{0} -mt 8 -i {1} -o {2}timing".format(OPTS.spice_exe, temp_stim, OPTS.openram_temp) + valid_retcode=0 else: - cmd_args = "-b -i {1} -o {2}timing.lis 2>&1 /dev/null".format(OPTS.spice_exe, - temp_stim, - OPTS.openram_temp) + cmd = "{0} -b -o {2}timing.lis {1}".format(OPTS.spice_exe, + temp_stim, + OPTS.openram_temp) + # for some reason, ngspice-25 returns 1 when it only has acceptable warnings + valid_retcode=1 - FNULL = open(os.devnull, 'w') - debug.info(2, OPTS.spice_exe + " " + cmd_args) - retcode = subprocess.call([OPTS.spice_exe, cmd_args], stdout=FNULL, stderr=FNULL) - FNULL.close() + + spice_stdout = open("{0}spice_stdout.log".format(OPTS.openram_temp), 'w') + spice_stderr = open("{0}spice_stderr.log".format(OPTS.openram_temp), 'w') - if (retcode > 0): - debug.error("Spice simulation error: " + OPTS.spice_exe + " " + cmd_args) - sys.exit(-1) + debug.info(3, cmd) + retcode = subprocess.call(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True) + + spice_stdout.close() + spice_stderr.close() + + if (retcode > valid_retcode): + debug.error("Spice simulation error: " + cmd, -1) diff --git a/compiler/contact.py b/compiler/contact.py index 4553ff91..0f3b78bb 100644 --- a/compiler/contact.py +++ b/compiler/contact.py @@ -18,7 +18,7 @@ class contact(design.design): dimensions[1], contact.unique_contact_id) design.design.__init__(self, name) - debug.info(2, "create contact object {0}".format(name)) + debug.info(3, "create contact object {0}".format(name)) contact.unique_contact_id += 1 self.layer_stack = layer_stack diff --git a/compiler/globals.py b/compiler/globals.py index 2e0f160e..2d8a9667 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -14,19 +14,6 @@ import importlib # Current version of OpenRAM. VERSION = "1.0" -# Output banner for file output and program execution. -BANNER = """\ -############################################################## -# # -# OpenRAM Compiler v""" + VERSION + """ # -# # -# VLSI Design Automation Lab # -# UCSC CE Department # -# # -# VLSI Computer Architecture Research Group # -# Oklahoma State University ECE Department # -# # -##############################################################\n""" USAGE = "usage: openram.py [options] \n" @@ -81,6 +68,25 @@ def parse_args(): def get_opts(): return(OPTS) +def print_banner(): + """ Conditionally print the banner to stdout """ + global OPTS + if not OPTS.print_banner: + return + + print "|==============================================================================|" + name = "OpenRAM Compiler v"+VERSION + print "|=========" + name.center(60) + "=========|" + print "|=========" + " ".center(60) + "=========|" + print "|=========" + "VLSI Design and Automation Lab".center(60) + "=========|" + print "|=========" + "University of California Santa Cruz CE Department".center(60) + "=========|" + print "|=========" + " ".center(60) + "=========|" + print "|=========" + "VLSI Computer Architecture Research Group".center(60) + "=========|" + print "|=========" + "Oklahoma State University ECE Department".center(60) + "=========|" + print "|=========" + " ".center(60) + "=========|" + print "|=========" + OPTS.openram_temp.center(60) + "=========|" + print "|==============================================================================|" + def init_openram(config_file): """Initialize the technology, paths, simulators, etc.""" @@ -140,7 +146,6 @@ def end_openram(): def cleanup_paths(): # we should clean up this temp directory after execution... - if os.path.exists(OPTS.openram_temp): shutil.rmtree(OPTS.openram_temp, ignore_errors=True) @@ -191,23 +196,48 @@ def set_spice(): debug.info(2,"Finding spice...") global OPTS - # set the input dir for spice files if using ngspice (not needed for - # hspice) + OPTS.spice_exe = "" + + # Check if the preferred spice option exists in the path + for path in os.environ["PATH"].split(os.pathsep): + spice_exe = os.path.join(path, OPTS.spice_version) + # if it is found, then break and use first version + if is_exe(spice_exe): + debug.info(1, "Using spice: " + spice_exe) + OPTS.spice_exe = spice_exe + break + + if not OPTS.force_spice and OPTS.spice_exe == "": + # if we didn't find the preferred version, try the other version and warn + prev_version=OPTS.spice_version + if OPTS.spice_version == "hspice": + OPTS.spice_version = "ngspice" + else: + OPTS.spice_version = "hspice" + debug.warning("Unable to find {0} so trying {1}".format(prev_version,OPTS.spice_version)) + + for path in os.environ["PATH"].split(os.pathsep): + spice_exe = os.path.join(path, OPTS.spice_version) + # if it is found, then break and use first version + if is_exe(spice_exe): + found_spice = True + debug.info(1, "Using spice: " + spice_exe) + OPTS.spice_exe = spice_exe + break + + # set the input dir for spice files if using ngspice if OPTS.spice_version == "ngspice": os.environ["NGSPICE_INPUT_DIR"] = "{0}".format(OPTS.openram_temp) - # search for calibre in the path - for path in os.environ["PATH"].split(os.pathsep): - OPTS.spice_exe = os.path.join(path, OPTS.spice_version) - # if it is found, then break and use first version - if is_exe(OPTS.spice_exe): - debug.info(1, "Using spice: " + OPTS.spice_exe) - break - else: + if OPTS.spice_exe == "": # otherwise, give warning and procede - debug.warning("Spice not found. Unable to perform characterization.") - + if OPTS.force_spice: + debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_version),1) + else: + debug.error("Neither hspice/ngspice not found. Unable to perform characterization.",1) + + # imports correct technology directories for testing def import_tech(): global OPTS diff --git a/compiler/hierarchy_layout.py b/compiler/hierarchy_layout.py index 420df8cd..a9ed0e99 100644 --- a/compiler/hierarchy_layout.py +++ b/compiler/hierarchy_layout.py @@ -245,14 +245,14 @@ class layout: Otherwise, start a new layout for dynamic generation.""" # open the gds file if it exists or else create a blank layout if os.path.isfile(self.gds_file): - debug.info(2, "opening %s" % self.gds_file) + debug.info(3, "opening %s" % self.gds_file) self.gds = gdsMill.VlsiLayout(units=GDS["unit"]) reader = gdsMill.Gds2reader(self.gds) reader.loadFromFile(self.gds_file) # TODO: parse the width/height # TODO: parse the pin locations else: - debug.info(2, "creating structure %s" % self.name) + debug.info(3, "creating structure %s" % self.name) self.gds = gdsMill.VlsiLayout( name=self.name, units=GDS["unit"]) diff --git a/compiler/hierarchy_spice.py b/compiler/hierarchy_spice.py index 857b5ec7..78fc56e0 100644 --- a/compiler/hierarchy_spice.py +++ b/compiler/hierarchy_spice.py @@ -68,7 +68,7 @@ class spice: """Reads the sp file (and parse the pins) from the library Otherwise, initialize it to null for dynamic generation""" if os.path.isfile(self.sp_file): - debug.info(2, "opening {0}".format(self.sp_file)) + debug.info(3, "opening {0}".format(self.sp_file)) f = open(self.sp_file) self.spice = f.readlines() for i in range(len(self.spice)): diff --git a/compiler/openram.py b/compiler/openram.py index cbff2bf4..f9f6e2f4 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -33,9 +33,8 @@ import debug if len(args) < 1: print globals.USAGE sys.exit(2) - -if OPTS.print_banner: - print globals.BANNER + +globals.print_banner() globals.init_openram(args[0]) @@ -94,7 +93,7 @@ s.gds_write(gdsname) # Run Characterizer on the design sram_file = spname -if OPTS.run_pex: +if OPTS.use_pex: sram_file = OPTS.out_path + "temp_pex.sp" calibre.run_pex(s.name, gdsname, spname, output=sram_file) diff --git a/compiler/options.py b/compiler/options.py index f8060a67..ffe7f01d 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -6,6 +6,7 @@ class options(optparse.Values): """ Class for holding all of the OpenRAM options. """ + # This is the technology directory. openram_tech = "" # This is the name of the technology. @@ -19,6 +20,8 @@ class options(optparse.Values): check_lvsdrc = True # Variable to select the variant of spice (hspice or ngspice right now) spice_version = "hspice" + # Should we fall back if we can't find our preferred spice? + force_spice = False # Should we print out the banner at startup print_banner = True # The Calibre executable being used which is derived from the user PATH. @@ -26,7 +29,7 @@ class options(optparse.Values): # The spice executable being used which is derived from the user PATH. spice_exe = "" # Run with extracted parasitics - run_pex = False + use_pex = False # Trim noncritical memory cells for simulation speed-up trim_noncritical = False # Define the output file paths diff --git a/compiler/path.py b/compiler/path.py index 57409f50..fb08fd36 100644 --- a/compiler/path.py +++ b/compiler/path.py @@ -20,7 +20,7 @@ class path(design.design): name = "path_{0}".format(path.unique_path_id) path.unique_path_id += 1 design.design.__init__(self, name) - debug.info(2, "create path obj {0}".format(name)) + debug.info(3, "create path obj {0}".format(name)) self.name = name self.layer_name = layer diff --git a/compiler/ptx.py b/compiler/ptx.py index f6d29027..3ffa2d69 100644 --- a/compiler/ptx.py +++ b/compiler/ptx.py @@ -16,7 +16,7 @@ class ptx(design.design): name = "{0}{1}".format(name, ptx.unique_mos_id) ptx.unique_mos_id += 1 design.design.__init__(self, name) - debug.info(2, "create ptx structure {0}".format(name)) + debug.info(3, "create ptx structure {0}".format(name)) self.tx_type = tx_type self.mults = mults diff --git a/compiler/tests/00_code_format_check_test.py b/compiler/tests/00_code_format_check_test.py index b732edde..04ea2e99 100644 --- a/compiler/tests/00_code_format_check_test.py +++ b/compiler/tests/00_code_format_check_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2.7 import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py index 31bfedcc..e394d84b 100644 --- a/compiler/tests/01_library_drc_test.py +++ b/compiler/tests/01_library_drc_test.py @@ -2,7 +2,7 @@ "Run a regresion test the library cells for DRC" import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/02_library_lvs_test.py b/compiler/tests/02_library_lvs_test.py index 0cba32b4..734784e0 100644 --- a/compiler/tests/02_library_lvs_test.py +++ b/compiler/tests/02_library_lvs_test.py @@ -2,7 +2,7 @@ "Run a regresion test the library cells for LVS" import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/03_contact_test.py b/compiler/tests/03_contact_test.py index 8e0c71ff..85acc10a 100644 --- a/compiler/tests/03_contact_test.py +++ b/compiler/tests/03_contact_test.py @@ -2,7 +2,7 @@ "Run a regresion test for DRC on basic contacts of different array sizes" import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/03_path_test.py b/compiler/tests/03_path_test.py index c4394c2b..64767f3f 100644 --- a/compiler/tests/03_path_test.py +++ b/compiler/tests/03_path_test.py @@ -2,7 +2,7 @@ "Run a regresion test on a basic path" import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/03_ptx_1finger_nmos_test.py b/compiler/tests/03_ptx_1finger_nmos_test.py index 02d74bb5..3f023020 100644 --- a/compiler/tests/03_ptx_1finger_nmos_test.py +++ b/compiler/tests/03_ptx_1finger_nmos_test.py @@ -2,7 +2,7 @@ "Run a regresion test on a basic parameterized transistors" import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/03_ptx_1finger_pmos_test.py b/compiler/tests/03_ptx_1finger_pmos_test.py index abe206b5..4bb3e312 100644 --- a/compiler/tests/03_ptx_1finger_pmos_test.py +++ b/compiler/tests/03_ptx_1finger_pmos_test.py @@ -2,7 +2,7 @@ "Run a regresion test on a basic parameterized transistors" import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/03_ptx_3finger_nmos_test.py b/compiler/tests/03_ptx_3finger_nmos_test.py index d60a72ab..17ec9092 100644 --- a/compiler/tests/03_ptx_3finger_nmos_test.py +++ b/compiler/tests/03_ptx_3finger_nmos_test.py @@ -2,7 +2,7 @@ "Run a regresion test on a basic parameterized transistors" import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/03_ptx_3finger_pmos_test.py b/compiler/tests/03_ptx_3finger_pmos_test.py index e8519be0..f889527d 100644 --- a/compiler/tests/03_ptx_3finger_pmos_test.py +++ b/compiler/tests/03_ptx_3finger_pmos_test.py @@ -2,7 +2,7 @@ "Run a regresion test on a basic parameterized transistors" import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/03_wire_test.py b/compiler/tests/03_wire_test.py index 2e64591b..d9856b43 100644 --- a/compiler/tests/03_wire_test.py +++ b/compiler/tests/03_wire_test.py @@ -2,7 +2,7 @@ "Run a regresion test on a basic wire" import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/04_nand_2_test.py b/compiler/tests/04_nand_2_test.py index bed8a98d..aa8d6c08 100644 --- a/compiler/tests/04_nand_2_test.py +++ b/compiler/tests/04_nand_2_test.py @@ -6,7 +6,7 @@ size 2_input nand gate that is nmos_width=2*tech.drc[minwidth_tx]. """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/04_nand_3_test.py b/compiler/tests/04_nand_3_test.py index b46f9c84..87ba75a0 100644 --- a/compiler/tests/04_nand_3_test.py +++ b/compiler/tests/04_nand_3_test.py @@ -6,7 +6,7 @@ It generate only the minimum size 3_input nand gate that is nmos_width=3*tech.dr """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/04_nor_2_test.py b/compiler/tests/04_nor_2_test.py index b0edc49a..d866cede 100644 --- a/compiler/tests/04_nor_2_test.py +++ b/compiler/tests/04_nor_2_test.py @@ -5,7 +5,7 @@ This module doesn't generate multi_finger 2_input nor gate It generate only the minimum size 2_input nor gate that is nmos_width=2*tech.drc[minwidth_tx] """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/04_pinv_test.py b/compiler/tests/04_pinv_test.py index a7ea8fcd..de20a27d 100644 --- a/compiler/tests/04_pinv_test.py +++ b/compiler/tests/04_pinv_test.py @@ -4,7 +4,7 @@ Run regresion tests on a parameterized inverter """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/04_wordline_driver_test.py b/compiler/tests/04_wordline_driver_test.py index 591ea631..b1a5c470 100644 --- a/compiler/tests/04_wordline_driver_test.py +++ b/compiler/tests/04_wordline_driver_test.py @@ -4,7 +4,7 @@ Run a regresion test on a wordline_driver array """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py index 4d080423..6ec0c7d4 100644 --- a/compiler/tests/05_bitcell_array_test.py +++ b/compiler/tests/05_bitcell_array_test.py @@ -4,7 +4,7 @@ Run a regresion test on a basic array """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/06_hierarchical_decoder_test.py b/compiler/tests/06_hierarchical_decoder_test.py index 5b4e60de..649a1fd9 100644 --- a/compiler/tests/06_hierarchical_decoder_test.py +++ b/compiler/tests/06_hierarchical_decoder_test.py @@ -4,7 +4,7 @@ Run a regresion test on a thierarchy_decoder. """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/06_hierarchical_predecode2x4_test.py b/compiler/tests/06_hierarchical_predecode2x4_test.py index 596265cc..551a1fb0 100644 --- a/compiler/tests/06_hierarchical_predecode2x4_test.py +++ b/compiler/tests/06_hierarchical_predecode2x4_test.py @@ -4,7 +4,7 @@ Run a regresion test on a hierarchical_predecode2x4. """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/06_hierarchical_predecode3x8_test.py b/compiler/tests/06_hierarchical_predecode3x8_test.py index cb3cffc4..50162d31 100644 --- a/compiler/tests/06_hierarchical_predecode3x8_test.py +++ b/compiler/tests/06_hierarchical_predecode3x8_test.py @@ -4,7 +4,7 @@ Run a regresion test on a hierarchical_predecode3x8. """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/07_single_level_column_mux_test.py b/compiler/tests/07_single_level_column_mux_test.py index 798a7c9b..490a3497 100644 --- a/compiler/tests/07_single_level_column_mux_test.py +++ b/compiler/tests/07_single_level_column_mux_test.py @@ -4,7 +4,7 @@ Run a regresion test on a single transistor column_mux. """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/08_precharge_array_test.py b/compiler/tests/08_precharge_array_test.py index 41aaf993..308dc937 100644 --- a/compiler/tests/08_precharge_array_test.py +++ b/compiler/tests/08_precharge_array_test.py @@ -4,7 +4,7 @@ Run a regresion test on a precharge array """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/09_sense_amp_array_test.py b/compiler/tests/09_sense_amp_array_test.py index 5272ae19..80536e16 100644 --- a/compiler/tests/09_sense_amp_array_test.py +++ b/compiler/tests/09_sense_amp_array_test.py @@ -4,7 +4,7 @@ Run a regresion test on a sense amp array """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/10_write_driver_array_test.py b/compiler/tests/10_write_driver_array_test.py index b65967ae..ca289e30 100644 --- a/compiler/tests/10_write_driver_array_test.py +++ b/compiler/tests/10_write_driver_array_test.py @@ -4,7 +4,7 @@ Run a regresion test on a write driver array """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/11_ms_flop_array_test.py b/compiler/tests/11_ms_flop_array_test.py index cc770bf1..9f282278 100644 --- a/compiler/tests/11_ms_flop_array_test.py +++ b/compiler/tests/11_ms_flop_array_test.py @@ -4,7 +4,7 @@ Run a regresion test on a dff_array. """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/13_control_logic_test.py b/compiler/tests/13_control_logic_test.py index 5e0e393f..8d308ace 100644 --- a/compiler/tests/13_control_logic_test.py +++ b/compiler/tests/13_control_logic_test.py @@ -4,7 +4,7 @@ Run a regresion test on a control_logic """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/14_logic_effort_dc_test.py b/compiler/tests/14_logic_effort_dc_test.py index d277748d..0ce27871 100644 --- a/compiler/tests/14_logic_effort_dc_test.py +++ b/compiler/tests/14_logic_effort_dc_test.py @@ -4,7 +4,7 @@ Run a test on a delay chain """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/15_tri_gate_array_test.py b/compiler/tests/15_tri_gate_array_test.py index dcb52bc7..1b7c8440 100644 --- a/compiler/tests/15_tri_gate_array_test.py +++ b/compiler/tests/15_tri_gate_array_test.py @@ -4,7 +4,7 @@ Run a regresion test on a tri_gate_array. """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/16_replica_bitline_test.py b/compiler/tests/16_replica_bitline_test.py index 1f3b97a9..6e0d943e 100644 --- a/compiler/tests/16_replica_bitline_test.py +++ b/compiler/tests/16_replica_bitline_test.py @@ -4,7 +4,7 @@ Run a test on a delay chain """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/19_bank_test.py b/compiler/tests/19_bank_test.py index 74e6d7a3..bfeeef61 100644 --- a/compiler/tests/19_bank_test.py +++ b/compiler/tests/19_bank_test.py @@ -4,7 +4,7 @@ Run a regresion test on various srams """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/20_sram_1bank_test.py b/compiler/tests/20_sram_1bank_test.py index 797573d8..261fa315 100644 --- a/compiler/tests/20_sram_1bank_test.py +++ b/compiler/tests/20_sram_1bank_test.py @@ -4,7 +4,7 @@ Run a regresion test on a 1 bank SRAM """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/20_sram_2bank_test.py b/compiler/tests/20_sram_2bank_test.py index e5788177..ce0e1c07 100644 --- a/compiler/tests/20_sram_2bank_test.py +++ b/compiler/tests/20_sram_2bank_test.py @@ -4,7 +4,7 @@ Run a regresion test on a 2 bank SRAM """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/20_sram_4bank_test.py b/compiler/tests/20_sram_4bank_test.py index 4e23772a..8603cd8a 100644 --- a/compiler/tests/20_sram_4bank_test.py +++ b/compiler/tests/20_sram_4bank_test.py @@ -4,7 +4,7 @@ Run a regresion test on a 4 bank SRAM """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/21_timing_delay_test.py b/compiler/tests/21_hspice_delay_test.py similarity index 90% rename from compiler/tests/21_timing_delay_test.py rename to compiler/tests/21_hspice_delay_test.py index 11a63318..c1354790 100644 --- a/compiler/tests/21_timing_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -4,7 +4,7 @@ Run a regresion test on various srams """ import unittest -from header import header +from testutils import header,isclose import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals @@ -22,8 +22,10 @@ class timing_sram_test(unittest.TestCase): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) # we will manually run lvs/drc OPTS.check_lvsdrc = False - OPTS.use_pex = False - + OPTS.spice_version="hspice" + OPTS.force_spice = True + globals.set_spice() + import sram debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") @@ -60,15 +62,9 @@ class timing_sram_test(unittest.TestCase): self.assertTrue(False) # other techs fail os.remove(tempspice) - + globals.end_openram() - -def isclose(value1,value2): - """ This is used to compare relative values for convergence. """ - return (abs(value1 - value2) / max(value1,value2) <= 1e-2) - - # instantiate a copdsay of the class to actually run the test if __name__ == "__main__": (OPTS, args) = globals.parse_args() diff --git a/compiler/tests/21_timing_hold_test.py b/compiler/tests/21_hspice_hold_test.py similarity index 85% rename from compiler/tests/21_timing_hold_test.py rename to compiler/tests/21_hspice_hold_test.py index 9c87f3a7..533a0afd 100644 --- a/compiler/tests/21_timing_hold_test.py +++ b/compiler/tests/21_hspice_hold_test.py @@ -4,7 +4,7 @@ Run a regresion test on various srams """ import unittest -from header import header +from testutils import header,isclose import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals @@ -22,7 +22,9 @@ class timing_setup_test(unittest.TestCase): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) # we will manually run lvs/drc OPTS.check_lvsdrc = False - OPTS.use_pex = False + OPTS.spice_version="hspice" + OPTS.force_spice = True + globals.set_spice() import sram import setup_hold @@ -42,11 +44,6 @@ class timing_setup_test(unittest.TestCase): self.assertTrue(False) # other techs fail globals.end_openram() - -def isclose(value1,value2): - """ This is used to compare relative values for convergence. """ - return (abs(value1 - value2) / max(value1,value2) <= 1e-2) - # instantiate a copdsay of the class to actually run the test if __name__ == "__main__": diff --git a/compiler/tests/21_timing_setup_test.py b/compiler/tests/21_hspice_setup_test.py similarity index 86% rename from compiler/tests/21_timing_setup_test.py rename to compiler/tests/21_hspice_setup_test.py index ffa6b91b..6e264531 100644 --- a/compiler/tests/21_timing_setup_test.py +++ b/compiler/tests/21_hspice_setup_test.py @@ -4,7 +4,7 @@ Run a regresion test on various srams """ import unittest -from header import header +from testutils import header,isclose import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals @@ -20,9 +20,12 @@ class timing_setup_test(unittest.TestCase): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) + # we will manually run lvs/drc OPTS.check_lvsdrc = False - OPTS.use_pex = False + OPTS.spice_version="hspice" + OPTS.force_spice = True + globals.set_spice() import sram import setup_hold @@ -42,11 +45,6 @@ class timing_setup_test(unittest.TestCase): globals.end_openram() -def isclose(value1,value2): - """ This is used to compare relative values for convergence. """ - return (abs(value1 - value2) / max(value1,value2) <= 1e-2) - - # instantiate a copdsay of the class to actually run the test if __name__ == "__main__": (OPTS, args) = globals.parse_args() diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py new file mode 100644 index 00000000..50985119 --- /dev/null +++ b/compiler/tests/21_ngspice_delay_test.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python2.7 +""" +Run a regresion test on various srams +""" + +import unittest +from testutils import header,isclose +import sys,os +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +import debug +import calibre + +OPTS = globals.get_opts() + +#@unittest.skip("SKIPPING 21_ngspice_delay_test") +class timing_sram_test(unittest.TestCase): + + def runTest(self): + globals.init_openram("config_20_{0}".format(OPTS.tech_name)) + # we will manually run lvs/drc + OPTS.check_lvsdrc = False + OPTS.spice_version="ngspice" + OPTS.force_spice = True + globals.set_spice() + + import sram + + debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") + s = sram.sram(word_size=OPTS.config.word_size, + num_words=OPTS.config.num_words, + num_banks=OPTS.config.num_banks, + name="test_sram1") + + # reset these options + OPTS.check_lvsdrc = True + OPTS.spice_version="hspice" + OPTS.force_spice = False + globals.set_spice() + + import delay + + tempspice = OPTS.openram_temp + "temp.sp" + s.sp_write(tempspice) + + probe_address = "1" * s.addr_size + probe_data = s.word_size - 1 + debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data)) + + d = delay.delay(s,tempspice) + data = d.analyze(probe_address, probe_data) + + if OPTS.tech_name == "freepdk45": + self.assertTrue(isclose(data['delay1'],0.013649)) # diff than hspice + self.assertTrue(isclose(data['delay0'],0.22893)) # diff than hspice + self.assertTrue(isclose(data['min_period1'],0.078582763671875)) # diff than hspice + self.assertTrue(isclose(data['min_period0'],0.25543212890625)) # diff than hspice + elif OPTS.tech_name == "scn3me_subm": + self.assertTrue(isclose(data['delay1'],1.5342000000000002)) # diff than hspice + self.assertTrue(isclose(data['delay0'],2.2698)) # diff than hspice + self.assertTrue(isclose(data['min_period1'],1.534423828125)) # diff than hspice + self.assertTrue(isclose(data['min_period0'],2.99560546875)) # diff than hspice + else: + self.assertTrue(False) # other techs fail + + os.remove(tempspice) + +# instantiate a copdsay of the class to actually run the test +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main() diff --git a/compiler/tests/21_ngspice_hold_test.py b/compiler/tests/21_ngspice_hold_test.py new file mode 100644 index 00000000..f8c891ee --- /dev/null +++ b/compiler/tests/21_ngspice_hold_test.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python2.7 +""" +Run a regresion test on various srams +""" + +import unittest +from testutils import header,isclose +import sys,os +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +import debug +import calibre + +OPTS = globals.get_opts() + +#@unittest.skip("SKIPPING 21_timing_sram_test") + + +class timing_setup_test(unittest.TestCase): + + def runTest(self): + globals.init_openram("config_20_{0}".format(OPTS.tech_name)) + # we will manually run lvs/drc + OPTS.check_lvsdrc = False + OPTS.spice_version="ngspice" + OPTS.force_spice = True + globals.set_spice() + + import sram + import setup_hold + + sh = setup_hold.setup_hold() + [one_setup_time, zero_setup_time] = sh.hold_time() + + # reset these options + OPTS.check_lvsdrc = True + OPTS.spice_version="hspice" + OPTS.force_spice = False + globals.set_spice() + + if OPTS.tech_name == "freepdk45": + self.assertTrue(isclose(one_setup_time,-0.0048828125)) + self.assertTrue(isclose(zero_setup_time,-0.010986328125)) + elif OPTS.tech_name == "scn3me_subm": + self.assertTrue(isclose(one_setup_time,0.45654296875)) # diff than hspice + self.assertTrue(isclose(zero_setup_time,-0.0830078125)) + else: + self.assertTrue(False) # other techs fail + +# instantiate a copdsay of the class to actually run the test +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main() diff --git a/compiler/tests/21_ngspice_setup_test.py b/compiler/tests/21_ngspice_setup_test.py new file mode 100644 index 00000000..79d1b218 --- /dev/null +++ b/compiler/tests/21_ngspice_setup_test.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python2.7 +""" +Run a regresion test on various srams +""" + +import unittest +from testutils import header,isclose +import sys,os +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +import debug +import calibre + +OPTS = globals.get_opts() + +#@unittest.skip("SKIPPING 21_timing_sram_test") + + +class timing_setup_test(unittest.TestCase): + + def runTest(self): + globals.init_openram("config_20_{0}".format(OPTS.tech_name)) + # we will manually run lvs/drc + OPTS.check_lvsdrc = False + OPTS.spice_version="ngspice" + OPTS.force_spice = True + globals.set_spice() + + import sram + import setup_hold + + sh = setup_hold.setup_hold() + [one_setup_time, zero_setup_time] = sh.setup_time() + + # reset these options + OPTS.check_lvsdrc = True + OPTS.spice_version="hspice" + OPTS.force_spice = False + globals.set_spice() + + if OPTS.tech_name == "freepdk45": + self.assertTrue(isclose(one_setup_time,0.0146484375)) + self.assertTrue(isclose(zero_setup_time,0.008544921875)) + elif OPTS.tech_name == "scn3me_subm": + self.assertTrue(isclose(one_setup_time,0.09521484375)) #diff than hspice + self.assertTrue(isclose(zero_setup_time,-0.0244140625)) + else: + self.assertTrue(False) # other techs fail + +# instantiate a copdsay of the class to actually run the test +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main() diff --git a/compiler/tests/22_pex_func_test_with_pinv.py b/compiler/tests/22_pex_func_test_with_pinv.py index e613d03b..f9410eea 100644 --- a/compiler/tests/22_pex_func_test_with_pinv.py +++ b/compiler/tests/22_pex_func_test_with_pinv.py @@ -4,7 +4,7 @@ Run a regression test on an extracted SRAM to ensure functionality. """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals diff --git a/compiler/tests/22_sram_func_test.py b/compiler/tests/22_sram_func_test.py index 24f47ee7..bc4b876b 100644 --- a/compiler/tests/22_sram_func_test.py +++ b/compiler/tests/22_sram_func_test.py @@ -4,7 +4,7 @@ Run a regresion test on various srams """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals @@ -22,7 +22,6 @@ class sram_func_test(unittest.TestCase): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) # we will manually run lvs/drc OPTS.check_lvsdrc = False - OPTS.use_pex = False import sram diff --git a/compiler/tests/23_lib_sram_test.py b/compiler/tests/23_lib_sram_test.py index 0611a4e4..6ad3041a 100644 --- a/compiler/tests/23_lib_sram_test.py +++ b/compiler/tests/23_lib_sram_test.py @@ -4,7 +4,7 @@ Check the .lib file for an SRAM """ import unittest -from header import header +from testutils import header,isdiff import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals @@ -20,11 +20,9 @@ class lib_test(unittest.TestCase): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) # we will manually run lvs/drc OPTS.check_lvsdrc = False - OPTS.use_pex = False import sram import lib - import filecmp debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank") s = sram.sram(word_size=2, @@ -33,18 +31,16 @@ class lib_test(unittest.TestCase): name="sram_2_16_1_{0}".format(OPTS.tech_name)) OPTS.check_lvsdrc = True - tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) - curpath=os.path.dirname(os.path.realpath(__file__)) + "/" filename = s.name + ".lib" - libname = curpath + filename + libname = OPTS.openram_temp + filename lib.lib(libname,s,tempspice) # let's diff the result with a golden model golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename) - self.assertEqual(filecmp.cmp(libname,golden),True) + self.assertEqual(isdiff(libname,golden),True) os.system("rm {0}".format(libname)) diff --git a/compiler/tests/24_lef_sram_test.py b/compiler/tests/24_lef_sram_test.py index 5fb82f70..5c08d72e 100644 --- a/compiler/tests/24_lef_sram_test.py +++ b/compiler/tests/24_lef_sram_test.py @@ -4,7 +4,7 @@ Check the LEF file for an SRMA """ import unittest -from header import header +from testutils import header,isdiff import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals @@ -23,7 +23,6 @@ class lef_test(unittest.TestCase): import sram import lef - import filecmp debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank") s = sram.sram(word_size=2, @@ -33,17 +32,16 @@ class lef_test(unittest.TestCase): OPTS.check_lvsdrc = True - curpath=os.path.dirname(os.path.realpath(__file__)) + "/" gdsfile = s.name + ".gds" leffile = s.name + ".lef" - gdsname = curpath + gdsfile - lefname = curpath + leffile + gdsname = OPTS.openram_temp + gdsfile + lefname = OPTS.openram_temp + leffile s.gds_write(gdsname) lef.lef(gdsname,lefname,s) # let's diff the result with a golden model golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),leffile) - self.assertEqual(filecmp.cmp(lefname,golden),True) + self.assertEqual(isdiff(lefname,golden),True) os.system("rm {0}".format(gdsname)) os.system("rm {0}".format(lefname)) diff --git a/compiler/tests/25_verilog_sram_test.py b/compiler/tests/25_verilog_sram_test.py index 496b89d9..cf042089 100644 --- a/compiler/tests/25_verilog_sram_test.py +++ b/compiler/tests/25_verilog_sram_test.py @@ -4,7 +4,7 @@ Check the .v file for an SRAM """ import unittest -from header import header +from testutils import header,isdiff import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals @@ -23,7 +23,6 @@ class verilog_test(unittest.TestCase): import sram import verilog - import filecmp debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank") s = sram.sram(word_size=2, @@ -33,15 +32,14 @@ class verilog_test(unittest.TestCase): OPTS.check_lvsdrc = True - curpath=os.path.dirname(os.path.realpath(__file__)) + "/" vfile = s.name + ".v" - vname = curpath + vfile + vname = OPTS.openram_temp + vfile verilog.verilog(vname,s) # let's diff the result with a golden model golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),vfile) - self.assertEqual(filecmp.cmp(vname,golden),True) + self.assertEqual(isdiff(vname,golden),True) os.system("rm {0}".format(vname)) diff --git a/compiler/tests/30_openram_test.py b/compiler/tests/30_openram_test.py index 9e032441..575cd39b 100644 --- a/compiler/tests/30_openram_test.py +++ b/compiler/tests/30_openram_test.py @@ -6,7 +6,7 @@ check that these files are right. """ import unittest -from header import header +from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals @@ -24,10 +24,8 @@ class openram_test(unittest.TestCase): debug.info(1, "Testing top-level openram.py with 2-bit, 16 word SRAM.") out_file = "testsram" - # get the directory under the test modules - out_path=os.path.dirname(os.path.realpath(__file__)) # make a temp directory for output - out_path += "/testsram" + out_path = OPTS.openram_temp + out_file # make sure we start without the files existing if os.path.exists(out_path): diff --git a/compiler/tests/header.py b/compiler/tests/header.py deleted file mode 100644 index 194a301d..00000000 --- a/compiler/tests/header.py +++ /dev/null @@ -1,10 +0,0 @@ - -def header(str, tec): - tst = "Running Test for:" - print "\n" - print " ______________________________________________________________________________ " - print "|==============================================================================|" - print "|=========" + tst.center(60) + "=========|" - print "|=========" + tec.center(60) + "=========|" - print "|=========" + str.center(60) + "=========|" - print "|==============================================================================|" diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index d0307116..5b958faf 100644 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -9,8 +9,8 @@ import globals (OPTS, args) = globals.parse_args() del sys.argv[1:] -import header -header.header(__file__, OPTS.tech_name) +from testutils import header +header(__file__, OPTS.tech_name) # get a list of all files in the tests directory files = os.listdir(sys.path[0]) diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py new file mode 100644 index 00000000..7b8e2cc6 --- /dev/null +++ b/compiler/tests/testutils.py @@ -0,0 +1,43 @@ + + +def isclose(value1,value2,error_tolerance=1e-2): + """ This is used to compare relative values. """ + import debug + relative_diff = abs(value1 - value2) / max(value1,value2) + check = relative_diff <= error_tolerance + if not check: + debug.info(1,"NOT CLOSE {0} {1} relative diff={2}".format(value1,value2,relative_diff)) + else: + debug.info(2,"CLOSE {0} {1} relative diff={2}".format(value1,value2,relative_diff)) + return (check) + +def isdiff(file1,file2): + """ This is used to compare two files and display the diff if they are different.. """ + import debug + import filecmp + import difflib + check = filecmp.cmp(file1,file2) + if not check: + debug.info(2,"MISMATCH {0} {1}".format(file1,file2)) + f1 = open(file1,"r") + s1 = f1.readlines() + f2 = open(file2,"r") + s2 = f2.readlines() + for line in difflib.unified_diff(s1, s2): + debug.error(line) + else: + debug.info(2,"MATCH {0} {1}".format(file1,file2)) + return (check) + +def header(filename, technology): + tst = "Running Test for:" + print "\n" + print " ______________________________________________________________________________ " + print "|==============================================================================|" + print "|=========" + tst.center(60) + "=========|" + print "|=========" + technology.center(60) + "=========|" + print "|=========" + filename.center(60) + "=========|" + import globals + OPTS = globals.get_opts() + print "|=========" + OPTS.openram_temp.center(60) + "=========|" + print "|==============================================================================|" diff --git a/compiler/utils.py b/compiler/utils.py index 4f00563a..5034cb53 100644 --- a/compiler/utils.py +++ b/compiler/utils.py @@ -41,3 +41,7 @@ def auto_measure_libcell(pin_list, name, units, layer): for pin in pin_list: cell[str(pin)] = gdsPinToOffset(cell_vlsi.readPin(str(pin))) return cell + + + + diff --git a/compiler/wire.py b/compiler/wire.py index 541fa50a..51a2ae91 100644 --- a/compiler/wire.py +++ b/compiler/wire.py @@ -20,7 +20,7 @@ class wire(path): name = "wire_{0}".format(wire.unique_wire_id) wire.unique_wire_id += 1 design.design.__init__(self, name) - debug.info(2, "create wire obj {0}".format(name)) + debug.info(3, "create wire obj {0}".format(name)) self.layer_stack = layer_stack self.position_list = position_list diff --git a/technology/setup_scripts/setup_openram_freepdk45.py b/technology/setup_scripts/setup_openram_freepdk45.py index 6488d604..6c010ae9 100644 --- a/technology/setup_scripts/setup_openram_freepdk45.py +++ b/technology/setup_scripts/setup_openram_freepdk45.py @@ -23,7 +23,8 @@ os.environ["MGC_TMPDIR"] = "/tmp" #OpenRAM Paths DRCLVS_HOME= PDK_DIR+"/ncsu_basekit/techfile/calibre" -os.environ["DRCLVS_HOME"] = DRCLVS_HOME +os.environ["DRCLVS_HOME"] = DRCLVS_HOME + os.environ["SPICE_MODEL_DIR"] = PDK_DIR+"/ncsu_basekit/models/hspice/tran_models/models_nom" ########################## diff --git a/technology/setup_scripts/setup_openram_scn3me_subm.py b/technology/setup_scripts/setup_openram_scn3me_subm.py index 2ea082a3..da5d1374 100644 --- a/technology/setup_scripts/setup_openram_scn3me_subm.py +++ b/technology/setup_scripts/setup_openram_scn3me_subm.py @@ -21,8 +21,12 @@ os.environ["MGC_TMPDIR"] = "/tmp" # OpenRAM Paths OPENRAM_TECH=os.path.abspath(os.environ.get("OPENRAM_TECH")) DRCLVS_HOME=OPENRAM_TECH+"/scn3me_subm/tech" -os.environ["DRCLVS_HOME"] = DRCLVS_HOME -os.environ["SPICE_MODEL_DIR"] = "/mada/software/techfiles/scn3me_subm" +os.environ["DRCLVS_HOME"] = DRCLVS_HOME +# You can override the spice model diretory in the environment +try: + SPICE_MODEL_DIR = os.path.abspath(os.environ.get("SPICE_MODEL_DIR")) +except: + os.environ["SPICE_MODEL_DIR"] = "/mada/software/techfiles/scn3me_subm" ########################## # Paths required for OPENRAM to function