From 6c89f7965d08ac08770421f947bd4a89936c2fdc Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 8 Feb 2018 12:47:19 -0800 Subject: [PATCH] Refactor openram.py. --- compiler/globals.py | 68 ++++++++++++++++++++++----- compiler/openram.py | 111 +++++++------------------------------------- compiler/sram.py | 49 ++++++++++++++++++- 3 files changed, 122 insertions(+), 106 deletions(-) diff --git a/compiler/globals.py b/compiler/globals.py index 84b831f2..5eda7d52 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -16,13 +16,7 @@ USAGE = "Usage: openram.py [options] \nUse -h for help.\n" # Anonymous object that will be the options OPTS = options.options() -# check that we are not using version 3 and at least 2.7 -major_python_version = sys.version_info.major -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) - -def parse_args(): +def parse_args(is_unit_test=True): """ Parse the optional arguments for OpenRAM """ global OPTS @@ -36,8 +30,6 @@ def parse_args(): help="Output file(s) location"), optparse.make_option("-n", "--nocheck", action="store_false", help="Disable inline LVS/DRC checks", dest="check_lvsdrc"), - optparse.make_option("-q", "--quiet", action="store_false", dest="print_banner", - help="Don\'t display banner"), optparse.make_option("-v", "--verbose", action="count", dest="debug_level", help="Increase the verbosity level"), optparse.make_option("-t", "--tech", dest="tech_name", @@ -66,13 +58,19 @@ def parse_args(): # Alias SCMOS to AMI 0.5um if OPTS.tech_name == "scmos": OPTS.tech_name = "scn3me_subm" - + + # Check that we have a single configuration file as argument. + OPTS.is_unit_test=is_unit_test + if not OPTS.is_unit_test and len(args) < 1: + print(USAGE) + sys.exit(2) + return (options, args) def print_banner(): """ Conditionally print the banner to stdout """ global OPTS - if not OPTS.print_banner: + if OPTS.is_unit_test: return print("|==============================================================================|") @@ -89,8 +87,17 @@ def print_banner(): print("|==============================================================================|") +def check_versions(): + """ check that we are not using version 3 and at least 2.7 """ + major_python_version = sys.version_info.major + 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) + + def init_openram(config_file): """Initialize the technology, paths, simulators, etc.""" + check_versions() debug.info(1,"Initializing OpenRAM...") @@ -100,6 +107,8 @@ def init_openram(config_file): import_tech() + report_status() + def get_tool(tool_type, preferences): """ @@ -173,6 +182,7 @@ def read_config(config_file): def end_openram(): """ Clean up openram for a proper exit """ cleanup_paths() + @@ -270,3 +280,39 @@ def import_tech(): debug.error("Nonexistent technology_setup_file: {0}.py".format(filename)) sys.exit(1) +def print_time(name, now_time, last_time=None): + if last_time: + time = round((now_time-last_time).total_seconds(),1) + else: + time = now_time + print("** {0}: {1} seconds".format(name,time)) + return now_time + + +def report_status(): + """ Check for valid arguments and report the info about the SRAM being generated """ + # Check if all arguments are integers for bits, size, banks + if type(OPTS.word_size)!=int: + debug.error("{0} is not an integer in config file.".format(OPTS.word_size)) + if type(OPTS.num_words)!=int: + debug.error("{0} is not an integer in config file.".format(OPTS.sram_size)) + if type(OPTS.num_banks)!=int: + debug.error("{0} is not an integer in config file.".format(OPTS.num_banks)) + + if not OPTS.tech_name: + debug.error("Tech name must be specified in config file.") + + if (OPTS.output_name == ""): + OPTS.output_name = "sram_{0}_{1}_{2}_{3}".format(OPTS.word_size, + OPTS.num_words, + OPTS.num_banks, + OPTS.OPTS.tech_name) + if not OPTS.is_unit_test: + print("Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)") + print("Technology: {0}".format(OPTS.tech_name)) + print("Word size: {0}\nWords: {1}\nBanks: {2}".format(OPTS.word_size, + OPTS.num_words, + OPTS.num_banks)) + if not OPTS.check_lvsdrc: + print("DRC/LVS/PEX checking is disabled.") + diff --git a/compiler/openram.py b/compiler/openram.py index 64e32306..95847db1 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -14,116 +14,39 @@ import sys,os import datetime import re import importlib -import globals +from globals import * -(OPTS, args) = globals.parse_args() - -def print_time(name, now_time, last_time=None): - if last_time: - time = round((now_time-last_time).total_seconds(),1) - else: - time = now_time - print("** {0}: {1} seconds".format(name,time)) - return now_time +(OPTS, args) = parse_args(is_unit_test=False) # These depend on arguments, so don't load them until now. import debug -# required positional args for using openram main exe -if len(args) < 1: - print(globals.USAGE) - sys.exit(2) +# Only print banner here so it's not in unit tests +print_banner() -globals.print_banner() +init_openram(args[0]) -globals.init_openram(args[0]) - -# Check if all arguments are integers for bits, size, banks -if type(OPTS.word_size)!=int: - debug.error("{0} is not an integer in config file.".format(OPTS.word_size)) -if type(OPTS.num_words)!=int: - debug.error("{0} is not an integer in config file.".format(OPTS.sram_size)) -if type(OPTS.num_banks)!=int: - debug.error("{0} is not an integer in config file.".format(OPTS.num_banks)) - -if not OPTS.tech_name: - debug.error("Tech name must be specified in config file.") - -word_size = OPTS.word_size -num_words = OPTS.num_words -num_banks = OPTS.num_banks - -if (OPTS.output_name == ""): - OPTS.output_name = "sram_{0}_{1}_{2}_{3}".format(word_size, - num_words, - num_banks, - OPTS.tech_name) - -print("Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)") - -print("Technology: {0}".format(OPTS.tech_name)) -print("Word size: {0}\nWords: {1}\nBanks: {2}".format(word_size,num_words,num_banks)) - -# only start importing modules after we have the config file +# Start importing design modules after we have the config file import verify import sram +# Keep track of running stats start_time = datetime.datetime.now() last_time = start_time -print_time("Start",datetime.datetime.now()) -if not OPTS.check_lvsdrc: - print("DRC/LVS/PEX checking is disabled.") +print_time("Start",last_time) + # import SRAM test generation -s = sram.sram(word_size=word_size, - num_words=num_words, - num_banks=num_banks, +s = sram.sram(word_size=OPTS.word_size, + num_words=OPTS.num_words, + num_banks=OPTS.num_banks, name=OPTS.output_name) last_time=print_time("SRAM creation", datetime.datetime.now(), last_time) # Output the files for the resulting SRAM +s.save_output(last_time) -spname = OPTS.output_path + s.name + ".sp" -print("SP: Writing to {0}".format(spname)) -s.sp_write(spname) -last_time=print_time("Spice writing", datetime.datetime.now(), last_time) - -# Output the extracted design -sram_file = spname -if OPTS.use_pex: - sram_file = OPTS.output_path + "temp_pex.sp" - verify.run_pex(s.name, gdsname, spname, output=sram_file) - -# Characterize the design -from characterizer import lib -libname = OPTS.output_path + s.name + ".lib" -print("LIB: Writing to {0}".format(libname)) -if OPTS.analytical_delay: - print("Using analytical delay models (no characterization)") -else: - if OPTS.spice_name!="": - print("Performing simulation-based characterization with {}".format(OPTS.spice_name)) - if OPTS.trim_netlist: - print("Trimming netlist to speed up characterization.") -lib.lib(libname,s,sram_file) -last_time=print_time("Characterization", datetime.datetime.now(), last_time) - -# Write the layout -gdsname = OPTS.output_path + s.name + ".gds" -print("GDS: Writing to {0}".format(gdsname)) -s.gds_write(gdsname) -last_time=print_time("GDS", datetime.datetime.now(), last_time) - -# Create a LEF physical model -lefname = OPTS.output_path + s.name + ".lef" -print("LEF: Writing to {0}".format(lefname)) -s.lef_write(lefname) -last_time=print_time("LEF", datetime.datetime.now(), last_time) - -# Write a verilog model -vname = OPTS.output_path + s.name + ".v" -print("Verilog: Writing to {0}".format(vname)) -s.verilog_write(vname) -last_time=print_time("Verilog", datetime.datetime.now(), last_time) - -globals.end_openram() +# Delete temp files etc. +end_openram() print_time("End",datetime.datetime.now(), start_time) + + diff --git a/compiler/sram.py b/compiler/sram.py index 7690b1e7..0e90c7f2 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -8,7 +8,7 @@ from bank import bank import datetime import getpass from vector import vector -from globals import OPTS +from globals import OPTS, print_time class sram(design.design): @@ -1009,3 +1009,50 @@ class sram(design.design): def analytical_delay(self,slew,load): """ LH and HL are the same in analytical model. """ return self.bank.analytical_delay(slew,load) + + + def save_output(self, last_time): + """ Save all the output files while reporting time to do it as well. """ + + spname = OPTS.output_path + self.name + ".sp" + print("SP: Writing to {0}".format(spname)) + self.sp_write(spname) + last_time=print_time("Spice writing", datetime.datetime.now(), last_time) + + # Output the extracted design + sram_file = spname + if OPTS.use_pex: + sram_file = OPTS.output_path + "temp_pex.sp" + verify.run_pex(self.name, gdsname, spname, output=sram_file) + + # Characterize the design + from characterizer import lib + libname = OPTS.output_path + self.name + ".lib" + print("LIB: Writing to {0}".format(libname)) + if OPTS.analytical_delay: + print("Using analytical delay models (no characterization)") + else: + if OPTS.spice_name!="": + print("Performing simulation-based characterization with {}".format(OPTS.spice_name)) + if OPTS.trim_netlist: + print("Trimming netlist to speed up characterization.") + lib.lib(libname,self,sram_file) + last_time=print_time("Characterization", datetime.datetime.now(), last_time) + + # Write the layout + gdsname = OPTS.output_path + self.name + ".gds" + print("GDS: Writing to {0}".format(gdsname)) + self.gds_write(gdsname) + last_time=print_time("GDS", datetime.datetime.now(), last_time) + + # Create a LEF physical model + lefname = OPTS.output_path + self.name + ".lef" + print("LEF: Writing to {0}".format(lefname)) + self.lef_write(lefname) + last_time=print_time("LEF", datetime.datetime.now(), last_time) + + # Write a verilog model + vname = OPTS.output_path + self.name + ".v" + print("Verilog: Writing to {0}".format(vname)) + self.verilog_write(vname) + last_time=print_time("Verilog", datetime.datetime.now(), last_time)