From 88740c107fa65f227ced4fc70044c1ee755a3627 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 16 Nov 2017 13:52:58 -0800 Subject: [PATCH] Improve global and code structure using modules. Comment and reorganize globals.py Tests consistently use globals module for OPTions. Add characterizer as module support. Modify unit tests to reload new characterizer for ngspice/hspice. Enable relative and absolute config file arguments so you can run openram from anywhere on any config file. --- compiler/characterizer/charutils.py | 4 +- compiler/characterizer/delay.py | 4 +- compiler/characterizer/lib.py | 4 +- compiler/characterizer/setup_hold.py | 4 +- compiler/characterizer/stimuli.py | 4 +- compiler/debug.py | 2 +- compiler/design.py | 3 +- compiler/globals.py | 58 ++++++++++--------- compiler/tests/03_ptx_1finger_nmos_test.py | 3 +- .../07_single_level_column_mux_array_test.py | 3 +- compiler/tests/08_precharge_array_test.py | 2 +- compiler/tests/09_sense_amp_array_test.py | 3 +- compiler/tests/10_write_driver_array_test.py | 3 +- compiler/tests/11_ms_flop_array_test.py | 3 +- compiler/tests/12_tri_gate_array_test.py | 3 +- compiler/tests/13_replica_bitline_test.py | 3 +- compiler/tests/14_delay_chain_test.py | 5 +- compiler/tests/16_control_logic_test.py | 4 +- compiler/tests/19_multi_bank_test.py | 5 +- compiler/tests/19_single_bank_test.py | 3 +- compiler/tests/20_sram_1bank_test.py | 3 +- compiler/tests/20_sram_2bank_test.py | 3 +- compiler/tests/20_sram_4bank_test.py | 3 +- compiler/tests/21_hspice_delay_test.py | 12 ++-- compiler/tests/21_hspice_setuphold_test.py | 17 +++--- compiler/tests/21_ngspice_delay_test.py | 9 +-- compiler/tests/21_ngspice_setuphold_test.py | 11 ++-- compiler/tests/22_pex_func_test_with_pinv.py | 3 +- compiler/tests/22_sram_func_test.py | 13 +++-- compiler/tests/23_lib_sram_model_test.py | 8 +-- compiler/tests/23_lib_sram_prune_test.py | 13 +++-- compiler/tests/23_lib_sram_test.py | 14 ++--- compiler/tests/24_lef_sram_test.py | 3 +- compiler/tests/25_verilog_sram_test.py | 3 +- compiler/tests/30_openram_test.py | 5 +- compiler/tests/config_20_freepdk45.py | 2 +- compiler/tests/config_20_scn3me_subm.py | 2 +- compiler/tests/testutils.py | 3 +- compiler/verify/assura.py | 42 +++++++------- compiler/verify/calibre.py | 22 +++---- compiler/verify/magic.py | 20 +++---- 41 files changed, 152 insertions(+), 182 deletions(-) diff --git a/compiler/characterizer/charutils.py b/compiler/characterizer/charutils.py index d933ba7c..a763737c 100644 --- a/compiler/characterizer/charutils.py +++ b/compiler/characterizer/charutils.py @@ -1,8 +1,6 @@ -import globals import re import debug - -OPTS = globals.get_opts() +from globals import OPTS def relative_compare(value1,value2,error_tolerance=0.001): diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index f519809e..03f0eda2 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1,14 +1,12 @@ import sys import re -import globals import debug import tech import math import stimuli import charutils as ch import utils - -OPTS = globals.get_opts() +from globals import OPTS class delay(): """ diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 7cece91a..b2a87479 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -1,7 +1,6 @@ import os import sys import re -import globals import debug import tech import math @@ -11,8 +10,7 @@ import charutils as ch import tech import numpy as np from trim_spice import trim_spice - -OPTS = globals.get_opts() +from globals import OPTS class lib: """ lib file generation.""" diff --git a/compiler/characterizer/setup_hold.py b/compiler/characterizer/setup_hold.py index e0c43ffd..919bb9b9 100644 --- a/compiler/characterizer/setup_hold.py +++ b/compiler/characterizer/setup_hold.py @@ -1,12 +1,10 @@ import sys -import globals import tech import stimuli import debug import charutils as ch import ms_flop - -OPTS = globals.get_opts() +from globals import OPTS class setup_hold(): diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index ec6c00f0..ec735abe 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -4,15 +4,13 @@ simulation. There are various functions that can be be used to generate stimulus for other simulations as well. """ -import globals import tech import debug import subprocess import os import sys import numpy as np - -OPTS = globals.get_opts() +from globals import OPTS vdd_voltage = tech.spice["supply_voltage"] gnd_voltage = tech.spice["gnd_voltage"] diff --git a/compiler/debug.py b/compiler/debug.py index f36a8df2..a5502fda 100644 --- a/compiler/debug.py +++ b/compiler/debug.py @@ -30,7 +30,7 @@ def warning(str): def info(lev, str): - OPTS = globals.get_opts() + from globals import OPTS if (OPTS.debug_level >= lev): frm = inspect.stack()[1] mod = inspect.getmodule(frm[0]) diff --git a/compiler/design.py b/compiler/design.py index 15096de0..e655c570 100644 --- a/compiler/design.py +++ b/compiler/design.py @@ -4,8 +4,7 @@ import globals import verify import debug import os - -OPTS = globals.get_opts() +from globals import OPTS class design(hierarchy_spice.spice, hierarchy_layout.layout): diff --git a/compiler/globals.py b/compiler/globals.py index d169c496..d1f9c556 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -25,12 +25,8 @@ minor_python_version = sys.version_info.minor if not (major_python_version == 2 and minor_python_version >= 7): debug.error("Python 2.7 is required.",-1) -# parse the optional arguments -# this only does the optional arguments - - def parse_args(): - """Parse the arguments and initialize openram""" + """ Parse the optional arguments for OpenRAM """ global OPTS @@ -57,8 +53,8 @@ def parse_args(): help="Use analytical models to calculate delays (default)"), optparse.make_option("-c", "--characterize", action="store_false", dest="analytical_delay", help="Perform characterization to calculate delays (default is analytical models)") + # -h --help is implicit. } -# -h --help is implicit. parser = optparse.OptionParser(option_list=option_list, description="Compile and/or characterize an SRAM.", @@ -72,13 +68,8 @@ def parse_args(): if OPTS.tech_name == "": OPTS.tech_name = "freepdk45" - return (options, args) - -def get_opts(): - return(OPTS) - def print_banner(): """ Conditionally print the banner to stdout """ global OPTS @@ -112,14 +103,15 @@ def init_openram(config_file): def get_tool(tool_type, preferences): """ - Find which tool we have from a list of preferences and return the full path. + Find which tool we have from a list of preferences and return the + one selected and its full path. """ debug.info(2,"Finding {} tool...".format(tool_type)) global OPTS for name in preferences: exe_name = find_exe(name) - if exe_name!="": + if exe_name != None: debug.info(1, "Using {0}: {1}".format(tool_type,exe_name)) return(name,exe_name) else: @@ -130,17 +122,29 @@ def get_tool(tool_type, preferences): def read_config(config_file): - global OPTS - - OPTS.config_file = config_file - OPTS.config_file = re.sub(r'\.py$', "", OPTS.config_file) + """ + Read the configuration file that defines a few parameters. The + config file is just a Python file that defines some config + options. + """ - # dynamically import the configuration file of which modules to use - debug.info(1, "Configuration file is " + OPTS.config_file + ".py") + # Create a full path relative to current dir unless it is already an abs path + if not os.path.isabs(config_file): + config_file = os.getcwd() + "/" + config_file + # Make it a python file if the base name was only given + config_file = re.sub(r'\.py$', "", config_file) + # Expand the user if it is used + config_file = os.path.expanduser(config_file) + # Add the path to the system path so we can import things in the other directory + dir_name = os.path.dirname(config_file) + file_name = os.path.basename(config_file) + sys.path.append(dir_name) + # Import the configuration file of which modules to use + debug.info(1, "Configuration file is " + config_file + ".py") try: - OPTS.config = importlib.import_module(OPTS.config_file) + OPTS.config = importlib.import_module(file_name) except: - debug.error("Unable to read configuration file: {0}".format(OPTS.config_file+".py. Did you specify the technology?"),2) + debug.error("Unable to read configuration file: {0}".format(config_file),2) # This path must be setup after the config file. try: @@ -177,7 +181,9 @@ def end_openram(): def cleanup_paths(): - # we should clean up this temp directory after execution... + """ + We should clean up the temp directory after execution. + """ if os.path.exists(OPTS.openram_temp): shutil.rmtree(OPTS.openram_temp, ignore_errors=True) @@ -199,9 +205,6 @@ def setup_paths(): debug.check(os.path.isdir(OPENRAM_HOME+"/tests"), "$OPENRAM_HOME/tests does not exist: {0}".format(OPENRAM_HOME+"/tests")) sys.path.append("{0}/tests".format(OPENRAM_HOME)) - debug.check(os.path.isdir(OPENRAM_HOME+"/characterizer"), - "$OPENRAM_HOME/characterizer does not exist: {0}".format(OPENRAM_HOME+"/characterizer")) - sys.path.append("{0}/characterizer".format(OPENRAM_HOME)) debug.check(os.path.isdir(OPENRAM_HOME+"/router"), "$OPENRAM_HOME/router does not exist: {0}".format(OPENRAM_HOME+"/router")) sys.path.append("{0}/router".format(OPENRAM_HOME)) @@ -221,17 +224,18 @@ def setup_paths(): def is_exe(fpath): + """ Return true if the given is an executable file that exists. """ return os.path.exists(fpath) and os.access(fpath, os.X_OK) def find_exe(check_exe): - """ Check if the binary exists in the path and return the full path. """ + """ Check if the binary exists in any path dir and return the full path. """ # Check if the preferred spice option exists in the path for path in os.environ["PATH"].split(os.pathsep): exe = os.path.join(path, check_exe) # if it is found, then break and use first version if is_exe(exe): return exe - return "" + return None # imports correct technology directories for testing def import_tech(): diff --git a/compiler/tests/03_ptx_1finger_nmos_test.py b/compiler/tests/03_ptx_1finger_nmos_test.py index 7f8e16f6..fccbc41d 100644 --- a/compiler/tests/03_ptx_1finger_nmos_test.py +++ b/compiler/tests/03_ptx_1finger_nmos_test.py @@ -146,8 +146,7 @@ class ptx_test(unittest.TestCase): self.assertFalse(verify.run_drc(fet.name, tempgds)) - os.remove(tempspice) - os.remove(tempgds) + globals.end_openram() # instantiate a copy of the class to actually run the test if __name__ == "__main__": diff --git a/compiler/tests/07_single_level_column_mux_array_test.py b/compiler/tests/07_single_level_column_mux_array_test.py index fd92951c..c03a5d28 100644 --- a/compiler/tests/07_single_level_column_mux_array_test.py +++ b/compiler/tests/07_single_level_column_mux_array_test.py @@ -8,11 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - class single_level_column_mux_test(unittest.TestCase): diff --git a/compiler/tests/08_precharge_array_test.py b/compiler/tests/08_precharge_array_test.py index 1f3d3e2d..c5e70aba 100644 --- a/compiler/tests/08_precharge_array_test.py +++ b/compiler/tests/08_precharge_array_test.py @@ -8,10 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() #@unittest.skip("SKIPPING 08_precharge_test") diff --git a/compiler/tests/09_sense_amp_array_test.py b/compiler/tests/09_sense_amp_array_test.py index 9947c950..7d80efb6 100644 --- a/compiler/tests/09_sense_amp_array_test.py +++ b/compiler/tests/09_sense_amp_array_test.py @@ -8,11 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 09_sense_amp_test") diff --git a/compiler/tests/10_write_driver_array_test.py b/compiler/tests/10_write_driver_array_test.py index 752ff5da..dab8c2e2 100644 --- a/compiler/tests/10_write_driver_array_test.py +++ b/compiler/tests/10_write_driver_array_test.py @@ -8,11 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 10_write_driver_test") diff --git a/compiler/tests/11_ms_flop_array_test.py b/compiler/tests/11_ms_flop_array_test.py index 70ffff53..ce24f49a 100644 --- a/compiler/tests/11_ms_flop_array_test.py +++ b/compiler/tests/11_ms_flop_array_test.py @@ -8,12 +8,11 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify import importlib -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 20_sram_test") diff --git a/compiler/tests/12_tri_gate_array_test.py b/compiler/tests/12_tri_gate_array_test.py index eb42ab8e..534e1656 100644 --- a/compiler/tests/12_tri_gate_array_test.py +++ b/compiler/tests/12_tri_gate_array_test.py @@ -8,11 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - class tri_gate_array_test(unittest.TestCase): diff --git a/compiler/tests/13_replica_bitline_test.py b/compiler/tests/13_replica_bitline_test.py index 66ca8bc2..a82d95b5 100644 --- a/compiler/tests/13_replica_bitline_test.py +++ b/compiler/tests/13_replica_bitline_test.py @@ -8,12 +8,11 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify import importlib -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 14_delay_chain_test") diff --git a/compiler/tests/14_delay_chain_test.py b/compiler/tests/14_delay_chain_test.py index e71d4d61..888b4442 100644 --- a/compiler/tests/14_delay_chain_test.py +++ b/compiler/tests/14_delay_chain_test.py @@ -8,14 +8,11 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 14_delay_chain_test") - - class delay_chain_test(unittest.TestCase): def runTest(self): diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index 4a4b9850..0d23bef6 100644 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -8,12 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - - class control_logic_test(unittest.TestCase): def runTest(self): diff --git a/compiler/tests/19_multi_bank_test.py b/compiler/tests/19_multi_bank_test.py index a15d9be6..9dbbf276 100644 --- a/compiler/tests/19_multi_bank_test.py +++ b/compiler/tests/19_multi_bank_test.py @@ -8,13 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - - - class multi_bank_test(unittest.TestCase): def runTest(self): diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py index 90b60952..4e5ba00f 100644 --- a/compiler/tests/19_single_bank_test.py +++ b/compiler/tests/19_single_bank_test.py @@ -8,11 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 20_sram_test") diff --git a/compiler/tests/20_sram_1bank_test.py b/compiler/tests/20_sram_1bank_test.py index 5330b859..7e19161d 100644 --- a/compiler/tests/20_sram_1bank_test.py +++ b/compiler/tests/20_sram_1bank_test.py @@ -8,11 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 20_sram_test") diff --git a/compiler/tests/20_sram_2bank_test.py b/compiler/tests/20_sram_2bank_test.py index 93596593..f29d2038 100644 --- a/compiler/tests/20_sram_2bank_test.py +++ b/compiler/tests/20_sram_2bank_test.py @@ -8,11 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 20_sram_test") diff --git a/compiler/tests/20_sram_4bank_test.py b/compiler/tests/20_sram_4bank_test.py index a6d9e657..7539f10e 100644 --- a/compiler/tests/20_sram_4bank_test.py +++ b/compiler/tests/20_sram_4bank_test.py @@ -8,11 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 20_sram_test") diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index d86f53dc..3b39d958 100644 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -8,11 +8,10 @@ from testutils import header,isclose import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 21_timing_sram_test") @@ -80,18 +79,15 @@ class timing_sram_test(unittest.TestCase): for k in data.keys(): if type(data[k])==list: for i in range(len(data[k])): - self.assertTrue(isclose(data[k][i],golden_data[k][i])) + self.assertTrue(isclose(data[k][i],golden_data[k][i],0.10)) else: - self.assertTrue(isclose(data[k],golden_data[k])) + self.assertTrue(isclose(data[k],golden_data[k],0.10)) # reset these options OPTS.check_lvsdrc = True - OPTS.spice_version="hspice" OPTS.analytical_delay = True - globals.set_spice() - - os.remove(tempspice) + reload(characterizer) globals.end_openram() diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py index 2d49f4d1..9b40729c 100644 --- a/compiler/tests/21_hspice_setuphold_test.py +++ b/compiler/tests/21_hspice_setuphold_test.py @@ -8,11 +8,10 @@ from testutils import header,isclose import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 21_timing_sram_test") @@ -23,14 +22,16 @@ class timing_setup_test(unittest.TestCase): # we will manually run lvs/drc OPTS.check_lvsdrc = False - from characterizer import delay + OPTS.spice_version="hspice" + OPTS.analytical_delay = False + import characterizer + reload(characterizer) + from characterizer import setup_hold import sram import tech slews = [tech.spice["rise_time"]*2] - import setup_hold - sh = setup_hold.setup_hold() data = sh.analyze(slews,slews) @@ -53,11 +54,13 @@ class timing_setup_test(unittest.TestCase): for k in data.keys(): if type(data[k])==list: for i in range(len(data[k])): - self.assertTrue(isclose(data[k][i],golden_data[k][i])) + self.assertTrue(isclose(data[k][i],golden_data[k][i],0.10)) else: - self.assertTrue(isclose(data[k],golden_data[k])) + self.assertTrue(isclose(data[k],golden_data[k],0.10)) OPTS.check_lvsdrc = True + OPTS.analytical_delay = True + reload(characterizer) globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 12daa90b..78bad910 100644 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -8,11 +8,10 @@ from testutils import header,isclose import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 21_ngspice_delay_test") class timing_sram_test(unittest.TestCase): @@ -77,9 +76,9 @@ class timing_sram_test(unittest.TestCase): for k in data.keys(): if type(data[k])==list: for i in range(len(data[k])): - self.assertTrue(isclose(data[k][i],golden_data[k][i])) + self.assertTrue(isclose(data[k][i],golden_data[k][i],0.10)) else: - self.assertTrue(isclose(data[k],golden_data[k])) + self.assertTrue(isclose(data[k],golden_data[k]),0.10) # reset these options OPTS.check_lvsdrc = True @@ -87,8 +86,6 @@ class timing_sram_test(unittest.TestCase): OPTS.analytical_delay = True reload(characterizer) - os.remove(tempspice) - globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/21_ngspice_setuphold_test.py b/compiler/tests/21_ngspice_setuphold_test.py index 23620028..bbf0f18a 100644 --- a/compiler/tests/21_ngspice_setuphold_test.py +++ b/compiler/tests/21_ngspice_setuphold_test.py @@ -8,11 +8,10 @@ from testutils import header,isclose import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 21_timing_sram_test") @@ -20,9 +19,11 @@ 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.analytical_delay = False # This is a hack to reload the characterizer __init__ with the spice version import characterizer reload(characterizer) @@ -54,14 +55,14 @@ class timing_setup_test(unittest.TestCase): for k in data.keys(): if type(data[k])==list: for i in range(len(data[k])): - self.assertTrue(isclose(data[k][i],golden_data[k][i])) + self.assertTrue(isclose(data[k][i],golden_data[k][i],0.10)) else: - self.assertTrue(isclose(data[k],golden_data[k])) + self.assertTrue(isclose(data[k],golden_data[k],0.10)) # reset these options OPTS.check_lvsdrc = True OPTS.spice_version="hspice" - + OPTS.analytical_delay = True reload(characterizer) globals.end_openram() diff --git a/compiler/tests/22_pex_func_test_with_pinv.py b/compiler/tests/22_pex_func_test_with_pinv.py index 917af2ba..6e75e81b 100644 --- a/compiler/tests/22_pex_func_test_with_pinv.py +++ b/compiler/tests/22_pex_func_test_with_pinv.py @@ -8,11 +8,10 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - @unittest.skip("SKIPPING 22_sram_func_test") class sram_func_test(unittest.TestCase): diff --git a/compiler/tests/22_sram_func_test.py b/compiler/tests/22_sram_func_test.py index f56e8fa0..be5ce574 100644 --- a/compiler/tests/22_sram_func_test.py +++ b/compiler/tests/22_sram_func_test.py @@ -8,21 +8,26 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - #@unittest.skip("SKIPPING 21_timing_sram_test") class sram_func_test(unittest.TestCase): def runTest(self): - OPTS.analytical_delay = False globals.init_openram("config_20_{0}".format(OPTS.tech_name)) + # we will manually run lvs/drc OPTS.check_lvsdrc = False + OPTS.spice_version="hspice" + OPTS.analytical_delay = False + import characterizer + reload(characterizer) + from characterizer import delay + import sram debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") @@ -32,7 +37,6 @@ class sram_func_test(unittest.TestCase): name="sram_func_test") OPTS.check_lvsdrc = True - import delay tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) @@ -52,6 +56,7 @@ class sram_func_test(unittest.TestCase): os.remove(tempspice) OPTS.analytical_delay = True + reload(characterizer) globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/23_lib_sram_model_test.py b/compiler/tests/23_lib_sram_model_test.py index 9cd5be3b..d33a7bb8 100644 --- a/compiler/tests/23_lib_sram_model_test.py +++ b/compiler/tests/23_lib_sram_model_test.py @@ -8,12 +8,10 @@ from testutils import header,isapproxdiff import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - - class lib_test(unittest.TestCase): def runTest(self): @@ -22,7 +20,7 @@ class lib_test(unittest.TestCase): OPTS.check_lvsdrc = False import sram - import lib + from characterizer import lib debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank") s = sram.sram(word_size=2, @@ -43,8 +41,6 @@ class lib_test(unittest.TestCase): # Randomly decided 1% difference between spice simulators is ok. self.assertEqual(isapproxdiff(libname,golden,0.01),True) - os.system("rm {0}".format(libname)) - globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/23_lib_sram_prune_test.py b/compiler/tests/23_lib_sram_prune_test.py index 082331a7..d975027b 100644 --- a/compiler/tests/23_lib_sram_prune_test.py +++ b/compiler/tests/23_lib_sram_prune_test.py @@ -8,22 +8,23 @@ from testutils import header,isapproxdiff import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - - class lib_test(unittest.TestCase): def runTest(self): - OPTS.analytical_delay = False globals.init_openram("config_20_{0}".format(OPTS.tech_name)) # we will manually run lvs/drc OPTS.check_lvsdrc = False + OPTS.spice_version="hspice" + OPTS.analytical_delay = False + import characterizer + reload(characterizer) + from characterizer import lib import sram - import lib debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank") s = sram.sram(word_size=2, @@ -44,8 +45,8 @@ class lib_test(unittest.TestCase): # 15% worked in freepdk, but scmos needed 20% self.assertEqual(isapproxdiff(libname,golden,0.20),True) - os.system("rm {0}".format(libname)) OPTS.analytical_delay = True + reload(characterizer) globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/23_lib_sram_test.py b/compiler/tests/23_lib_sram_test.py index d4d49335..7e869b7f 100644 --- a/compiler/tests/23_lib_sram_test.py +++ b/compiler/tests/23_lib_sram_test.py @@ -8,23 +8,23 @@ from testutils import header,isapproxdiff import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - - class lib_test(unittest.TestCase): def runTest(self): - OPTS.analytical_delay = False - OPTS.trim_netlist = False globals.init_openram("config_20_{0}".format(OPTS.tech_name)) # we will manually run lvs/drc OPTS.check_lvsdrc = False + OPTS.analytical_delay = False + OPTS.trim_netlist = False + import characterizer + reload(characterizer) + from characterizer import lib import sram - import lib debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank") s = sram.sram(word_size=2, @@ -45,9 +45,9 @@ class lib_test(unittest.TestCase): # Randomly decided 10% difference between spice simulators is ok. self.assertEqual(isapproxdiff(libname,golden,0.10),True) - os.system("rm {0}".format(libname)) OPTS.analytical_delay = True OPTS.trim_netlist = True + reload(characterizer) globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/24_lef_sram_test.py b/compiler/tests/24_lef_sram_test.py index 9fb169f9..33f7bc5d 100644 --- a/compiler/tests/24_lef_sram_test.py +++ b/compiler/tests/24_lef_sram_test.py @@ -8,11 +8,10 @@ from testutils import header,isdiff import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - class lef_test(unittest.TestCase): diff --git a/compiler/tests/25_verilog_sram_test.py b/compiler/tests/25_verilog_sram_test.py index 418b6b79..7203c339 100644 --- a/compiler/tests/25_verilog_sram_test.py +++ b/compiler/tests/25_verilog_sram_test.py @@ -8,11 +8,10 @@ from testutils import header,isdiff import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import verify -OPTS = globals.get_opts() - class verilog_test(unittest.TestCase): diff --git a/compiler/tests/30_openram_test.py b/compiler/tests/30_openram_test.py index 575cd39b..027fcf87 100644 --- a/compiler/tests/30_openram_test.py +++ b/compiler/tests/30_openram_test.py @@ -10,13 +10,12 @@ from testutils import header import sys,os sys.path.append(os.path.join(sys.path[0],"..")) import globals +from globals import OPTS import debug import os import re import shutil -OPTS = globals.get_opts() - class openram_test(unittest.TestCase): def runTest(self): @@ -73,7 +72,7 @@ class openram_test(unittest.TestCase): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# instantiate a copy of the class to actually run the test if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/config_20_freepdk45.py b/compiler/tests/config_20_freepdk45.py index 9f92fae9..71a655a7 100644 --- a/compiler/tests/config_20_freepdk45.py +++ b/compiler/tests/config_20_freepdk45.py @@ -5,7 +5,7 @@ num_banks = 1 tech_name = "freepdk45" # Optional, will be over-ridden on command line. -output_path = "/tmp/mysram" +output_path = "/tmp/freepdk45_sram" output_name = "sram_2_16_1_freepdk45" decoder = "hierarchical_decoder" diff --git a/compiler/tests/config_20_scn3me_subm.py b/compiler/tests/config_20_scn3me_subm.py index 8bcb7027..fefc8474 100644 --- a/compiler/tests/config_20_scn3me_subm.py +++ b/compiler/tests/config_20_scn3me_subm.py @@ -5,7 +5,7 @@ num_banks = 1 tech_name = "scn3me_subm" # Optional, will be over-ridden on command line. -output_path = "/tmp/mysram" +output_path = "/tmp/scn3me_subm_mysram" output_name = "sram_2_16_1_scn3me_subm" decoder = "hierarchical_decoder" diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index 9588dccd..63b98f95 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -110,7 +110,6 @@ def header(filename, technology): print "|=========" + tst.center(60) + "=========|" print "|=========" + technology.center(60) + "=========|" print "|=========" + filename.center(60) + "=========|" - import globals - OPTS = globals.get_opts() + from globals import OPTS print "|=========" + OPTS.openram_temp.center(60) + "=========|" print "|==============================================================================|" diff --git a/compiler/verify/assura.py b/compiler/verify/assura.py index a4f4a96d..27949721 100644 --- a/compiler/verify/assura.py +++ b/compiler/verify/assura.py @@ -1,11 +1,11 @@ """ -This is a DRC/LVS interface for Assura. It implements completely -independently two functions: run_drc and run_lvs, that perform these -functions in batch mode and will return true/false if the result -passes. All of the setup (the rules, temp dirs, etc.) should be -contained in this file. Replacing with another DRC/LVS tool involves -rewriting this code to work properly. Porting to a new technology in -Assura means pointing the code to the proper DRC and LVS rule files. +This is a DRC/LVS interface for Assura. It implements completely two +functions: run_drc and run_lvs, that perform these functions in batch +mode and will return true/false if the result passes. All of the setup +(the rules, temp dirs, etc.) should be contained in this file. +Replacing with another DRC/LVS tool involves rewriting this code to +work properly. Porting to a new technology in Assura means pointing +the code to the proper DRC and LVS rule files. LVS Notes: @@ -23,19 +23,16 @@ import os import re import time import debug -import globals - +from globals import OPTS def run_drc(name, gds_name): """Run DRC check on a given top-level name which is implemented in gds_name.""" - OPTS = globals.get_opts() from tech import drc - drc_rules = drc["drc_rules"] drc_runset = OPTS.openram_temp + name + ".rsf" - drc_log_file = "%s%s.log" % (OPTS.openram_temp, name) + drc_log_file = "{0}{1}.log".format(OPTS.openram_temp, name) # write the runset file # the runset file contains all the options to run Assura @@ -51,10 +48,10 @@ def run_drc(name, gds_name): f.write(")\n") f.write("\n") f.write("avParameters(\n") - f.write(" ?inputLayout ( \"gds2\" \"%s\" )\n" % (gds_name)) - f.write(" ?cellName \"%s\"\n" % (name)) - f.write(" ?workingDirectory \"%s\"\n" % (OPTS.openram_temp)) - f.write(" ?rulesFile \"%s\"\n" % (drc_rules)) + f.write(" ?inputLayout ( \"gds2\" \"{}\" )\n".format(gds_name)) + f.write(" ?cellName \"{}\"\n".format(name)) + f.write(" ?workingDirectory \"{}\"\n".format(OPTS.openram_temp)) + f.write(" ?rulesFile \"{}\"\n".format(drc_rules)) f.write(" ?set ( \"GridCheck\" )\n") f.write(" ?avrpt t\n") f.write(")\n") @@ -83,7 +80,7 @@ def run_drc(name, gds_name): debug.info(1, line) if errors > 0: - debug.error("Errors: %d" % (errors)) + debug.error("Errors: {}".format(errors)) return errors @@ -91,13 +88,12 @@ def run_drc(name, gds_name): def run_lvs(name, gds_name, sp_name): """Run LVS check on a given top-level name which is implemented in gds_name and sp_name. """ - OPTS = globals.get_opts() - from tech import drc - lvs_rules = drc["lvs_rules"] lvs_runset = OPTS.openram_temp + name + ".rsf" + # The LVS compare rules must be defined in the tech file for Assura. lvs_compare = drc["lvs_compare"] + # Define the must-connect names for disconnected LVS nets for Assura lvs_bindings = drc["lvs_bindings"] lvs_log_file = "{0}{1}.log".format(OPTS.openram_temp, name) # Needed when FET models are sub-circuits @@ -168,3 +164,9 @@ def run_lvs(name, gds_name, sp_name): debug.info(1, line) return errors + + +def run_pex(name, gds_name, sp_name, output=None): + """Run pex on a given top-level name which is + implemented in gds_name and sp_name. """ + debug.error("PEX extraction not implemented with Assura.",-1) diff --git a/compiler/verify/calibre.py b/compiler/verify/calibre.py index 2565dbfe..3eed8560 100644 --- a/compiler/verify/calibre.py +++ b/compiler/verify/calibre.py @@ -62,14 +62,13 @@ import os import re import time import debug -import globals +from globals import OPTS import subprocess def run_drc(name, gds_name): """Run DRC check on a given top-level name which is implemented in gds_name.""" - OPTS = globals.get_opts() # the runset file contains all the options to run calibre from tech import drc @@ -91,7 +90,7 @@ def run_drc(name, gds_name): # write the runset file f = open(OPTS.openram_temp + "drc_runset", "w") for k in sorted(drc_runset.iterkeys()): - f.write("*%s: %s\n" % (k, drc_runset[k])) + f.write("*{0}: {1}\n".format(k, drc_runset[k])) f.close() # run drc @@ -125,19 +124,21 @@ def run_drc(name, gds_name): # always display this summary if errors > 0: - debug.error("%-25s\tGeometries: %d\tChecks: %d\tErrors: %d" % - (name, geometries, rulechecks, errors)) + debug.error("{0}\tGeometries: {1}\tChecks: {2}\tErrors: {3}".format(name, + geometries, + rulechecks, + errors)) else: - debug.info(1, "%-25s\tGeometries: %d\tChecks: %d\tErrors: %d" % - (name, geometries, rulechecks, errors)) - + debug.info(1, "{0}\tGeometries: {1}\tChecks: {2}\tErrors: {3}".format(name, + geometries, + rulechecks, + errors)) return errors def run_lvs(name, gds_name, sp_name): """Run LVS check on a given top-level name which is implemented in gds_name and sp_name. """ - OPTS = globals.get_opts() from tech import drc lvs_rules = drc["lvs_rules"] lvs_runset = { @@ -167,7 +168,7 @@ def run_lvs(name, gds_name, sp_name): # write the runset file f = open(OPTS.openram_temp + "lvs_runset", "w") for k in sorted(lvs_runset.iterkeys()): - f.write("*%s: %s\n" % (k, lvs_runset[k])) + f.write("*{0}: {1}\n".format(k, lvs_runset[k])) f.close() # run LVS @@ -246,7 +247,6 @@ def run_lvs(name, gds_name, sp_name): def run_pex(name, gds_name, sp_name, output=None): """Run pex on a given top-level name which is implemented in gds_name and sp_name. """ - OPTS = globals.get_opts() from tech import drc if output == None: output = name + ".pex.netlist" diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 38894b5a..97044bc2 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -56,7 +56,7 @@ import os import re import time import debug -import globals +from globals import OPTS import subprocess @@ -66,12 +66,10 @@ def run_drc(name, gds_name): debug.warning("DRC using magic not implemented.") return 0 - OPTS = globals.get_opts() # the runset file contains all the options to run drc from tech import drc drc_rules = drc["drc_rules"] - drc_runset = { 'drcRulesFile': drc_rules, 'drcRunDir': OPTS.openram_temp, @@ -88,7 +86,7 @@ def run_drc(name, gds_name): # write the runset file f = open(OPTS.openram_temp + "drc_runset", "w") for k in sorted(drc_runset.iterkeys()): - f.write("*%s: %s\n" % (k, drc_runset[k])) + f.write("*{0}: {1}\n".format(k, drc_runset[k])) f.close() # run drc @@ -123,11 +121,15 @@ def run_drc(name, gds_name): # always display this summary if errors > 0: - debug.error("%-25s\tGeometries: %d\tChecks: %d\tErrors: %d" % - (name, geometries, rulechecks, errors)) + debug.error("{0}\tGeometries: {1}\tChecks: {2}\tErrors: {3}".format(name, + geometries, + rulechecks, + errors)) else: - debug.info(1, "%-25s\tGeometries: %d\tChecks: %d\tErrors: %d" % - (name, geometries, rulechecks, errors)) + debug.info(1, "{0}\tGeometries: {1}\tChecks: {2}\tErrors: {3}".format(name, + geometries, + rulechecks, + errors)) return errors @@ -139,7 +141,6 @@ def run_lvs(name, gds_name, sp_name): debug.warning("LVS using magic+netgen not implemented.") return 0 - OPTS = globals.get_opts() from tech import drc lvs_rules = drc["lvs_rules"] lvs_runset = { @@ -253,7 +254,6 @@ def run_pex(name, gds_name, sp_name, output=None): debug.warning("PEX using magic not implemented.") return 0 - OPTS = globals.get_opts() from tech import drc if output == None: output = name + ".pex.netlist"