diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d4852d8..1ee401d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,9 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v1 + - name: Library build + run: | + make library - name: Docker build run: | cd ${{ github.workspace }}/docker diff --git a/.gitignore b/.gitignore index 83eede78..b2ddb51b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,9 @@ technology/sky130/tech/.magicrc .idea compiler/tests/results/ open_pdks/ +dist/ +openram.egg-info/ +sky130A/ +sky130B/ +skywater-pdk/ +sky130_fd_bd_sram/ diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..b2d45363 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,24 @@ +include Makefile +include openram.mk +include setpaths.sh +include requirements.txt +include docker/* +recursive-include compiler * +recursive-include technology * +exclude .DS_Store +exclude .idea +exclude **/model_data +exclude technology/sky130/*_lib +exclude technology/sky130/tech/.magicrc +exclude compiler/gen_stimulus.py +exclude compiler/model_data_util.py +exclude compiler/printGDS.py +exclude compiler/processGDS.py +exclude compiler/uniquifyGDS.py +exclude compiler/view_profile.py +exclude compiler/run_profile.sh +recursive-exclude open_pdks * +recursive-exclude compiler/tests/results * +recursive-exclude technology/freepdk45/ncsu_basekit * +recursive-exclude outputs * +global-exclude *.pyc *~ *.orig *.rej *.aux *.out *.toc *.synctex.gz \ No newline at end of file diff --git a/Makefile b/Makefile index 401b0a73..c32f9d3e 100644 --- a/Makefile +++ b/Makefile @@ -215,3 +215,16 @@ wipe: uninstall @rm -rf $(OPEN_PDKS_DIR) @rm -rf $(SKY130_PDKS_DIR) .PHONY: wipe + +# Build the openram library +build-library: + @rm -rf dist + @rm -rf openram.egg-info + @python3 -m pip install --upgrade build + @python3 -m build +.PHONY: build-library + +# Build and install the openram library +library: build-library + @python3 -m pip install --find-links=dist openram --force +.PHONY: library \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 00000000..5eca3f7e --- /dev/null +++ b/__init__.py @@ -0,0 +1,22 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import os +import sys + +# Attempt to add the source code to the PYTHONPATH here before running globals.init_openram(). +try: + OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) +except: + import openram + OPENRAM_HOME = os.path.dirname(openram.__file__) + "/compiler" + +if not os.path.isdir(OPENRAM_HOME): + assert False + +if OPENRAM_HOME not in sys.path: + sys.path.insert(0, OPENRAM_HOME) \ No newline at end of file diff --git a/compiler/Makefile b/compiler/Makefile index 117e4bd2..d3596421 100644 --- a/compiler/Makefile +++ b/compiler/Makefile @@ -95,7 +95,7 @@ model: $(STAMPS) $(eval bname=$(basename $(notdir $@))) $(eval config_path=$(CONFIG_DIR)/$(addsuffix .py, $(notdir $(basename $@)))) mkdir -p $(SIM_DIR)/$(bname) - -python3 $(OPENRAM_HOME)/openram.py $(OPTS) -p $(SIM_DIR)/$(bname) -o $(bname) -t $(TECH) $(config_path) 2>&1 > /dev/null + -python3 $(OPENRAM_HOME)/../sram_compiler.py $(OPTS) -p $(SIM_DIR)/$(bname) -o $(bname) -t $(TECH) $(config_path) 2>&1 > /dev/null touch $@ clean_model: diff --git a/compiler/debug.py b/compiler/debug.py index 4052e713..8e970cca 100644 --- a/compiler/debug.py +++ b/compiler/debug.py @@ -131,7 +131,7 @@ def bp(): An empty function so you can set soft breakpoints in pdb. Usage: 1) Add a breakpoint anywhere in your code with "import debug; debug.bp()". - 2) Run "python3 -m pdb openram.py config.py" or "python3 -m pdb 05_bitcell_array.test" (for example) + 2) Run "python3 -m pdb sram_compiler.py config.py" or "python3 -m pdb 05_bitcell_array.test" (for example) 3) When pdb starts, run "break debug.bp" to set a SOFT breakpoint. (Or you can add this to your ~/.pdbrc) 4) Then run "cont" to continue. 5) You can now set additional breakpoints or display commands diff --git a/compiler/globals.py b/compiler/globals.py index 9a185052..01c52725 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -24,7 +24,7 @@ import subprocess VERSION = "1.2.0" NAME = "OpenRAM v{}".format(VERSION) -USAGE = "openram.py [options] \nUse -h for help.\n" +USAGE = "sram_compiler.py [options] \nUse -h for help.\n" OPTS = options.options() CHECKPOINT_OPTS = None @@ -141,9 +141,6 @@ def print_banner(): debug.print_raw("|=========" + user_info.center(60) + "=========|") dev_info = "Development help: openram-dev-group@ucsc.edu" debug.print_raw("|=========" + dev_info.center(60) + "=========|") - if OPTS.openram_temp: - temp_info = "Temp dir: {}".format(OPTS.openram_temp) - debug.print_raw("|=========" + temp_info.center(60) + "=========|") debug.print_raw("|=========" + "See LICENSE for license info".center(60) + "=========|") debug.print_raw("|==============================================================================|") @@ -432,16 +429,23 @@ def setup_paths(): global OPTS + # If $OPENRAM_HOME is defined, use that path for the source code. + # Otherwise, use the openram package. try: OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) except: - debug.error("$OPENRAM_HOME is not properly defined.", 1) + import openram + OPENRAM_HOME = os.path.dirname(openram.__file__) + "/compiler" + # Add this directory to os.environ here + os.environ["OPENRAM_HOME"] = OPENRAM_HOME debug.check(os.path.isdir(OPENRAM_HOME), "$OPENRAM_HOME does not exist: {0}".format(OPENRAM_HOME)) + debug.info(1, "OpenRAM source code found in {}".format(OPENRAM_HOME)) if OPENRAM_HOME not in sys.path: - debug.error("Please add OPENRAM_HOME to the PYTHONPATH.", -1) + sys.path.insert(0, OPENRAM_HOME) + debug.info(2, "Adding source code to PYTHONPATH.") # Use a unique temp subdirectory if multithreaded if OPTS.num_threads > 1 or OPTS.openram_temp == "/tmp": @@ -547,11 +551,30 @@ def import_tech(): debug.info(2, "Importing technology: " + OPTS.tech_name) - # environment variable should point to the technology dir + OPENRAM_TECH = "" + + # Check if $OPENRAM_TECH is defined try: OPENRAM_TECH = os.path.abspath(os.environ.get("OPENRAM_TECH")) except: - debug.error("$OPENRAM_TECH environment variable is not defined.", 1) + debug.info(2, + "$OPENRAM_TECH environment variable is not defined. " + "Only the default technology modules will be considered if installed.") + # Point to the default technology modules that are part of the openram package + try: + import openram + if OPENRAM_TECH != "": + OPENRAM_TECH += ":" + OPENRAM_TECH += os.path.dirname(openram.__file__) + "/technology" + except: + if OPENRAM_TECH == "": + debug.warning("Couldn't find a tech directory. " + "Install openram library or set $OPENRAM_TECH.") + + debug.info(1, "Tech directory found in {}".format(OPENRAM_TECH)) + + # Add this environment variable to os.environ + os.environ["OPENRAM_TECH"] = OPENRAM_TECH # Add all of the paths for tech_path in OPENRAM_TECH.split(":"): diff --git a/compiler/options.py b/compiler/options.py index 770045b3..729718e8 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -13,7 +13,7 @@ class options(optparse.Values): """ Class for holding all of the OpenRAM options. All of these options can be over-riden in a configuration file - that is the sole required command-line positional argument for openram.py. + that is the sole required command-line positional argument for sram_compiler.py. """ ################### diff --git a/compiler/tests/00_code_format_check_test.py b/compiler/tests/00_code_format_check_test.py index cfe72a21..8eff7388 100755 --- a/compiler/tests/00_code_format_check_test.py +++ b/compiler/tests/00_code_format_check_test.py @@ -35,7 +35,7 @@ class code_format_test(openram_test): continue if re.search("debug.py$", code): continue - if re.search("openram.py$", code): + if re.search("sram_compiler.py$", code): continue if re.search("testutils.py$", code): continue diff --git a/compiler/tests/30_openram_back_end_test.py b/compiler/tests/30_openram_back_end_test.py index 9d5b1e42..5519f42e 100755 --- a/compiler/tests/30_openram_back_end_test.py +++ b/compiler/tests/30_openram_back_end_test.py @@ -23,7 +23,7 @@ class openram_back_end_test(openram_test): config_file = "{}/tests/configs/config_back_end".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) - debug.info(1, "Testing top-level back-end openram.py with 2-bit, 16 word SRAM.") + debug.info(1, "Testing top-level back-end sram_compiler.py with 2-bit, 16 word SRAM.") out_file = "testsram" out_path = "/tmp/testsram_{0}_{1}_{2}/".format(OPTS.tech_name, getpass.getuser(), os.getpid()) @@ -54,9 +54,9 @@ class openram_back_end_test(openram_test): # Always perform code coverage if OPTS.coverage == 0: debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage") - exe_name = "{0}/openram.py ".format(OPENRAM_HOME) + exe_name = "{0}/../sram_compiler.py ".format(OPENRAM_HOME) else: - exe_name = "{0}{1}/openram.py ".format(OPTS.coverage_exe, OPENRAM_HOME) + exe_name = "{0}{1}/../sram_compiler.py ".format(OPTS.coverage_exe, OPENRAM_HOME) config_name = "{0}/tests/configs/config_back_end.py".format(OPENRAM_HOME) cmd = "{0} -o {1} -p {2} {3} {4} 2>&1 > {5}/output.log".format(exe_name, out_file, diff --git a/compiler/tests/30_openram_front_end_test.py b/compiler/tests/30_openram_front_end_test.py index 489ea26c..928ac74e 100755 --- a/compiler/tests/30_openram_front_end_test.py +++ b/compiler/tests/30_openram_front_end_test.py @@ -23,7 +23,7 @@ class openram_front_end_test(openram_test): config_file = "{}/tests/configs/config_front_end".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) - debug.info(1, "Testing top-level front-end openram.py with 2-bit, 16 word SRAM.") + debug.info(1, "Testing top-level front-end sram_compiler.py with 2-bit, 16 word SRAM.") out_file = "testsram" out_path = "/tmp/testsram_{0}_{1}_{2}".format(OPTS.tech_name, getpass.getuser(), os.getpid()) @@ -54,9 +54,9 @@ class openram_front_end_test(openram_test): # Always perform code coverage if OPTS.coverage == 0: debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage") - exe_name = "{0}/openram.py ".format(OPENRAM_HOME) + exe_name = "{0}/../sram_compiler.py ".format(OPENRAM_HOME) else: - exe_name = "{0}{1}/openram.py ".format(OPTS.coverage_exe, OPENRAM_HOME) + exe_name = "{0}{1}/../sram_compiler.py ".format(OPTS.coverage_exe, OPENRAM_HOME) config_name = "{0}/tests/configs/config_front_end.py".format(OPENRAM_HOME) cmd = "{0} -n -o {1} -p {2} {3} {4} 2>&1 > {5}/output.log".format(exe_name, out_file, diff --git a/compiler/tests/Makefile b/compiler/tests/Makefile index c563d4fa..f736d222 100644 --- a/compiler/tests/Makefile +++ b/compiler/tests/Makefile @@ -121,7 +121,7 @@ $(TEST_BASES): @mkdir -p results/$*/tmp @$(DOCKER_CMD) sh -c ". /home/cad-user/.bashrc && sleep 1 && python3 -u $(OPENRAM_DIR)/$(getfile).py \ -t $(gettech) -k -v $(ARGS) -p $(OPENRAM_DIR)/results/$* > $(OPENRAM_DIR)/results/$*.out 2>&1 && touch $(OPENRAM_DIR)/results/$*.ok || touch $(OPENRAM_DIR)/results/$*.bad" -ifdef $(KEEP) +ifdef KEEP @test -f $(TOP_DIR)/compiler/tests/results/$*.ok && echo "$* ... PASS!" || echo "$* ... FAIL!" else @test -f $(TOP_DIR)/compiler/tests/results/$*.ok && echo "$* ... PASS!" && rm -rf $(TOP_DIR)/compiler/tests/results/$* || echo "$* ... FAIL!" diff --git a/docs/source/FAQ.md b/docs/source/FAQ.md index 37e31817..a515b17a 100644 --- a/docs/source/FAQ.md +++ b/docs/source/FAQ.md @@ -2,6 +2,8 @@ # Frequently Asked Questions +## What to do if OpenRAM encounters an error? + When OpenRAM runs, it puts files in a temporary directory that is shown in the banner at the top. Like: ``` @@ -11,109 +13,26 @@ This is where simulations and DRC/LVS get run so there is no network traffic. The directory name is unique for each person and run of OpenRAM to not clobber any files and allow simultaneous runs. If it passes, the files are deleted. If it fails, you will see these files: -+ temp.gds is the layout (.mag files too if using SCMOS) -+ temp.sp is the netlist -+ test1.drc.err is the std err output of the DRC command -+ test1.drc.out is the standard output of the DRC command -+ test1.drc.results is the DRC results file -+ test1.lvs.err is the std err output of the LVS command -+ test1.lvs.out is the standard output of the LVS command -+ test1.lvs.results is the DRC results file ++ `temp.gds` is the layout (.mag files too if using SCMOS) ++ `temp.sp` is the netlist ++ `test1.drc.err` is the std err output of the DRC command ++ `test1.drc.out` is the standard output of the DRC command ++ `test1.drc.results` is the DRC results file ++ `test1.lvs.err` is the std err output of the LVS command ++ `test1.lvs.out` is the standard output of the LVS command ++ `test1.lvs.results` is the DRC results file Depending on your DRC/LVS tools, there will also be: -+ \_calibreDRC.rul\_ is the DRC rule file (Calibre) -+ dc_runset is the command file (Calibre) -+ extracted.sp (Calibre) -+ run_lvs.sh is a Netgen script for LVS (Netgen) -+ run_drc.sh is a Magic script for DRC (Magic) -+ .spice (Magic) ++ `run\_drc.sh` is a script to run DRC ++ `run\_ext.sh` is a script to run extraction ++ `run\_lvs.sh` is a script to run LVS -If DRC/LVS fails, the first thing is to check if it ran in the .out and -.err file. This shows the standard output and error output from +If DRC/LVS fails, the first thing is to check if it ran in the `.out` and +`.err` file. This shows the standard output and error output from running DRC/LVS. If there is a setup problem it will be shown here. -If DRC/LVS runs, but doesn't pass, you then should look at the .results +If DRC/LVS runs, but doesn't pass, you then should look at the `.results` file. If the DRC fails, it will typically show you the command that was used to run Calibre or Magic+Netgen. -To debug, you will need a layout viewer. I prefer to use Glade -on my Mac, but you can also use Calibre, Magic, etc. -1. Klayout - - You can view the designs in [Klayout](https://www.klayout.de/) with the configuration - file provided in the tech directories. For example, -``` - klayout temp.gds -l /home/vagrant/openram/technology/freepdk45/tf/FreePDK45.lyp -``` - -2. Calibre - - Start the Calibre DESIGNrev viewer in the temp directory and load your GDS file: -``` - calibredrv temp.gds -``` - Select Verification->Start RVE and select the results database file in - the new form (e.g., test1.drc.db). This will start the RVE (results - viewer). Scroll through the check pane and find the DRC check with an - error. Select it and it will open some numbers to the right. Double - click on any of the errors in the result browser. These will be - labelled as numbers "1 2 3 4" for example will be 4 DRC errors. - - In the viewer ">" opens the layout down a level. - -3. Glade - - You can view errors in [Glade](http://www.peardrop.co.uk/glade/) as well. - - To remote display over X windows, you need to disable OpenGL acceleration or use vnc - or something. You can disable by adding this to your .bashrc in bash: -``` - export GLADE_USE_OPENGL=no -``` - or in .cshrc/.tcshrc in csh/tcsh: -``` - setenv GLADE_USE_OPENGAL no -``` - To use this with the FreePDK45 or SCMOS layer views you should use the - tech files. Then create a .glade.py file in your user directory with - these commands to load the technology layers: -``` -ui().importCds("default", -"/Users/mrg/techfiles/freepdk45/display.drf", -"/Users/mrg/techfiles/freepdk45/FreePDK45.tf", 1000, 1, -"/Users/mrg/techfiles/freepdk45/layers.map") -``` - Obviously, edit the paths to point to your directory. To switch - between processes, you have to change the importCds command (or you - can manually run the command each time you start glade). - - To load the errors, you simply do Verify->Import Calibre Errors select - the .results file from Calibre. - -4. Magic - - Magic is only supported in SCMOS. You will need to install the MOSIS SCMOS rules - and [Magic](http://opencircuitdesign.com/) - - When running DRC or extraction, OpenRAM will load the GDS file, save - the .ext/.mag files, and export an extracted netlist (.spice). - -5. It is possible to use other viewers as well, such as: - * [LayoutEditor](http://www.layouteditor.net/) - - -# Example to output/input .gds layout files from/to Cadence - -1. To create your component layouts, you should stream them to - individual gds files using our provided layermap and flatten - cells. For example, -``` - strmout -layerMap layers.map -library sram -topCell $i -view layout -flattenVias -flattenPcells -strmFile ../gds_lib/$i.gds -``` -2. To stream a layout back into Cadence, do this: -``` - strmin -layerMap layers.map -attachTechFileOfLib NCSU\_TechLib\_FreePDK45 -library sram_4_32 -strmFile sram_4_32.gds -``` - When you import a gds file, make sure to attach the correct tech lib - or you will get incorrect layers in the resulting library. diff --git a/docs/source/base_data_structures.md b/docs/source/base_data_structures.md index 89dab8ab..72083e99 100644 --- a/docs/source/base_data_structures.md +++ b/docs/source/base_data_structures.md @@ -7,9 +7,9 @@ This page of the documentation explains the base data structures of OpenRAM. ## Table of Contents 1. [Design Classes](#design-classes) -2. [Base Class Inheritance](#base-class-inheritance) -3. [Parameterized Transistor](#parameterized-transistor-ptx-or-pfinfet) -4. [Parameterized Cells](#parameterized-cells) +1. [Base Class Inheritance](#base-class-inheritance) +1. [Parameterized Transistor](#parameterized-transistor-ptx-or-pfinfet) +1. [Parameterized Cells](#parameterized-cells) @@ -69,4 +69,4 @@ Dynamically generated cells (in `$OPENRAM_HOME/pgates`) * Buffer/drivers * `pbuf`, `pinvbuf`, `pdriver` * SRAM Logic - * `precharge`, `single_level_column_mux` \ No newline at end of file + * `precharge`, `single_level_column_mux` diff --git a/docs/source/basic_setup.md b/docs/source/basic_setup.md index 188a94f8..2b649d95 100644 --- a/docs/source/basic_setup.md +++ b/docs/source/basic_setup.md @@ -13,35 +13,55 @@ In general, the OpenRAM compiler has very few dependencies: + Make + Python 3.6 or higher + Various Python packages (pip install -r requirements.txt) -+ [Git] ++ Git + + + +## OpenRAM Library +OpenRAM is available as a Python library. There are a few ways to install it: + ++ Install using Makefile (you need to clone the repo): +``` +git clone git@github.com:VLSIDA/OpenRAM.git +cd OpenRAM +make library +``` ++ Install the latest _dev_ version: +``` +pip3 install git+ssh://git@github.com/VLSIDA/OpenramRAM.git@dev +``` + ## Docker -We have a [docker setup](./docker) to run OpenRAM. To use this, you should run: +We have a [docker setup](../../docker) to run OpenRAM. To use this, you should run: ``` cd OpenRAM/docker make build ``` -This must be run once and will take a while to build all the tools. +This must be run once and will take a while to build all the tools. If you have the +OpenRAM library installed, you can also run the docker setup from the package +installation directory. + ## Environment -You must set two environment variables: +If you haven't installed the OpenRAM library or you want to use a different OpenRAM installation, +you can set two environment variables: + OPENRAM\_HOME should point to the compiler source directory. -+ OPENERAM\_TECH should point to one or more root technology directories (colon separated). ++ OPENRAM\_TECH should point to one or more root technology directories (colon separated). -You should also add OPENRAM\_HOME to your PYTHONPATH. +If you have the library installed and OPENRAM\_HOME set, the library will use the installation on +the OPENRAM\_HOME path. -For example add this to your .bashrc: +If you don't have the library, you should also add OPENRAM\_HOME to your PYTHONPATH. This is not +needed if you have the library. +You can add these environment variables to your `.bashrc`: ``` export OPENRAM_HOME="$HOME/OpenRAM/compiler" export OPENRAM_TECH="$HOME/OpenRAM/technology" -``` - -You should also add OPENRAM\_HOME to your PYTHONPATH: -``` export PYTHONPATH=$OPENRAM_HOME ``` @@ -51,17 +71,17 @@ directory that you use and any custom technology modules as well. For example: export PYTHONPATH="$OPENRAM_HOME:$OPENRAM_TECH/sky130:$OPENRAM_TECH/sky130/custom" ``` -We include the tech files necessary for [SCMOS] SCN4M_SUBM, +We include the tech files necessary for [SCMOS] SCN4M\_SUBM, [FreePDK45]. The [SCMOS] spice models, however, are generic and should be replaced with foundry models. You may get the entire [FreePDK45 PDK here][FreePDK45]. + ### Sky130 Setup -To install [Sky130], you must have the open_pdks files installed in $PDK_ROOT. +To install [Sky130], you must have the open\_pdks files installed in $PDK\_ROOT. To install this automatically, you can run: - ``` cd $HOME/OpenRAM make pdk @@ -69,8 +89,15 @@ make pdk Then you must also install the [Sky130] SRAM build space and the appropriate cell views by running: - ``` cd $HOME/OpenRAM make install ``` + +You can also run these from the package installation directory if you have the OpenRAM library. + + + +[SCMOS]: https://www.mosis.com/files/scmos/scmos.pdf +[FreePDK45]: https://www.eda.ncsu.edu/wiki/FreePDK45:Contents +[Sky130]: https://github.com/google/skywater-pdk-libs-sky130_fd_bd_sram.git diff --git a/docs/source/basic_usage.md b/docs/source/basic_usage.md index 153bbe9a..b64269e4 100644 --- a/docs/source/basic_usage.md +++ b/docs/source/basic_usage.md @@ -7,16 +7,19 @@ This page of the documentation explains the basic usage of OpenRAM. ## Table of Contents 1. [Environment Variable Setup](#environment-variable-setup-assuming-bash) -2. [Command Line Usage](#command-line-usage) -3. [Configuration Files](#configuration-files) -4. [Common Configuration File Options](#common-configuration-file-options) -5. [Output Files](#output-files) -6. [Data Sheets](#data-sheets) +1. [Script Usage (with library)](#script-usage-with-library) +1. [Command Line Usage (with library)](#command-line-usage-with-library) +1. [Command Line Usage (without library)](#command-line-usage-without-library) +1. [Configuration Files](#configuration-files) +1. [Common Configuration File Options](#common-configuration-file-options) +1. [Output Files](#output-files) +1. [Data Sheets](#data-sheets) ## Environment Variable Setup (assuming bash) -* OPENRAM_HOME defines where the compiler directory is +> **Note**: This is optional if you have the OpenRAM library. See [basic setup](./basic_setup.md#go-back) for details. +* OPENRAM\_HOME defines where the compiler directory is * ```export OPENRAM_HOME="$HOME/openram/compiler"``` * OPENRAM_TECH defines list of paths where the technologies exist * `export OPENRAM_TECH="$HOME/openram/technology"` @@ -27,14 +30,41 @@ This page of the documentation explains the basic usage of OpenRAM. -## Command Line Usage +## Script Usage (with library) +If you have the library installed, you can use OpenRAM in any Python script. You can import "openram" as follows: +```python +import openram +import globals +globals.init_openram("myconfig.py") # Config files are explained on this page +``` +Note that you should import "openram" in this order so that the modules are imported properly. You can also look +at `sram_compiler.py` as an example on how to use "openram." + + + +## Command Line Usage (with library) +You can run OpenRAM from the command line using the `sram_compiler.py` script that is included in the +library's installation. You can the package directory on a path like: +``` +/home/mrg/.local/lib/python3.8/site-packages/openram +``` + +Alternatively, you can run the following command to find that path: +``` +echo -e "import os\nimport openram\nprint(os.path.dirname(openram.__file__))" | python3 - +``` + +You can continue with following section for more details. + + +## Command Line Usage (without library) Once you have defined the environment, you can run OpenRAM from the command line using a single configuration file written in Python. For example, create a file called *myconfig.py* specifying the following parameters for your memory: -``` +```python # Data word size word_size = 2 # Number of words in the memory @@ -65,7 +95,7 @@ output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name) You can then run OpenRAM by executing: ``` -python3 $OPENRAM_HOME/openram.py myconfig +python3 $OPENRAM_HOME/../sram_compiler.py myconfig ``` You can see all of the options for the configuration file in $OPENRAM\_HOME/options.py diff --git a/docs/source/bitcells.md b/docs/source/bitcells.md index ecb7e860..92c5709b 100644 --- a/docs/source/bitcells.md +++ b/docs/source/bitcells.md @@ -7,8 +7,8 @@ This page of the documentation explains the bitcells supported by OpenRAM. ## Table of Contents 1. [Multiport Bitcells](#multiport-bitcells) -2. [Relative Bitcell Sizes](#relative-bitcell-sizes-035um-scmos) -3. [Thin SRAM Bitcells](#thin-sram-bitcells-130nm) +1. [Relative Bitcell Sizes](#relative-bitcell-sizes-035um-scmos) +1. [Thin SRAM Bitcells](#thin-sram-bitcells-130nm) @@ -37,4 +37,4 @@ This page of the documentation explains the bitcells supported by OpenRAM. | | | :----------------------------------------------------------: | -| DFF (for reference) 5.83um x 7.07 um | \ No newline at end of file +| DFF (for reference) 5.83um x 7.07 um | diff --git a/docs/source/characterization.md b/docs/source/characterization.md index 9d70985e..60adc74a 100644 --- a/docs/source/characterization.md +++ b/docs/source/characterization.md @@ -6,19 +6,19 @@ This page of the documentation explains the characterization of OpenRAM. ## Table of Contents -1. [Characterization Overview](#characterization-overview) -2. [Characterizer Organization](#characterizer-organization) -3. [Characterization Options](#characterization-options) -4. [Characterization Measurements](#characterization-measurements) -5. [Analytical Characterization](#analytical-characterization) -6. [Multiport Characterization](#multiport-characterization) -7. [Characterizer Unit Test Use](#characterizer-unit-test-use) -8. [Functional Simulation](#functional-simulation) -9. [Power/Delay Characterization](#powerdelay-characterization) -10. [Timing Graph](#timing-graph) -11. [Graph Creation Example: Buffer](#graph-creation-example-buffer) -12. [Graph Module Exclusion](#graph-module-exclusion) -13. [Timing Measurement Checks](#timing-measurement-checks) +1. [Characterization Overview](#characterization-overview) +1. [Characterizer Organization](#characterizer-organization) +1. [Characterization Options](#characterization-options) +1. [Characterization Measurements](#characterization-measurements) +1. [Analytical Characterization](#analytical-characterization) +1. [Multiport Characterization](#multiport-characterization) +1. [Characterizer Unit Test Use](#characterizer-unit-test-use) +1. [Functional Simulation](#functional-simulation) +1. [Power/Delay Characterization](#powerdelay-characterization) +1. [Timing Graph](#timing-graph) +1. [Graph Creation Example: Buffer](#graph-creation-example-buffer) +1. [Graph Module Exclusion](#graph-module-exclusion) +1. [Timing Measurement Checks](#timing-measurement-checks) @@ -62,9 +62,9 @@ Measures the timing/power through SPICE simulation: ## Characterization Measurements * Characterization is performed primarily to generate tables in .lib file - * cell_rise/cell_fall - Delay of from negative clock edge to DOUT when reading a 1 or 0 respectively - * rise_transition/fall_transition - Slew of DOUT when read 1 or 0 respectively - * Setup and hold time for inputs (setup_rising, hold_rising) + * cell\_rise/cell\_fall - Delay of from negative clock edge to DOUT when reading a 1 or 0 respectively + * rise\_transition/fall\_transition - Slew of DOUT when read 1 or 0 respectively + * Setup and hold time for inputs (setup\_rising, hold\_rising) * Total power and leakage power * Delays and slews and intended to be independent of clock period. * Fall delays are copied to rise delays after characterization* @@ -175,4 +175,4 @@ In addition to measurements done for characterization. Several measurements are * Bitline measurements - Voltage of bitlines measured the checked to have at least a 10% difference * Bitcell Measurements - Voltage measured on internal storage of cells and check that they match the operation. * Output voltage measurements - Output voltage (`DOUT`) checked at end of cycle so it matches operation. -* Sense Amp Enable Timing - Delay of `S_EN` should not exceed a half-period \ No newline at end of file +* Sense Amp Enable Timing - Delay of `S_EN` should not exceed a half-period diff --git a/docs/source/control_logic.md b/docs/source/control_logic.md index 2f4a6850..f760e379 100644 --- a/docs/source/control_logic.md +++ b/docs/source/control_logic.md @@ -7,13 +7,13 @@ This page of the documentation explains the control logic and timing of OpenRAM. ## Table of Contents 1. [Read Timing](#read-timing) -2. [Write Timing](#write-timing) -3. [External Control Signals](#external-control-signals) -4. [Internal Control Signals](#internal-control-signals) -5. [Replica Bitline (RBL)](#replica-bitline-rbl) -6. [Internal Control Signals Diagram (Read)](#internal-control-signals-diagram-read) -7. [Internal Control Signals Diagram (Write)](#internal-control-signals-diagram-write) -8. [Clock Distribution](#clock-distribution) +1. [Write Timing](#write-timing) +1. [External Control Signals](#external-control-signals) +1. [Internal Control Signals](#internal-control-signals) +1. [Replica Bitline (RBL)](#replica-bitline-rbl) +1. [Internal Control Signals Diagram (Read)](#internal-control-signals-diagram-read) +1. [Internal Control Signals Diagram (Write)](#internal-control-signals-diagram-write) +1. [Clock Distribution](#clock-distribution) @@ -97,4 +97,4 @@ This page of the documentation explains the control logic and timing of OpenRAM. * This is LOW when disabled * `gated_clk_bar = cs && clk_bar` * This is LOW when disabled - * `gated_clk = cs && clk_buf` \ No newline at end of file + * `gated_clk = cs && clk_buf` diff --git a/docs/source/debug.md b/docs/source/debug.md index dac6b0ec..73cc31db 100644 --- a/docs/source/debug.md +++ b/docs/source/debug.md @@ -7,11 +7,11 @@ This page of the documentation explains the debugging and unit testing of OpenRA ## Table of Contents 1. [Unit Tests](#unit-tests) -2. [Unit Test Organization](#unit-test-organization) -3. [Running Unit Tests](#running-unit-tests) -4. [Successful Unit Tests](#successful-unit-tests) -5. [Debugging Unsuccessful Unit Tests](#debugging-unsuccessful-unit-tests-or-openrampy) -6. [Temporary Output Files](#temporary-output-files) +1. [Unit Test Organization](#unit-test-organization) +1. [Running Unit Tests](#running-unit-tests) +1. [Successful Unit Tests](#successful-unit-tests) +1. [Debugging Unsuccessful Unit Tests](#debugging-unsuccessful-unit-tests-or-sram_compilerpy) +1. [Temporary Output Files](#temporary-output-files) @@ -124,7 +124,7 @@ OK -## Debugging Unsuccessful Unit Tests (or openram.py) +## Debugging Unsuccessful Unit Tests (or sram\_compiler.py) * You will get an ERROR during unit test and see a stack trace * Examine the temporary output files in the temp directory (/tmp/mydir) ```console diff --git a/docs/source/design_modules.md b/docs/source/design_modules.md index 84117ff2..f220ef2b 100644 --- a/docs/source/design_modules.md +++ b/docs/source/design_modules.md @@ -6,17 +6,17 @@ This page of the documentation explains the hierarchical design modules of OpenR ## Table of Contents -1. [Hierarchical Design Modules](#hierarchical-design-modules-1) -2. [Bank](#bank) -3. [Port Data](#port-data) -4. [Port Address](#port-address) -5. [Plain Bitcell Array](#plain-bitcell-array) -6. [Variations of Bitcells Needed](#variations-of-bitcells-needed) -7. [Replica Bitcell Array](#replica-bitcell-array) -8. [1D Arrays](#1d-arrays) -9. [2D Arrays](#2d-arrays) -10. [Delay Line](#delay-line) -11. [Hierarchical (Address) Decoder](#hierarchical-address-decoder) +1. [Hierarchical Design Modules](#hierarchical-design-modules-1) +1. [Bank](#bank) +1. [Port Data](#port-data) +1. [Port Address](#port-address) +1. [Plain Bitcell Array](#plain-bitcell-array) +1. [Variations of Bitcells Needed](#variations-of-bitcells-needed) +1. [Replica Bitcell Array](#replica-bitcell-array) +1. [1D Arrays](#1d-arrays) +1. [2D Arrays](#2d-arrays) +1. [Delay Line](#delay-line) +1. [Hierarchical (Address) Decoder](#hierarchical-address-decoder) @@ -61,7 +61,7 @@ This page of the documentation explains the hierarchical design modules of OpenR ## Port Address * Encapsulates the row decoder and wordline driver for easier placement next to a bank -* Each port will have its own port_address module +* Each port will have its own port\_address module @@ -149,4 +149,4 @@ This page of the documentation explains the hierarchical design modules of OpenR * `hierarchical_predecode_4x16` * Hierarchical decoder uses predecoder + another decode stage * Predecoders are also used for the column mux decode and bank select decode -* Wish list: Handle thin bitcell height \ No newline at end of file +* Wish list: Handle thin bitcell height diff --git a/docs/source/index.md b/docs/source/index.md index 167ed550..208bc30d 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -6,14 +6,15 @@ These pages provide the documentation of OpenRAM. You can use the links below to ## Table of Contents -1. [OpenRAM Dependencies](#openram-dependencies) -1. [Supported Technologies](#supported-technologies) -1. [Bitcells](./bitcells.md#go-back) -1. [Architecture](./architecture.md#go-back) -1. [Implementation](#implementation) -1. [Technology and Tool Portability](#technology-and-tool-portability) -1. [Basic Usage](./basic_usage.md#go-back) -1. [Tutorials](./tutorials.md#go-back) +1. [OpenRAM Dependencies](#openram-dependencies) +1. [Supported Technologies](#supported-technologies) +1. [Basic Setup](./basic_setup.md#go-back) +1. [Basic Usage](./basic_usage.md#go-back) +1. [Bitcells](./bitcells.md#go-back) +1. [Architecture](./architecture.md#go-back) +1. [Implementation](#implementation) +1. [Technology and Tool Portability](#technology-and-tool-portability) +1. [Tutorials](./tutorials.md#go-back) 1. [Debugging and Unit Testing](./debug.md#go-back) 1. [Technology Setup](./technology_setup.md#go-back) 1. [Library Cells](./library_cells.md#go-back) @@ -24,13 +25,12 @@ These pages provide the documentation of OpenRAM. You can use the links below to 1. [Characterization](./characterization.md#go-back) 1. [Results](./results.md#go-back) 1. [FAQ](./FAQ.md#go-back) -1. [Contributors/Collaborators](#contributorscollaborators) +1. [Contributors/Collaborators](#contributorscollaborators) ## OpenRAM Dependencies - Please see the Dockerfile for the required versions of tools. In general, the OpenRAM compiler has very few dependencies: @@ -38,16 +38,16 @@ In general, the OpenRAM compiler has very few dependencies: + Make + Python 3.6 or higher + Various Python packages (pip install -r requirements.txt) -+ [Git] ++ Git Commercial tools (optional): * Spice Simulator * Hspice I-2013.12-1 (or later) * CustomSim 2017 (or later) * DRC - * Calibre 2017.3_29.23 + * Calibre 2017.3\_29.23 * LVS - * Calibre 2017.3_29.23 + * Calibre 2017.3\_29.23 @@ -55,7 +55,7 @@ Commercial tools (optional): * NCSU FreePDK 45nm * Non-fabricable but contains DSM rules * Calibre or klayout for DRC/LVS -* MOSIS 0.35um (SCN4M_SUBM) +* MOSIS 0.35um (SCN4M\_SUBM) * Fabricable technology * Magic/Netgen or Calibre for DRC/LVS * Skywater 130nm (sky130) diff --git a/docs/source/library_cells.md b/docs/source/library_cells.md index 7e9bd95a..732e9667 100644 --- a/docs/source/library_cells.md +++ b/docs/source/library_cells.md @@ -7,12 +7,12 @@ This page of the documentation explains the library cells of OpenRAM. ## Table of Contents 1. [Required Hard/Custom Cells](#required-hardcustom-cells) -2. [Bitcell(s)](#bitcells) -3. [Multiport Bitcells](#multiport-bitcells) -4. [Parameterized Bitcell](#parameterized-bitcell) -5. [Sense Amplifier](#sense-amplifier) -6. [DFF](#dff) -7. [Tristate/Write Driver](#tristatewrite-driver) +1. [Bitcell(s)](#bitcells) +1. [Multiport Bitcells](#multiport-bitcells) +1. [Parameterized Bitcell](#parameterized-bitcell) +1. [Sense Amplifier](#sense-amplifier) +1. [DFF](#dff) +1. [Tristate/Write Driver](#tristatewrite-driver) @@ -93,4 +93,4 @@ This page of the documentation explains the library cells of OpenRAM. ## Tristate/Write Driver * Tristate is used for multi-bank implementations * Write driver drives the data onto the bitlines -* Both of these are currently library cells, but plans are to make them dynamically generated (`ptristate.py` and `pwrite_driver.py`) \ No newline at end of file +* Both of these are currently library cells, but plans are to make them dynamically generated (`ptristate.py` and `pwrite_driver.py`) diff --git a/docs/source/results.md b/docs/source/results.md index da613f9f..8909049c 100644 --- a/docs/source/results.md +++ b/docs/source/results.md @@ -6,13 +6,13 @@ This page of the documentation explains the results of OpenRAM. ## Table of Contents -1. [Small Layouts](#small-layouts) -2. [Relative Planar Bitcells](#relative-planar-bitcells-035um-scmos) -3. [SRAM Area](#sram-area) -4. [Generated Layout by OpenRAM](#generated-layout-by-openram-for-a-multiport-6r2w-sram-in-32-nm-soi-cmos-technology) -5. [Timing and Density Results for Generated SRAMs](#timing-and-density-results-for-generated-srams) -6. [Comparison with Fabricated SRAMs](#comparison-with-fabricated-srams) -7. [Conclusions](#conclusions) +1. [Small Layouts](#small-layouts) +1. [Relative Planar Bitcells](#relative-planar-bitcells-035um-scmos) +1. [SRAM Area](#sram-area) +1. [Generated Layout by OpenRAM](#generated-layout-by-openram-for-a-multiport-6r2w-sram-in-32-nm-soi-cmos-technology) +1. [Timing and Density Results for Generated SRAMs](#timing-and-density-results-for-generated-srams) +1. [Comparison with Fabricated SRAMs](#comparison-with-fabricated-srams) +1. [Conclusions](#conclusions) @@ -64,4 +64,4 @@ This page of the documentation explains the results of OpenRAM. * OpenRAM is open-sourced, flexible, and portable and can be adapted to various technologies. * OpenRAM generates the circuit, functional model, and layout of variable-sized SRAMs. * OpenRAM provides a memory characterizer for synthesis timing/power models. -* We are also actively introducing new features, such as non-6T memories, variability characterization, word-line segmenting, characterization speed-up, etc. \ No newline at end of file +* We are also actively introducing new features, such as non-6T memories, variability characterization, word-line segmenting, characterization speed-up, etc. diff --git a/docs/source/routing.md b/docs/source/routing.md index 4160c243..bcaa45fa 100644 --- a/docs/source/routing.md +++ b/docs/source/routing.md @@ -7,9 +7,9 @@ This page of the documentation explains the routing of OpenRAM. ## Table of Contents 1. [Power Supply Options](#power-supply-options) -2. [Power Routing](#power-routing) -3. [Power Supply Algorithm](#power-supply-algorithm) -4. [Channel Router](#channel-router) +1. [Power Routing](#power-routing) +1. [Power Supply Algorithm](#power-supply-algorithm) +1. [Channel Router](#channel-router) @@ -53,4 +53,4 @@ This page of the documentation explains the routing of OpenRAM. | | | | :-------------------------------------------------------------------------: | :---------------------------------------------------------------------: | -| Credit: Chen & Chang, EDA Handbook, Chapter 12, Global and detailed routing | Sense amp to data flop connection | \ No newline at end of file +| Credit: Chen & Chang, EDA Handbook, Chapter 12, Global and detailed routing | Sense amp to data flop connection | diff --git a/docs/source/technology_setup.md b/docs/source/technology_setup.md index f937e53b..1d0c9d98 100644 --- a/docs/source/technology_setup.md +++ b/docs/source/technology_setup.md @@ -7,17 +7,17 @@ This page of the documentation explains the technology setup of OpenRAM. ## Table of Contents 1. [Technology Directories](#technology-directories) -2. Technology Configuration: +1. Technology Configuration: 1. [Layer Map](#technology-configuration-layer-map) - 2. [GDS](#technology-configuration-gds) - 3. [DRC](#technology-configuration-drc) - 4. [SPICE](#technology-configuration-spice) - 5. [Parameters](#technology-configuration-parameters) + 1. [GDS](#technology-configuration-gds) + 1. [DRC](#technology-configuration-drc) + 1. [SPICE](#technology-configuration-spice) + 1. [Parameters](#technology-configuration-parameters) ## Technology Directories -* Environment variable OPENRAM_TECH specifies list of technology directories +* Environment variable OPENRAM\_TECH specifies list of technology directories * Similar to `*nix $PATH` * Directory structure: ``` @@ -73,7 +73,7 @@ This page of the documentation explains the technology setup of OpenRAM. ## Technology Configuration: DRC -* Creates the design_rule class with several parts: +* Creates the design\_rule class with several parts: * Grid size * Location of DRC, LVS, PEX rules and layer map * Subset of design rules for FEOL and BEOL @@ -122,4 +122,4 @@ drc["metal3_to_metal3"] = drc_lut({(0.00, 0.0) : 0.07, * Rise/fall input slews * Analytical parameters * Used for analytical delay and power estimation - * E.g. device capacitance and "on" resistance \ No newline at end of file + * E.g. device capacitance and "on" resistance diff --git a/macros/Makefile b/macros/Makefile index 630541c0..a61a180e 100644 --- a/macros/Makefile +++ b/macros/Makefile @@ -65,7 +65,7 @@ OPENRAM_TMP=/openram/macros/$*/tmp %.ok: configs/%.py @echo "Building $*" @mkdir -p $* - @$(DOCKER_CMD) python3 -u /openram/compiler/openram.py $(OPENRAM_OPTS) -o $* -p /openram/macros/$* /openram/macros/$< && touch $@ + @$(DOCKER_CMD) python3 -u /openram/sram_compiler.py $(OPENRAM_OPTS) -o $* -p /openram/macros/$* /openram/macros/$< && touch $@ .DELETE_ON_ERROR: $(STAMPS) diff --git a/openram.mk b/openram.mk index f169fa32..9c131580 100644 --- a/openram.mk +++ b/openram.mk @@ -1,6 +1,6 @@ OPENRAM_HOME := $(abspath $(TOP_DIR)/compiler) OPENRAM_TECH := $(abspath $(TOP_DIR)/technology) -OPENRAM_COMPILER := $(OPENRAM_HOME)/openram.py +OPENRAM_COMPILER := $(abspath $(TOP_DIR)/sram_compiler.py) PDK_ROOT ?= $(TOP_DIR) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..5aebe600 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,15 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "openram" +version = "1.2.0" +description = "An open-source static random access memory (SRAM) compiler" +authors = [ + { name="Matthew Guthaus", email="mrg@ucsc.edu" }, +] +keywords = [ "sram", "magic", "gds", "netgen", "ngspice", "netlist" ] +readme = "README.md" +license = { text = "BSD-3-Clause License" } +requires-python = ">=3.6" \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..6494baeb --- /dev/null +++ b/setup.py @@ -0,0 +1,57 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2021 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +from setuptools import setup, find_namespace_packages + + +# Include these folder from the root of repo as submodules +include = ["compiler", "docker", "technology", "macros"] +# Exclude files/folders with these words +exclude = ["docs", "images"] + + +# Find all modules inside the 'compiler' folder +dirs = [] +for dir in find_namespace_packages(): + if any(x in dir for x in exclude): + continue + dirs.append(dir) + +# Replace 'compiler' with 'openram' for package names +packages = [] +for dir in dirs: + packages.append(dir) + +# Make the included folders submodules of openram package +for i in range(len(packages)): + if any(x in packages[i] for x in include): + packages[i] = "openram." + packages[i] + +# Fix directory paths +for i in range(len(dirs)): + dirs[i] = dirs[i].replace(".", "/") + +# Insert the root as the openram module +packages.insert(0, "openram") +dirs.insert(0, "") + +# Zip package names and their paths +package_dir = {k: v for k, v in zip(packages, dirs)} + + +# Create a list of required packages +with open("requirements.txt") as f: + reqs = f.read().splitlines() + + +# Call the setup to create the package +setup( + packages=packages, + package_dir=package_dir, + include_package_data=True, + install_requires=reqs, +) \ No newline at end of file diff --git a/compiler/openram.py b/sram_compiler.py similarity index 96% rename from compiler/openram.py rename to sram_compiler.py index fbbf4466..4ae4a819 100755 --- a/compiler/openram.py +++ b/sram_compiler.py @@ -16,8 +16,13 @@ a LEF (.lef) file for preliminary P&R (real one should be from layout) a Liberty (.lib) file for timing analysis/optimization """ +import os import sys import datetime +try: + import openram +except: + sys.path.append(os.getenv("OPENRAM_HOME")) import globals as g (OPTS, args) = g.parse_args() diff --git a/technology/scn4m_subm/tech/.magicrc b/technology/scn4m_subm/tech/.magicrc index 8fdad1b7..29c9977f 100644 --- a/technology/scn4m_subm/tech/.magicrc +++ b/technology/scn4m_subm/tech/.magicrc @@ -1,3 +1,12 @@ +# Check if the openram package is installed. If so, append that path to $OPENRAM_TECH. +# If $OPENRAM_TECH isn't defined and the package is installed, use the package directory. +set openramhome [exec echo -e "import os\ntry:\n import openram\n print(os.path.dirname(openram.__file__))\nexcept:\n print(\"notinstalled\")" | python3 -] +set openramtech "${openramhome}/technology/scn4m_subm/tech" +if { [info exists ::env(OPENRAM_TECH)] && ($openramhome != "notinstalled") } { + set ::env(OPENRAM_TECH) $env(OPENRAM_TECH):$openramtech +} elseif { $openramhome != "notinstalled" } { + set ::env(OPENRAM_TECH) $openramtech +} set openram_paths [split $::env(OPENRAM_TECH) ":"] foreach p $openram_paths { path sys +$p/scn4m_subm/tech