Merge branch 'multiport_cleanup' of https://github.com/VLSIDA/PrivateRAM into multiport_cleanup

This commit is contained in:
Matt Guthaus 2018-07-11 14:27:06 -07:00
commit 22d40364ec
15 changed files with 138 additions and 46 deletions

View File

@ -1,16 +1,18 @@
import os import os
import debug import debug
import globals
from globals import OPTS,find_exe,get_tool from globals import OPTS,find_exe,get_tool
from .lib import * from .lib import *
from .delay import * from .delay import *
from .setup_hold import * from .setup_hold import *
debug.info(2,"Initializing characterizer...") debug.info(1,"Initializing characterizer...")
OPTS.spice_exe = "" OPTS.spice_exe = ""
if not OPTS.analytical_delay: if not OPTS.analytical_delay:
debug.info(1, "Finding spice simulator.")
if OPTS.spice_name != "": if OPTS.spice_name != "":
OPTS.spice_exe=find_exe(OPTS.spice_name) OPTS.spice_exe=find_exe(OPTS.spice_name)
if OPTS.spice_exe=="": if OPTS.spice_exe=="":
@ -24,6 +26,7 @@ if not OPTS.analytical_delay:
if OPTS.spice_exe == "": if OPTS.spice_exe == "":
debug.error("No recognizable spice version found. Unable to perform characterization.",1) debug.error("No recognizable spice version found. Unable to perform characterization.",1)
else:
debug.info(1,"Analytical model enabled.")

View File

@ -13,19 +13,19 @@ def check(check,str):
(frame, filename, line_number, function_name, lines, (frame, filename, line_number, function_name, lines,
index) = inspect.getouterframes(inspect.currentframe())[1] index) = inspect.getouterframes(inspect.currentframe())[1]
if not check: if not check:
print("ERROR: file {0}: line {1}: {2}".format(os.path.basename(filename),line_number,str)) sys.stderr.write("ERROR: file {0}: line {1}: {2}\n".format(os.path.basename(filename),line_number,str))
assert 0 assert 0
def error(str,return_value=0): def error(str,return_value=0):
(frame, filename, line_number, function_name, lines, (frame, filename, line_number, function_name, lines,
index) = inspect.getouterframes(inspect.currentframe())[1] index) = inspect.getouterframes(inspect.currentframe())[1]
print("ERROR: file {0}: line {1}: {2}".format(os.path.basename(filename),line_number,str)) sys.stderr.write("ERROR: file {0}: line {1}: {2}\n".format(os.path.basename(filename),line_number,str))
assert return_value==0 assert return_value==0
def warning(str): def warning(str):
(frame, filename, line_number, function_name, lines, (frame, filename, line_number, function_name, lines,
index) = inspect.getouterframes(inspect.currentframe())[1] index) = inspect.getouterframes(inspect.currentframe())[1]
print("WARNING: file {0}: line {1}: {2}".format(os.path.basename(filename),line_number,str)) sys.stderr.write("WARNING: file {0}: line {1}: {2}\n".format(os.path.basename(filename),line_number,str))
def info(lev, str): def info(lev, str):

View File

@ -105,6 +105,7 @@ def check_versions():
def init_openram(config_file, is_unit_test=True): def init_openram(config_file, is_unit_test=True):
"""Initialize the technology, paths, simulators, etc.""" """Initialize the technology, paths, simulators, etc."""
check_versions() check_versions()
debug.info(1,"Initializing OpenRAM...") debug.info(1,"Initializing OpenRAM...")
@ -119,6 +120,26 @@ def init_openram(config_file, is_unit_test=True):
import hierarchy_design import hierarchy_design
hierarchy_design.hierarchy_design.name_map=[] hierarchy_design.hierarchy_design.name_map=[]
global OPTS
global CHECKPOINT_OPTS
# This is a hack. If we are running a unit test and have checkpointed
# the options, load them rather than reading the config file.
# This way, the configuration is reloaded at the start of every unit test.
# If a unit test fails, we don't have to worry about restoring the old config values
# that may have been tested.
if is_unit_test and CHECKPOINT_OPTS:
OPTS.__dict__ = CHECKPOINT_OPTS.__dict__.copy()
return
# Import these to find the executables for checkpointing
import characterizer
import verify
# Make a checkpoint of the options so we can restore
# after each unit test
if not CHECKPOINT_OPTS:
CHECKPOINT_OPTS = copy.copy(OPTS)
def get_tool(tool_type, preferences): def get_tool(tool_type, preferences):
@ -147,16 +168,6 @@ def read_config(config_file, is_unit_test=True):
reads will just restore the previous copy (ask mrg) reads will just restore the previous copy (ask mrg)
""" """
global OPTS global OPTS
global CHECKPOINT_OPTS
# This is a hack. If we are running a unit test and have checkpointed
# the options, load them rather than reading the config file.
# This way, the configuration is reloaded at the start of every unit test.
# If a unit test fails, we don't have to worry about restoring the old config values
# that may have been tested.
if is_unit_test and CHECKPOINT_OPTS:
OPTS = copy.deepcopy(CHECKPOINT_OPTS)
return
# Create a full path relative to current dir unless it is already an abs path # Create a full path relative to current dir unless it is already an abs path
if not os.path.isabs(config_file): if not os.path.isabs(config_file):
@ -211,14 +222,15 @@ def read_config(config_file, is_unit_test=True):
except: except:
debug.error("Unable to make output directory.",-1) debug.error("Unable to make output directory.",-1)
# Make a checkpoint of the options so we can restore
# after each unit test
CHECKPOINT_OPTS = copy.deepcopy(OPTS)
def end_openram(): def end_openram():
""" Clean up openram for a proper exit """ """ Clean up openram for a proper exit """
cleanup_paths() cleanup_paths()
import verify
verify.print_drc_stats()
verify.print_lvs_stats()
verify.print_pex_stats()
@ -227,6 +239,7 @@ def cleanup_paths():
""" """
We should clean up the temp directory after execution. We should clean up the temp directory after execution.
""" """
global OPTS
if not OPTS.purge_temp: if not OPTS.purge_temp:
debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp)) debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp))
return return
@ -341,6 +354,8 @@ def print_time(name, now_time, last_time=None):
def report_status(): def report_status():
""" Check for valid arguments and report the info about the SRAM being generated """ """ Check for valid arguments and report the info about the SRAM being generated """
global OPTS
# Check if all arguments are integers for bits, size, banks # Check if all arguments are integers for bits, size, banks
if type(OPTS.word_size)!=int: if type(OPTS.word_size)!=int:
debug.error("{0} is not an integer in config file.".format(OPTS.word_size)) debug.error("{0} is not an integer in config file.".format(OPTS.word_size))

View File

@ -13,10 +13,8 @@ class library_drc_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
global verify
import verify import verify
OPTS.check_lvsdrc=True
(gds_dir, gds_files) = setup_files() (gds_dir, gds_files) = setup_files()
drc_errors = 0 drc_errors = 0
debug.info(1, "\nPerforming DRC on: " + ", ".join(gds_files)) debug.info(1, "\nPerforming DRC on: " + ", ".join(gds_files))
@ -32,11 +30,12 @@ class library_drc_test(openram_test):
self.assertEqual(drc_errors, 0) self.assertEqual(drc_errors, 0)
globals.end_openram() globals.end_openram()
def setup_files(): def setup_files():
gds_dir = OPTS.openram_tech + "/gds_lib" gds_dir = OPTS.openram_tech + "/gds_lib"
files = os.listdir(gds_dir) files = os.listdir(gds_dir)
nametest = re.compile("\.gds$", re.IGNORECASE) nametest = re.compile("\.gds$", re.IGNORECASE)
gds_files = filter(nametest.search, files) gds_files = list(filter(nametest.search, files))
return (gds_dir, gds_files) return (gds_dir, gds_files)
@ -46,3 +45,4 @@ if __name__ == "__main__":
del sys.argv[1:] del sys.argv[1:]
header(__file__, OPTS.tech_name) header(__file__, OPTS.tech_name)
unittest.main() unittest.main()

View File

@ -14,7 +14,7 @@ class library_lvs_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
import verify import verify
OPTS.check_lvsdrc=True
(gds_dir, sp_dir, allnames) = setup_files() (gds_dir, sp_dir, allnames) = setup_files()
lvs_errors = 0 lvs_errors = 0
debug.info(1, "Performing LVS on: " + ", ".join(allnames)) debug.info(1, "Performing LVS on: " + ", ".join(allnames))

View File

@ -17,6 +17,7 @@ class timing_sram_test(openram_test):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
OPTS.spice_name="hspice" OPTS.spice_name="hspice"
OPTS.analytical_delay = False OPTS.analytical_delay = False
# This is a hack to reload the characterizer __init__ with the spice version # This is a hack to reload the characterizer __init__ with the spice version
from importlib import reload from importlib import reload
@ -83,7 +84,6 @@ class timing_sram_test(openram_test):
else: else:
self.isclose(data[k],golden_data[k],0.15) self.isclose(data[k],golden_data[k],0.15)
reload(characterizer)
globals.end_openram() globals.end_openram()
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test

View File

@ -26,7 +26,6 @@ class timing_setup_test(openram_test):
if not OPTS.spice_exe: if not OPTS.spice_exe:
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1) debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
import sram import sram
import tech import tech
slews = [tech.spice["rise_time"]*2] slews = [tech.spice["rise_time"]*2]
@ -58,7 +57,6 @@ class timing_setup_test(openram_test):
else: else:
self.isclose(data[k],golden_data[k],0.15) self.isclose(data[k],golden_data[k],0.15)
reload(characterizer)
globals.end_openram() globals.end_openram()
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test

View File

@ -83,7 +83,6 @@ class timing_sram_test(openram_test):
else: else:
self.isclose(data[k],golden_data[k],0.15) self.isclose(data[k],golden_data[k],0.15)
reload(characterizer)
globals.end_openram() globals.end_openram()
# instantiate a copdsay of the class to actually run the test # instantiate a copdsay of the class to actually run the test

View File

@ -16,6 +16,17 @@ class sram_func_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) globals.init_openram("config_20_{0}".format(OPTS.tech_name))
OPTS.use_pex = True
# This is a hack to reload the characterizer __init__ with the spice version
from importlib import reload
import characterizer
reload(characterizer)
from characterizer import setup_hold
if not OPTS.spice_exe:
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
global verify global verify
import verify import verify
@ -31,8 +42,6 @@ class sram_func_test(openram_test):
import tech import tech
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
global OPTS
OPTS.use_pex = True
s = sram.sram(word_size=OPTS.word_size, s = sram.sram(word_size=OPTS.word_size,
num_words=OPTS.num_words, num_words=OPTS.num_words,
num_banks=OPTS.num_banks, num_banks=OPTS.num_banks,

View File

@ -73,10 +73,7 @@ class openram_test(openram_test):
shutil.rmtree(out_path, ignore_errors=True) shutil.rmtree(out_path, ignore_errors=True)
self.assertEqual(os.path.exists(out_path),False) self.assertEqual(os.path.exists(out_path),False)
# The default was on, so disable it.
OPTS.check_lvsdrc=False
globals.end_openram() globals.end_openram()
OPTS.check_lvsdrc=True
# instantiate a copy of the class to actually run the test # instantiate a copy of the class to actually run the test
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -28,5 +28,12 @@ suite = unittest.TestSuite()
load = unittest.defaultTestLoader.loadTestsFromModule load = unittest.defaultTestLoader.loadTestsFromModule
suite.addTests(map(load, modules)) suite.addTests(map(load, modules))
ret = not unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() test_runner = unittest.TextTestRunner(verbosity=2,stream=sys.stderr)
sys.exit(ret) test_result = test_runner.run(suite)
import verify
verify.print_drc_stats()
verify.print_lvs_stats()
verify.print_pex_stats()
sys.exit(not test_result.wasSuccessful())

View File

@ -13,7 +13,7 @@ import debug
from globals import OPTS,find_exe,get_tool from globals import OPTS,find_exe,get_tool
import sys import sys
debug.info(2,"Initializing verify...") debug.info(1,"Initializing verify...")
if not OPTS.check_lvsdrc: if not OPTS.check_lvsdrc:
debug.info(1,"LVS/DRC/PEX disabled.") debug.info(1,"LVS/DRC/PEX disabled.")
@ -21,6 +21,7 @@ if not OPTS.check_lvsdrc:
OPTS.lvs_exe = None OPTS.lvs_exe = None
OPTS.pex_exe = None OPTS.pex_exe = None
else: else:
debug.info(1, "Finding DRC/LVS/PEX tools.")
OPTS.drc_exe = get_tool("DRC",["calibre","assura","magic"]) OPTS.drc_exe = get_tool("DRC",["calibre","assura","magic"])
OPTS.lvs_exe = get_tool("LVS",["calibre","assura","netgen"]) OPTS.lvs_exe = get_tool("LVS",["calibre","assura","netgen"])
OPTS.pex_exe = get_tool("PEX",["calibre","magic"]) OPTS.pex_exe = get_tool("PEX",["calibre","magic"])
@ -31,22 +32,22 @@ if OPTS.check_lvsdrc and OPTS.tech_name == "freepdk45":
if OPTS.drc_exe == None: if OPTS.drc_exe == None:
pass pass
elif "calibre"==OPTS.drc_exe[0]: elif "calibre"==OPTS.drc_exe[0]:
from .calibre import run_drc from .calibre import run_drc,print_drc_stats
elif "assura"==OPTS.drc_exe[0]: elif "assura"==OPTS.drc_exe[0]:
from .assura import run_drc from .assura import run_drc,print_drc_stats
elif "magic"==OPTS.drc_exe[0]: elif "magic"==OPTS.drc_exe[0]:
from .magic import run_drc from .magic import run_drc,print_drc_stats
else: else:
debug.warning("Did not find a supported DRC tool.") debug.warning("Did not find a supported DRC tool.")
if OPTS.lvs_exe == None: if OPTS.lvs_exe == None:
pass pass
elif "calibre"==OPTS.lvs_exe[0]: elif "calibre"==OPTS.lvs_exe[0]:
from .calibre import run_lvs from .calibre import run_lvs,print_lvs_stats
elif "assura"==OPTS.lvs_exe[0]: elif "assura"==OPTS.lvs_exe[0]:
from .assura import run_lvs from .assura import run_lvs,print_lvs_stats
elif "netgen"==OPTS.lvs_exe[0]: elif "netgen"==OPTS.lvs_exe[0]:
from .magic import run_lvs from .magic import run_lvs,print_lvs_stats
else: else:
debug.warning("Did not find a supported LVS tool.") debug.warning("Did not find a supported LVS tool.")
@ -54,9 +55,9 @@ else:
if OPTS.pex_exe == None: if OPTS.pex_exe == None:
pass pass
elif "calibre"==OPTS.pex_exe[0]: elif "calibre"==OPTS.pex_exe[0]:
from .calibre import run_pex from .calibre import run_pex,print_pex_stats
elif "magic"==OPTS.pex_exe[0]: elif "magic"==OPTS.pex_exe[0]:
from .magic import run_pex from .magic import run_pex,print_pex_stats
else: else:
debug.warning("Did not find a supported PEX tool.") debug.warning("Did not find a supported PEX tool.")

View File

@ -25,10 +25,18 @@ import time
import debug import debug
from globals import OPTS from globals import OPTS
# Keep track of statistics
num_drc_runs = 0
num_lvs_runs = 0
num_pex_runs = 0
def run_drc(name, gds_name): def run_drc(name, gds_name):
"""Run DRC check on a given top-level name which is """Run DRC check on a given top-level name which is
implemented in gds_name.""" implemented in gds_name."""
global num_drc_runs
num_drc_runs += 1
from tech import drc from tech import drc
drc_rules = drc["drc_rules"] drc_rules = drc["drc_rules"]
drc_runset = OPTS.openram_temp + name + ".rsf" drc_runset = OPTS.openram_temp + name + ".rsf"
@ -88,6 +96,10 @@ def run_drc(name, gds_name):
def run_lvs(name, gds_name, sp_name): def run_lvs(name, gds_name, sp_name):
"""Run LVS check on a given top-level name which is """Run LVS check on a given top-level name which is
implemented in gds_name and sp_name. """ implemented in gds_name and sp_name. """
global num_lvs_runs
num_lvs_runs += 1
from tech import drc from tech import drc
lvs_rules = drc["lvs_rules"] lvs_rules = drc["lvs_rules"]
lvs_runset = OPTS.openram_temp + name + ".rsf" lvs_runset = OPTS.openram_temp + name + ".rsf"
@ -170,3 +182,13 @@ def run_pex(name, gds_name, sp_name, output=None):
"""Run pex on a given top-level name which is """Run pex on a given top-level name which is
implemented in gds_name and sp_name. """ implemented in gds_name and sp_name. """
debug.error("PEX extraction not implemented with Assura.",-1) debug.error("PEX extraction not implemented with Assura.",-1)
global num_pex_runs
num_pex_runs += 1
def print_drc_stats():
debug.info(1,"DRC runs: {0}".format(num_drc_runs))
def print_lvs_stats():
debug.info(1,"LVS runs: {0}".format(num_lvs_runs))
def print_pex_stats():
debug.info(1,"PEX runs: {0}".format(num_pex_runs))

View File

@ -65,10 +65,17 @@ import debug
from globals import OPTS from globals import OPTS
import subprocess import subprocess
# Keep track of statistics
num_drc_runs = 0
num_lvs_runs = 0
num_pex_runs = 0
def run_drc(cell_name, gds_name): def run_drc(cell_name, gds_name):
"""Run DRC check on a given top-level name which is """Run DRC check on a given top-level name which is
implemented in gds_name.""" implemented in gds_name."""
global num_drc_runs
num_drc_runs += 1
# the runset file contains all the options to run calibre # the runset file contains all the options to run calibre
from tech import drc from tech import drc
@ -141,7 +148,10 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False):
"""Run LVS check on a given top-level name which is """Run LVS check on a given top-level name which is
implemented in gds_name and sp_name. Final verification will implemented in gds_name and sp_name. Final verification will
ensure that there are no remaining virtual conections. """ ensure that there are no remaining virtual conections. """
global num_lvs_runs
num_lvs_runs += 1
from tech import drc from tech import drc
lvs_rules = drc["lvs_rules"] lvs_rules = drc["lvs_rules"]
lvs_runset = { lvs_runset = {
@ -258,6 +268,10 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False):
def run_pex(cell_name, gds_name, sp_name, output=None): def run_pex(cell_name, gds_name, sp_name, output=None):
"""Run pex on a given top-level name which is """Run pex on a given top-level name which is
implemented in gds_name and sp_name. """ implemented in gds_name and sp_name. """
global num_pex_runs
num_pex_runs += 1
from tech import drc from tech import drc
if output == None: if output == None:
output = name + ".pex.netlist" output = name + ".pex.netlist"
@ -354,3 +368,10 @@ def correct_port(name, output_file_name, ref_file_name):
output_file.write(circuit_title) output_file.write(circuit_title)
output_file.write(part2) output_file.write(part2)
output_file.close() output_file.close()
def print_drc_stats():
debug.info(1,"DRC runs: {0}".format(num_drc_runs))
def print_lvs_stats():
debug.info(1,"LVS runs: {0}".format(num_lvs_runs))
def print_pex_stats():
debug.info(1,"PEX runs: {0}".format(num_pex_runs))

View File

@ -64,6 +64,11 @@ import debug
from globals import OPTS from globals import OPTS
import subprocess import subprocess
# Keep track of statistics
num_drc_runs = 0
num_lvs_runs = 0
num_pex_runs = 0
def write_magic_script(cell_name, gds_name, extract=False): def write_magic_script(cell_name, gds_name, extract=False):
""" Write a magic script to perform DRC and optionally extraction. """ """ Write a magic script to perform DRC and optionally extraction. """
@ -148,6 +153,9 @@ def write_netgen_script(cell_name, sp_name):
def run_drc(cell_name, gds_name, extract=False): def run_drc(cell_name, gds_name, extract=False):
"""Run DRC check on a cell which is implemented in gds_name.""" """Run DRC check on a cell which is implemented in gds_name."""
global num_drc_runs
num_drc_runs += 1
write_magic_script(cell_name, gds_name, extract) write_magic_script(cell_name, gds_name, extract)
# run drc # run drc
@ -198,6 +206,9 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False):
implemented in gds_name and sp_name. Final verification will implemented in gds_name and sp_name. Final verification will
ensure that there are no remaining virtual conections. """ ensure that there are no remaining virtual conections. """
global num_lvs_runs
num_lvs_runs += 1
run_drc(cell_name, gds_name, extract=True) run_drc(cell_name, gds_name, extract=True)
write_netgen_script(cell_name, sp_name) write_netgen_script(cell_name, sp_name)
@ -270,6 +281,9 @@ def run_pex(name, gds_name, sp_name, output=None):
"""Run pex on a given top-level name which is """Run pex on a given top-level name which is
implemented in gds_name and sp_name. """ implemented in gds_name and sp_name. """
global num_pex_runs
num_pex_runs += 1
debug.warning("PEX using magic not implemented.") debug.warning("PEX using magic not implemented.")
return 1 return 1
@ -337,3 +351,9 @@ def run_pex(name, gds_name, sp_name, output=None):
return out_errors return out_errors
def print_drc_stats():
debug.info(1,"DRC runs: {0}".format(num_drc_runs))
def print_lvs_stats():
debug.info(1,"LVS runs: {0}".format(num_lvs_runs))
def print_pex_stats():
debug.info(1,"PEX runs: {0}".format(num_pex_runs))