Merge branch 'dev' into char

This commit is contained in:
Bugra Onal 2022-11-29 14:50:00 -08:00
commit b9f16ea490
99 changed files with 1862 additions and 336 deletions

View File

@ -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

7
.gitignore vendored
View File

@ -14,5 +14,10 @@ technology/sky130/*_lib
technology/sky130/tech/.magicrc
.idea
compiler/tests/results/
sky*/
open_pdks/
dist/
openram.egg-info/
sky130A/
sky130B/
skywater-pdk/
sky130_fd_bd_sram/

117
HINTS.md
View File

@ -1,117 +0,0 @@
# Debugging
When OpenRAM runs, it puts files in a temporary directory that is
shown in the banner at the top. Like:
```
/tmp/openram_mrg_18128_temp/
```
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
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)
+ <topcell>.spice (Magic)
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
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.

24
MANIFEST.in Normal file
View File

@ -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

View File

@ -84,7 +84,7 @@ $(SRAM_LIB_DIR): check-pdk-root
git clone $(SRAM_LIB_GIT_REPO) $(SRAM_LIB_DIR) && \
cd $(SRAM_LIB_DIR) && git pull && git checkout $(SRAM_LIB_GIT_COMMIT))
install: $(SRAM_LIB_DIR) pdk
install: $(SRAM_LIB_DIR)
@[ -d $(PDK_ROOT)/sky130A ] || \
(echo "Warning: $(PDK_ROOT)/sky130A not found!! Run make pdk first." && false)
@[ -d $(PDK_ROOT)/skywater-pdk ] || \
@ -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

173
README.md
View File

@ -19,161 +19,8 @@ predictive and fabricable technologies.
# Documentation
Please take a look at our presentation We have created a detailed
presentation that serves as our [documentation][documentation].
This is the most up-to-date information, so please let us know if you see
things that need to be fixed.
# Basic Setup
## Dependencies
Please see the Dockerfile for the required versions of tools.
In general, the OpenRAM compiler has very few dependencies:
+ Docker
+ Make
+ Python 3.6 or higher
+ Various Python packages (pip install -r requirements.txt)
+ [Git]
## Docker
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.
## Environment
You must 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).
You should also add OPENRAM\_HOME to your PYTHONPATH.
For example add this to your .bashrc:
```
export OPENRAM_HOME="$HOME/openram/compiler"
export OPENRAM_TECH="$HOME/openram/technology"
export PYTHONPATH=$OPENRAM_HOME
```
Note that if you want symbols to resolve in your editor, you may also want to add the specific technology
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,
[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 this automatically, you can run:
cd $HOME/openram
make pdk
Then you must also install the [Sky130] SRAM build space and the appropriate cell views
by running:
cd $HOME/openram
make install
# Basic Usage
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:
```
# Data word size
word_size = 2
# Number of words in the memory
num_words = 16
# Technology to use in $OPENRAM_TECH
tech_name = "scn4m_subm"
# You can use the technology nominal corner only
nominal_corner_only = True
# Or you can specify particular corners
# Process corners to characterize
# process_corners = ["SS", "TT", "FF"]
# Voltage corners to characterize
# supply_voltages = [ 3.0, 3.3, 3.5 ]
# Temperature corners to characterize
# temperatures = [ 0, 25 100]
# Output directory for the results
output_path = "temp"
# Output file base name
output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name)
# Disable analytical models for full characterization (WARNING: slow!)
# analytical_delay = False
```
You can then run OpenRAM by executing:
```
python3 $OPENRAM_HOME/openram.py myconfig
```
You can see all of the options for the configuration file in
$OPENRAM\_HOME/options.py
To run designs in Docker, it is suggested to use, for example:
```
cd openram/macros
make example_config_scn4m_subm
```
# Unit Tests
Regression testing performs a number of tests for all modules in OpenRAM.
From the unit test directory ($OPENRAM\_HOME/tests),
use the following command to run all regression tests:
```
cd openram/compiler/tests
make -j 3
```
The -j can run with 3 threads. By default, this will run in all technologies.
To run a specific test in all technologies:
```
cd openram/compiler/tests
make 05_bitcell_array_test
```
To run a specific technology:
```
cd openram/compiler/tests
TECHS=scn4m_subm make 05_bitcell_array_test
```
To increase the verbosity of the test, add one (or more) -v options and
pass it as an argument to OpenRAM:
```
ARGS="-v" make 05_bitcell_array_test
```
Unit test results are put in a directory:
```
openram/compiler/tests/results/<technology>/<test>
```
If the test fails, there will be a tmp directory with intermediate results.
If the test passes, this directory will be deleted to save space.
You can view the .out file to see what the output of a test is in either case.
Please see our [documentation][documentation] and let us know if anything needs
updating.
# Get Involved
@ -186,17 +33,25 @@ You can view the .out file to see what the output of a test is in either case.
# Further Help
+ [Additional hints](./HINTS.md)
+ [Documentation][documentation]
+ [OpenRAM Slack Workspace][Slack]
+ [OpenRAM Users Group][user-group] ([subscribe here][user-group-subscribe])
+ [OpenRAM Developers Group][dev-group] ([subscribe here][dev-group-subscribe])
+ <a rel="me" href="https://fosstodon.org/@mrg">@mrg@fostodon.org</a>
# License
OpenRAM is licensed under the [BSD 3-clause License](./LICENSE).
# Publications
+ M. R. Guthaus, J. E. Stine, S. Ataei, B. Chen, B. Wu, M. Sarwar, "OpenRAM: An Open-Source Memory Compiler," Proceedings of the 35th International Conference on Computer-Aided Design (ICCAD), 2016
+ S. Ataei, J. Stine, M. Guthaus, “A 64 kb differential single-port 12T SRAM design with a bit-interleaving scheme for low-voltage operation in 32 nm SOI CMOS,” International Conference on Computer Design (ICCD), 2016, pp. 499-506.
+ E. Ebrahimi, M. Guthaus, J. Renau, “Timing Speculative SRAM”, IEEE In- ternational Symposium on Circuits and Systems (ISCAS), 2017
+ B. Wu, J.E. Stine, M.R. Guthaus, "Fast and Area-Efficient Word-Line Optimization", IEEE International Symposium on Circuits and Systems (ISCAS), 2019
+ B. Wu, M. Guthaus, "Bottom Up Approach for High Speed SRAM Word-line Buffer Insertion Optimization", IFIP/IEEE International Conference on Very Large Scale Integration (VLSI-SoC), 2019
+ H. Nichols, M. Grimes, J. Sowash, J. Cirimelli-Low, M. Guthaus "Automated Synthesis of Multi-Port Memories and Control", IFIP/IEEE International Conference on Very Large Scale Integration (VLSI-SoC), 2019
# Contributors & Acknowledgment
- [Matthew Guthaus] from [VLSIDA] created the OpenRAM project and is the lead architect.
@ -215,9 +70,9 @@ If I forgot to add you, please let me know!
[Github issues]: https://github.com/VLSIDA/OpenRAM/issues
[Github pull request]: https://github.com/VLSIDA/OpenRAM/pulls
[Github project]: https://github.com/VLSIDA/OpenRAM
[Github project]: https://github.com/VLSIDA/OpenRAM
[documentation]: https://docs.google.com/presentation/d/10InGB33N51I6oBHnqpU7_w9DXlx-qe9zdrlco2Yc5co/edit?usp=sharing
[documentation]: docs/source/index.md
[dev-group]: mailto:openram-dev-group@ucsc.edu
[user-group]: mailto:openram-user-group@ucsc.edu
[dev-group-subscribe]: mailto:openram-dev-group+subscribe@ucsc.edu

22
__init__.py Normal file
View File

@ -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)

View File

@ -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:

View File

@ -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

View File

@ -186,12 +186,15 @@ class cell_properties():
self.names["col_cap_bitcell_2port"] = "col_cap_cell_2rw"
self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw"
self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw"
self.names["internal"] = "internal"
self.use_strap = False
self._ptx = _ptx(model_is_subckt=False,
bin_spice_models=False)
self._pgate = _pgate(add_implants=False)
self._inv_dec = cell(["A", "Z", "vdd", "gnd"],
["INPUT", "OUTPUT", "POWER", "GROUND"])
@ -231,6 +234,12 @@ class cell_properties():
self._row_cap_2port = bitcell(["wl0", "wl1", "gnd"],
["INPUT", "INPUT", "POWER", "GROUND"])
self._internal = cell([],[])
@property
def internal(self):
return self._internal
@property
def ptx(self):
return self._ptx

View File

@ -24,7 +24,7 @@ import subprocess
VERSION = "1.2.0"
NAME = "OpenRAM v{}".format(VERSION)
USAGE = "openram.py [options] <config file>\nUse -h for help.\n"
USAGE = "sram_compiler.py [options] <config file>\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(":"):

1
compiler/modules/__init__.py Normal file → Executable file
View File

@ -80,3 +80,4 @@ from .write_mask_and_array import *
from .sram_1bank import *
from .sram_config import *
from .sram import *
from .internal_base import *

View File

@ -29,7 +29,3 @@ class bitcell_1port(bitcell_base):
"""
self.add_graph_edges(graph, port_nets)
def is_non_inverting(self):
"""Return input to output polarity for module"""
return False

View File

@ -99,8 +99,3 @@ class bitcell_2port(bitcell_base):
# Port 1 edges
graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self)
graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self)
def is_non_inverting(self):
"""Return input to output polarity for module"""
return False

View File

@ -265,3 +265,15 @@ class bitcell_base(design):
delay = math.sqrt(2*tstep*(vdd-spice["nom_threshold"])/m)
return delay
def build_graph(self, graph, inst_name, port_nets):
"""
Adds edges based on inputs/outputs.
Overrides base class function.
"""
debug.error("Must override build_graph function in bitcell base class.")
def is_non_inverting(self):
"""Return input to output polarity for module"""
return False

View File

@ -0,0 +1,14 @@
# 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 base import design
class internal_base(design):
def __init__(self, name, cell_name=None, prop=None):
design.__init__(self, name, cell_name, prop)

View File

@ -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.
"""
###################

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -121,8 +121,11 @@ $(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"
@test -f $(TOP_DIR)/compiler/tests/results/$*.ok && echo "$* ... PASS!" && \
rm -rf $(TOP_DIR)/compiler/tests/results/$* || echo "$* ... FAIL!"
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!"
endif
.DELETE_ON_ERROR: $(TEST_STAMPS)
.PHONY: docker-pull

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

38
docs/source/FAQ.md Normal file
View File

@ -0,0 +1,38 @@
### [Go Back](./index.md#table-of-contents)
# 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:
```
/tmp/openram_mrg_18128_temp/
```
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
Depending on your DRC/LVS tools, there will also be:
+ `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
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`
file. If the DRC fails, it will typically show you the command that was used
to run Calibre or Magic+Netgen.

View File

@ -0,0 +1,25 @@
### [Go Back](./index.md#table-of-contents)
# Architecture
This page of the documentation explains the architecture of OpenRAM.
## Table of Contents
1. [SRAM Architecture](#sram-architecture)
## SRAM Architecture
* Bit-cell Array
* Multiport Bitcells
* Each port:
* Address Decoder(s)
* Wordline Driver(s)
* Column Multiplexer(s)
* Bitline Precharge(s)
* Sense Amplifier(s)
* Write Driver(s)
* Control Logic with Replica Bitline
![OpenRAM SRAM Architecture](../assets/images/architecture/sram_architecture.png)

View File

@ -0,0 +1,72 @@
### [Go Back](./index.md#table-of-contents)
# Base Data Structures
This page of the documentation explains the base data structures of OpenRAM.
## Table of Contents
1. [Design Classes](#design-classes)
1. [Base Class Inheritance](#base-class-inheritance)
1. [Parameterized Transistor](#parameterized-transistor-ptx-or-pfinfet)
1. [Parameterized Cells](#parameterized-cells)
## Design Classes
<img align="right" height="100" src="../assets/images/base_data_structures/layout_1.png">
* SPICE and GDS2 Interfaces
* Custom cells (read GDS and SPICE)
* Generated cells (creates GDS and SPICE "on the fly")
* Netlist functions
* Add (directional) pins
* Add and connect instances
<img align="right" height="100" src="../assets/images/base_data_structures/layout_2.png">
* Layout functions
* Place instances
* Add wires, routes, vias
* Channel and Power router
* Verification functions (wrap around DRC and LVS tools)
## Base Class Inheritance
```mermaid
flowchart TD
A[design.py \n\n General design and helper DRC constants] --> B[hierarchy_design.py \n\n DRC/LVS functions]
B --> C["hierarchy_spice.py \n\n Netlist related functionality"]
B --> D["hierarchy_layout.py \n\n Layout related functionality"]
C --> E["Functions: \n add_pins \n add_inst"]
C --> F["sp_read \n sp_write \n Power data \n Delay data"]
D --> G["Functions: \n add_{layout_pin,rect,...} \n place_inst \n create_channel_route \n etc."]
D --> H["gds_read \n gds_write \n get_blockages \n etc."]
```
## Parameterized Transistor (ptx or pfinfet)
<img align="right" height="100" src="../assets/images/base_data_structures/transistor.png">
* Creates variable size/finger nmos or pmos transistor
* Optional gate and source/drain contacts in naive way
* Not optimal layout, but "good enough"
* Offset (0,0) is lower-left corner of active area
* Size/fingers effect on size must be estimated elsewhere perhaps by trying configurations
## Parameterized Cells
<img align="right" height="230" src="../assets/images/base_data_structures/parameterized_cell.png">
Dynamically generated cells (in `$OPENRAM_HOME/pgates`)
* Not the most efficient layouts but "ok"
* Try to use restrictive design rules to keep them portable
* Transistors
* `ptx`, `pfinfet`
* Logic gates
* `pinv`, `pnand2`, `pnand3`, `pnor2`
* Buffer/drivers
* `pbuf`, `pinvbuf`, `pdriver`
* SRAM Logic
* `precharge`, `single_level_column_mux`

103
docs/source/basic_setup.md Normal file
View File

@ -0,0 +1,103 @@
### [Go Back](./index.md#table-of-contents)
This page shows the basic setup for using OpenRAM.
# Basic Setup
## Dependencies
Please see the Dockerfile for the required versions of tools.
In general, the OpenRAM compiler has very few dependencies:
+ Docker
+ Make
+ Python 3.6 or higher
+ Various Python packages (pip install -r requirements.txt)
+ 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:
```
cd OpenRAM/docker
make build
```
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
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.
+ OPENRAM\_TECH should point to one or more root technology directories (colon separated).
If you have the library installed and OPENRAM\_HOME set, the library will use the installation on
the OPENRAM\_HOME path.
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"
export PYTHONPATH=$OPENRAM_HOME
```
Note that if you want symbols to resolve in your editor, you may also want to add the specific technology
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,
[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 this automatically, you can run:
```
cd $HOME/OpenRAM
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

206
docs/source/basic_usage.md Normal file
View File

@ -0,0 +1,206 @@
### [Go Back](./index.md#table-of-contents)
# Basic Usage
This page of the documentation explains the basic usage of OpenRAM.
## Table of Contents
1. [Environment Variable Setup](#environment-variable-setup-assuming-bash)
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)
> **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"`
* Colon separated list so you can have private technology directories
* Must also have any PDK related variables set up
* Add compiler to `PYTHONPATH`
* `export PYTHONPATH="$PYTHONPATH:$OPENRAM_HOME"`
## 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
num_words = 16
# Technology to use in $OPENRAM_TECH
tech_name = "scn4m_subm"
# You can use the technology nominal corner only
nominal_corner_only = True
# Or you can specify particular corners
# Process corners to characterize
# process_corners = ["SS", "TT", "FF"]
# Voltage corners to characterize
# supply_voltages = [ 3.0, 3.3, 3.5 ]
# Temperature corners to characterize
# temperatures = [ 0, 25 100]
# Output directory for the results
output_path = "temp"
# Output file base name
output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name)
# Disable analytical models for full characterization (WARNING: slow!)
# analytical_delay = False
```
You can then run OpenRAM by executing:
```
python3 $OPENRAM_HOME/../sram_compiler.py myconfig
```
You can see all of the options for the configuration file in
$OPENRAM\_HOME/options.py
To run designs in Docker, it is suggested to use, for example:
```
cd OpenRAM/macros
make example_config_scn4m_subm
```
* Common arguments:
* `-t` specify technology (scn4m_subm or scmos or freepdk45)
* `-v` increase verbosity of output
* `-n` don't run DRC/LVS
* `-c` perform simulation-based characterization
* `-d` don't purge /tmp directory contents
## Configuration Files
* Memories are created using a Python configuration file to replicate results
* No YAML, JSON, etc.
* Complete configuration options are in `$OPENRAM_HOME/options.py`
* Some options can be specified on the command line as well
* Not recommended for replicating results
* Example configuration file:
```python
# Data word size
word_size = 2
# Number of words in the memory
num_words = 16
# Technology to use in $OPENRAM_TECH
tech_name = "scn4m_subm"
# Process corners to characterize
process_corners = [ "TT" ]
# Voltage corners to characterize
supply_voltages = [ 3.3 ]
# Temperature corners to characterize
temperatures = [ 25 ]
# Output directory for the results
output_path = "temp"
# Output file base name
output_name = "sram_16x2"
# Disable analytical models for full characterization (WARNING: slow!)
# analytical_delay = False
# To force this to use magic and netgen for DRC/LVS/PEX
# Could be calibre for FreePDK45
drc_name = "magic"
lvs_name = "netgen"
pex_name = "magic"
```
## Common Configuration File Options
* Characterization corners
* `supply_voltages = [1.7, 1.8, 1.9]`
* `temperatures = [25, 50, 100]`
* `process_corners = ["SS", "TT", "FF"]`
* Do not generate layout
* `netlist_only = True`
* Multi-port options
* `num_rw_ports = 1`
* `num_r_ports = 1`
* `num_w_ports = 0`
* Customized module or bit cell
* `bitcell = "bitcell_1rw_1r"`
* `replica_bitcell = "replica_bitcell_1rw_1r"`
* Enable simulation characterization
> **Warning**: Slow!
* `analytical_delay = False`
* Output name and location
* `output_path = "temp"`
* `output_name = "sram_32x256"`
* Force tool selection (should match the PDK!)
* `drc_name = "magic"`
* `lvs_name = "netgen"`
* `pex_name = "magic"`
* Include shared configuration options using Python imports
* `from corners_freepdk45 import *`
## Output Files
The output files are placed in the `output_dir` defined in the configuration file.
The base name is specified by `output_name` and suffixes are added.
The final results files are:
* GDS (.gds)
* SPICE (.sp)
* Verilog (.v)
* P&R Abstract (.lef)
* Liberty (multiple corners .lib)
* Datasheet (.html)
* Log (.log)
* Configuration (.py) for replication of creation
## Data Sheets
![Datasheet 1](../assets/images/basic_usage/datasheet_1.png)
![Datasheet 2](../assets/images/basic_usage/datasheet_2.png)
![Datasheet 3](../assets/images/basic_usage/datasheet_3.png)

40
docs/source/bitcells.md Normal file
View File

@ -0,0 +1,40 @@
### [Go Back](./index.md#table-of-contents)
# Bitcells
This page of the documentation explains the bitcells supported by OpenRAM.
## Table of Contents
1. [Multiport Bitcells](#multiport-bitcells)
1. [Relative Bitcell Sizes](#relative-bitcell-sizes-035um-scmos)
1. [Thin SRAM Bitcells](#thin-sram-bitcells-130nm)
## Multiport Bitcells
* Based on 6T SRAM cell
* Standard read-write
* Isolated read-only ports
* Write-only port (not sized for reads)
* Can accommodate foundry bitcells
![Multiport Bitcells](../assets/images/bitcells/multiport_bitcells.png)
## Relative Bitcell Sizes (0.35um SCMOS)
| <img height="184" src="../assets/images/bitcells/6t.png"> | <img height="278" src="../assets/images/bitcells/10t.png"> | <img height="424" src="../assets/images/bitcells/dff.png"> |
| :-----------------------------------------------: | :------------------------------------------------: | :--------------------------------------------------: |
| Standard 6T (1rw) 6.8um x 9.2um | Isolated Read 10T (1rw, 1r) 10.9um x 13.9um | DFF 21.9um x 21.2um (from OSU standard cell library) |
## Thin SRAM Bitcells (130nm)
| <img height="158" src="../assets/images/bitcells/thin_single.png"> | <img height="158" src="../assets/images/bitcells/thin_dual.png"> | <img height="158" src="../assets/images/bitcells/thin_single_straps.png"> | <img height="197" src="../assets/images/bitcells/thin_dual_straps.png"> |
| :--------------------------------------------------------: | :------------------------------------------------------: | :-----------------------------------------------------------------: | :-------------------------------------------------------------: |
| Single Port 1.2um x 1.58um | Dual Port 2.40um x 1.58um | Single Port (w/ straps & taps) 2.49um x 1.58um | Dual Port (w/ straps & taps) 3.12um x 1.97um |
| <img height="707" src="../assets/images/bitcells/dff_reference.png"> |
| :----------------------------------------------------------: |
| DFF (for reference) 5.83um x 7.07 um |

View File

@ -0,0 +1,178 @@
### [Go Back](./index.md#table-of-contents)
# Characterization
This page of the documentation explains the characterization of OpenRAM.
## Table of Contents
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)
## Characterization Overview
Measures the timing/power through SPICE simulation:
* Generates the SPICE stimulus: The stimulus is written in standard SPICE format and can be used with any simulator that supports this.
* Runs the circuit simulations: To produce the average power, setup/hold times, and timing delay of the memory design.
* Parses the simulator's output: The setup time, hold time, and delay are found using a bidirectional search technique.
* Produces the output in a Liberty (.lib) file.
## Characterizer Organization
* Core Modules
* `delay.py` - Generates the delays and power of input SRAM and corner
* `setup_hold.py` - Generates setup and hold timing of DFFs by corner
* `lib.py` - Characterizes SRAM and builds Liberty file
* `stimuli.py` - Generates SPICE stimulus file for characterization
* Auxiliary Modules
* `simulation.py` - Base class for SRAM characterization modules
* `trim_spice.py` - Removes portions of SRAM SPICE to speedup simulation
* `measurements.py` - Contains classes to aid SPICE measurements
* `char_utils.py` - Contains common functions used during characterization
* `logical_effort.py` - Helper class for analytical delay model
* Testing Support Modules
* Other modules are derivatives of the simulation module used in the unit tests
## Characterization Options
* Characterization by Configuration File
* The process, voltage, and temperature (PVT) for characterization are defined in the config file.
* Running OpenRAM generates a Liberty (.lib) file for every corner characterized.
* Delays, slews, power determined for each input slew and outputs load combination in config file.
* OpenRAM Characterization Mode
* Supports analytical and SPICE based characterization
* Analytical characterization is default
* SPICE characterization enabled with -c flag (requires SPICE simulator)
## 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)
* 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*
* Characterizer can help with debugging or optimization
* Delay characterizer also produces Sense Amp Enable Timing to help debug read failures.
* Delay class can edited or can be base class if other measurements are wanted.
> **Note**: Rise delays are dependent on the clock period if measured from negative clock edge due to precharge.
## Analytical Characterization
* Delay
* Assumes a worst case delay through decoder, word line, and bit lines
* Calculates RC delay at each stage using parameters for handmade cells, unit capacitances, and unit resistances which are defined in the technology setup
* Output slews are estimated based on delays
* Wire delays only estimated for bitline delay
* Power
* Dynamic power at each stage calculated using $C * V^2 * frequency$
* Leakage power estimated with parameters in technology setup
* Corners add linear variations in delay and power
## Multiport Characterization
* Supports any port configuration specified by the configuration file
* Any number of Read, Write, and Read/Write ports
* Any custom bitcells may require modifications for characterization
* Characterization Algorithm
* Feasible period found for each port
* Common minimum period is found for all ports
* Power and delay is characterized on each port
* Characterization Runtime
* Ports are characterized separately for accuracy
* Runtime increases linearly with ports and can be slow.
## Characterizer Unit Test Use
* OpenRAM will use the characterizer to generate data for .lib by default
* Characterizer modules can be instantiated separately from lib.py to generate and test data
* Example: `21_ngspice_delay_test.py`
* Delay module generates data to compare against previously generated data to error check any recent OpenRAM changes having a large effect on the delay
* Delay/Simulation module can be used as base class and altered to include custom measurements
## Functional Simulation
* Assumes uninitialized memory
* Random operations
* Uses multiple ports when available
* Read, write, or noop
* Random address
* Random data
* Memory checks
* Uses standard CMOS noise margins
* Compares read with last write (or feed-through value if being written)
## Power/Delay Characterization
* Prunes unused portions of circuit for run-time
* Setup time, hold time, and delay are found using a bidirectional search.
* Finds a feasible period
* Iterates until convergence
* Dynamic and leakage measured
* Output saved in Liberty (.lib) file.
* Uses NLDM
* Wish list: CCS
## Timing Graph
* OpenRAM has SPICE like modules and instances
* A timing graph is created using the SPICE netlist, names and paths through lower level modules.
* Graph used in characterizer for debugging timing issues associated with the Sense Amp Enable
## Graph Creation Example: Buffer
![Buffer 1](../assets/images/characterization/buffer_1.png)
* SPICE instantiated module (vdd, gnd excluded from graph)
* Xbuf1 A Z vdd gnd Buffer
* Base module has its own naming for ports and internal signals
![Buffer 2](../assets/images/characterization/buffer_2.png)
* Node names reduced to top-most SPICE level with internal signals maintained.
* Internal modules determine edges between nodes
![Buffer 3](../assets/images/characterization/buffer_3.png)
* Most lower level modules (gates, PTX, FF, etc) determine edges by connecting every input to every output by default.
* Custom timing paths can be overridden in any module
## Graph Module Exclusion
* Modules can be excluded from the graph before it's built
* This can help trim timing paths that are known to not affect the overall timing
![Graph Module Exclusion](../assets/images/characterization/exclusion.png)
| <img height="400" src="../assets/images/characterization/graph_with_exclusion.png"> | <img height="400" src="../assets/images/characterization/graph_without_exclusion.png"> |
| :-------------------------------------------------------------------------: | :----------------------------------------------------------------------------: |
| Graph without exclusion | Graph with exclusion |
## Timing Measurement Checks
In addition to measurements done for characterization. Several measurements are done to help debug memory failures.
* 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

View File

@ -0,0 +1,100 @@
### [Go Back](./index.md#table-of-contents)
# Control Logic and Timing
This page of the documentation explains the control logic and timing of OpenRAM.
## Table of Contents
1. [Read Timing](#read-timing)
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)
## Read Timing
![Read Timing](../assets/images/control_logic/read_timing.png)
### Read Timing Simulation
![Read Timing Simulation](../assets/images/control_logic/read_simulation.png)
## Write Timing
![Write Timing](../assets/images/control_logic/write_timing.png)
### Write Timing Simulation
![Write Timing Simulation](../assets/images/control_logic/write_simulation.png)
## External Control Signals
* Behaves as a synchronous register interface
* Address and data captured on positive edge
* Data is available after the negative edge (before next positive edge)
* Clock is used for internal control generation
* Clock cycle
* Clock high: capture inputs + precharge + decode
* Clock low: read/write
* Reads and writes on multiple ports to the same address in the same cycle "feed through" but the noise margins of the bitcell must be able to handle this
## Internal Control Signals
* Sense Enable (`s_en`) -- Active high sense amp enable from Replica Bit Line (RB)
* RBL input: `rbl_wl = gated_clk_bar & we_bar`
* Delayed RBL output: `pre_s_en = DELAY(rbl_bl)`
* Buffered enable: `s_en = BUF(pre_s_en)`
* Write Driver Enable (`w_en`) -- Active high write driver enable
* `w_en = we`
* `we` is directly from control flops
* Precharge Enable Bar (`p_en_bar`) -- Active low enable of precharge
* `p_en_bar = !(gated_clk_bar)`
* Active for writes as well to prevent half select destruction
* Word line enable (`wl_en`) -- Active high word line enable
* `wl_en = BUF(gated_clk_bar)`
## Replica Bitline (RBL)
<img align="right" width=300 src="../assets/images/control_logic/replica_array.png">
* Determines when to start sensing by replicating a bitcell array column
* Replica Bitline Column (RBC) matches transition of column
* `rbl_bl = RBC(rbl_wl)`
* Delay Line delays the input signal to match word line driver
* `pre_s_en = DELAY(rbl_bl)`
* Buffer drives `s_en` signal to sense amps
## Internal Control Signals Diagram (Read)
![Internal Control Signals (Read)](../assets/images/control_logic/internal_signals_read.png)
## Internal Control Signals Diagram (Write)
![Internal Control Signals (Write)](../assets/images/control_logic/internal_signals_write.png)
## Clock Distribution
* External clock (`clk`)
* Buffered clock (`clk_buf`) drives all DFFs in the design
* `clk_buf = BUF(clk)`
* Buffered clock bar (`clk_bar`) used in control logic
* `clk_bar = INV(clk_buf)`
* Gated Clocks (`gated_clk` and `gated_clk_bar`) used in control logic
* This is LOW when disabled
* `gated_clk_bar = cs && clk_bar`
* This is LOW when disabled
* `gated_clk = cs && clk_buf`

179
docs/source/debug.md Normal file
View File

@ -0,0 +1,179 @@
### [Go Back](./index.md#table-of-contents)
# Debugging and Unit Testing
This page of the documentation explains the debugging and unit testing of OpenRAM.
## Table of Contents
1. [Unit Tests](#unit-tests)
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)
## Unit Tests
OpenRAM has the set of thorough regression tests implemented with the Python unit test framework:
* Unit tests allow users to add features without worrying about breaking functionality.
* Unit tests guide users when porting to new technologies.
* Every sub-module has its own regression test.
* There are regression tests for memory functionality, library cell verification, timing verification, and technology verification.
## Unit Test Organization
* `00_code_format_test.py` does basic lint checking.
* `01_library_drc_test.py` checks DRC of all library cells for the technology.
* `02_library_lvs_test.py` checks LVS of all library cells for the technology.
* `03_*_test.py` checks DRC and LVS of wires and transistors classes.
* `04_*_test.py` checks DRC and LVS of parameterized cells.
* `05-19_*_test.py` checks DRC and LVS of module cells (moving upward in hierarchy with numbers)
* `20_*_test.py` check DRC and LVS of full SRAM layouts with various configurations.
* `21_*_test.py` checks timing of full SRAMs and compares (with tolerance) to precomputed result.
> **Note**: These tests may fail using different simulators due to the tolerance level.
* `22_*_test.py` checks functional simulation of full SRAMs with various configurations.
* `23-25_*_test.py` checks lib, lef, and verilog outputs using diff.
* `30_openram_test.py` checks command-line interface and whether output files are created.
## Running Unit Tests
Regression testing performs a number of tests for all modules in OpenRAM.
From the unit test directory ($OPENRAM\_HOME/tests),
use the following command to run all regression tests:
```
cd OpenRAM/compiler/tests
make -j 3
```
The -j can run with 3 threads. By default, this will run in all technologies.
To run a specific test in all technologies:
```
cd OpenRAM/compiler/tests
make 05_bitcell_array_test
```
To run a specific technology:
```
cd OpenRAM/compiler/tests
TECHS=scn4m_subm make 05_bitcell_array_test
```
To increase the verbosity of the test, add one (or more) -v options and
pass it as an argument to OpenRAM:
```
ARGS="-v" make 05_bitcell_array_test
```
Unit test results are put in a directory:
```
OpenRAM/compiler/tests/results/<technology>/<test>
```
If the test fails, there will be a tmp directory with intermediate results.
If the test passes, this directory will be deleted to save space.
You can view the .out file to see what the output of a test is in either case.
* Tests can be run in the `$OPENRAM_HOME/tests` directory
* Command line arguments
* `-v` for verbose
* `-t` freepdk45 for tech
* `-d` to preserve /tmp results (done automatically if test fails)
* Individual tests
* `01_library_drc_test.py`
* All tests
* `regress.py`
## Successful Unit Tests
```console
user@host:/openram/compiler/tests$ ./regress.py
______________________________________________________________________________
|==============================================================================|
|========= Running Test for: =========|
|========= scn4m_subm =========|
|========= ./regress.py =========|
|========= /tmp/openram_mrg_13245_temp/ =========|
|==============================================================================|
runTest (00_code_format_check_test.code_format_test) ... ok
runTest (01_library_drc_test.library_drc_test) ... ok
runTest (02_library_lvs_test.library_lvs_test) ... ok
runTest (03_contact_test.contact_test) ... ok
runTest (03_path_test.path_test) ... ok
.
.
.
```
```console
user@host:/openram/compiler/tests$ ./03_ptx_1finger_nmos_test.py
______________________________________________________________________________
|==============================================================================|
|========= Running Test for: =========|
|========= scn4m_subm =========|
|========= ./03_ptx_1finger_nmos_test.py =========|
|========= /tmp/openram_mrg_13750_temp/ =========|
|==============================================================================|
.
----------------------------------------------------------------------
Ran 1 test in 0.596s
OK
```
## 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
_____________________________________________________________________________
|==============================================================================|
|========= Running Test for: =========|
|========= scn4m_subm =========|
|========= ./04_pinv_10x_test.py =========|
|========= /tmp/mydir =========|
|==============================================================================|
ERROR: file magic.py: line 174: DRC Errors pinv_0 2
F
======================================================================
FAIL: runTest (__main__.pinv_test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "./04_pinv_10x_test.py", line 22, in runTest
self.local_check(tx)
File "/Users/mrg/openram/compiler/tests/testutils.py", line 45, in local_check
self.fail("DRC failed: {}".format(a.name))
AssertionError: DRC failed: pinv_0
----------------------------------------------------------------------
Ran 1 test in 0.609s
FAILED (failures=1)
```
### It didn't finish... where are my files?
* OpenRAM puts all temporary files in a temporary directory named:
* `/tmp/openram_<user>_<pid>_temp`
* This allows multiple processes/users to simultaneously run
* This allows /tmp to be mapped to a RAM disk for faster performance
* After a successful run, the directory and contents are deleted
* To preserve the contents, you can run with the `-d` option for debugging
* `OPENRAM_TMP` will override the temporary directory location for debug
* `export OPENRAM_TMP="/home/myname/debugdir"`
## Temporary Output Files
* DRC standard output (`*.drc.out`), errors (`*.drc.err`), and results (`*.drc.results`)
* LVS standard output (`*.lvs.out`), errors (`*.lvs.out`), and results (`*.lvs.results`)
* GDS (and Magic) files for intermediate modules (`temp.gds`, `temp.mag`)
* SPICE netlist for intermediate module results (`temp.sp`)
* Extracted layout netlist for intermediate module results (`extracted.sp`)
* Magic only: Run scripts for DRC (`run_drc.sh`) and LVS (`run_lvs.sh`)
* Calibre only: Runset file for DRC (`drc_runset`) and LVS (`lvs_runset`)

View File

@ -0,0 +1,152 @@
### [Go Back](./index.md#table-of-contents)
# Hierarchical Design Modules
This page of the documentation explains the hierarchical design modules of OpenRAM.
## Table of Contents
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)
## Hierarchical Design Modules
* Memory building blocks
* SRAM, Bank, Control Logic, Decoders, Column Mux, Various arrays (DFF, drivers)
* Can override every module with a custom one in the configuration file
* Each module must:
* Create netlist
* Define inputs/outputs
* Instantiate and connect sub-modules and cells
* Create layout
* Place and route itself
* Route vdd/gnd to M3
* (Optional) Run DRC/LVS
* Analytically model timing and power
## Bank
<img align="right" height="180" src="../assets/images/design_modules/bank.png">
* Encompasses everything except
* Data and Address Flops
* Control logic
* Multi-bank logic
* Arranges ports
* Port 0 is left/bottom
* Port 1 is right/top
## Port Data
* Encapsulates all of the datapath logic for a rw, w, or r port
* Sense amplifiers (read types)
* Write drivers (write types)
* Column mux (if any)
* Precharge (read or write type) (write to not destroy half selected cells in a row)
* Also includes a precharge for the replica columns
## 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
## Plain Bitcell Array
<img align="right" height="150" src="../assets/images/design_modules/bitcell_array.png">
* 2D Array of bit cells
* Each row alternately flips vertically
* Assume bitcells tile
* Boundary is determined by boundary layer in GDS
* Word line must abut
* Bit lines must abut
## Variations of Bitcells Needed
* Normal bitcell for data storage
* Replica bitcell that is fixed to output a 0 value
* Dummy bitcell with bitlines disconnected (purely for wordline load and lithography regularity)
<img align="right" width=300 src="../assets/images/design_modules/replica_bitcell_array.png">
## Replica Bitcell Array
* Bitcells: B=regular, D=dummy, R=replica
* Main bitcell array ( $\color{green}{\textrm{green}}$ )
* Replica cols for each read port ( $\color{skyblue}{\textrm{blue}}$ ) on left or right (any number)
* Dummy bitcells on the top, bottom, left, and right for lithography regularity ( $\color{red}{\textrm{red}}$ )
* Replica columns activate two replica bitcells
* $\color{blue}{\textrm{One}}$ driven by replica wordline
* $\color{royalblue}{\textrm{Second}}$ driven by one of the normal wordlines (dark blue)
* Second port word and bit lines not shown
* Would be on right and top
## 1D Arrays
<img align="right" height="100" src="../assets/images/design_modules/1d_array.png">
* Several modules have 1D arrays:
* `sense_amp_array`
* `write_driver_array`
* `precharge_array`
* `single_level_column_mux_array`
* `tri_gate_array`
* `wordline_driver` (*should change name to _array)
* `sense_amp_array`, `write_driver_array`, `tri_gate_array` match column mux stride to space out
* Wish list: Allow wide sense amplifier array to use multiple rows of sense amplifiers.
<img align="right" height="250" src="../assets/images/design_modules/2d_array_vertical.png">
## 2D Arrays
* Regular DFF arrays (`dff_array.py`)
* Buffered DFF arrays (`dff_buf_array.py`)
* Inverted DFF array (`dff_inv_array.py`)
* Can be $1*N$ or $N*1$ or $M*N$
* Wish list: $M*N$ routes pins to edges
<p align="center">
<img align="center" height="80" src="../assets/images/design_modules/2d_array_horizontal.png">
</p>
## Delay Line
<img align="right" height="200" src="../assets/images/design_modules/delay_line.png">
* Configurable fanout and stages
* `[4,4,4]` means 3 FO4 stages
* `[1,1,4,4]` means 2 FO1 stages followed by FO4
## Hierarchical (Address) Decoder
<img align="right" height="200" src="../assets/images/design_modules/address_decoder.png">
* Generic `hierarchical_predecode` class
* Places routing rails and decode inverters
* Derived to implement multiple predecoders
* `hierarchical_predecode_2x4`
* `hierarchical_predecode_3x8`
* `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

111
docs/source/index.md Normal file
View File

@ -0,0 +1,111 @@
# OpenRAM Documentation
![OpenRAM Logo](../../images/OpenRAM_logo_yellow_transparent.svg)
These pages provide the documentation of OpenRAM. You can use the links below to navigate through the documentation.
## Table of Contents
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)
1. [Base Data Structures](./base_data_structures.md#go-back)
1. [Hierarchical Design Modules](./design_modules.md#go-back)
1. [Control Logic and Timing](./control_logic.md#go-back)
1. [Routing](./routing.md#go-back)
1. [Characterization](./characterization.md#go-back)
1. [Results](./results.md#go-back)
1. [FAQ](./FAQ.md#go-back)
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:
+ Docker
+ Make
+ Python 3.6 or higher
+ Various Python packages (pip install -r requirements.txt)
+ Git
Commercial tools (optional):
* Spice Simulator
* Hspice I-2013.12-1 (or later)
* CustomSim 2017 (or later)
* DRC
* Calibre 2017.3\_29.23
* LVS
* Calibre 2017.3\_29.23
## Supported Technologies
* NCSU FreePDK 45nm
* Non-fabricable but contains DSM rules
* Calibre or klayout for DRC/LVS
* MOSIS 0.35um (SCN4M\_SUBM)
* Fabricable technology
* Magic/Netgen or Calibre for DRC/LVS
* Skywater 130nm (sky130)
* Fabricable technology
* Magic/Netgen or klayout
## Implementation
* Front-end mode
* Generates SPICE, layout views, timing models
* Netlist-only mode can skip the physical design too
* Doesn't perform DRC/LVS
* Estimates power/delay analytically
* Back-end mode
* Generates SPICE, layout views, timing models
* Performs DRC/LVS
* Can perform at each level of hierarchy or at the end
* Simulates power/delay
* Can be back-annotated or not
## Technology and Tool Portability
* OpenRAM is technology independent by using a technology directory that includes:
* Technology's specific information
* Technology's rules such as DRC rules and the GDS layer map
* Custom designed library cells (6T, sense amp, DFF) to improve the SRAM density.
* For technologies that have specific design requirements, such as specialized well contacts, the user can include helper functions in the technology directory.
* Verification wrapper scripts
* Uses a wrapper interface with DRC and LVS tools that allow flexibility
* DRC and LVS can be performed at all levels of the design hierarchy to enhance bug tracking.
* DRC and LVS can be disabled completely for improved run-time or if licenses are not available.
## Contributors/Collaborators
<img align="right" height="120" src="../assets/images/logos/okstate.png">
* Prof. Matthew Guthaus (UCSC)
* Prof. James Stine & Dr. Samira Ataei (Oklahoma State University)
* UCSC students:
* Bin Wu
* Hunter Nichols
* Michael Grimes
* Jennifer Sowash
* Jesse Cirimelli-Low
<img align="right" height="100" src="../assets/images/logos/vlsida.png">
* Many other past students:
* Jeff Butera
* Tom Golubev
* Marcelo Sero
* Seokjoong Kim

View File

@ -0,0 +1,96 @@
### [Go Back](./index.md#table-of-contents)
# Library Cells
This page of the documentation explains the library cells of OpenRAM.
## Table of Contents
1. [Required Hard/Custom Cells](#required-hardcustom-cells)
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)
## Required Hard/Custom Cells
* Located in
* `$OPENRAM_TECH/<tech>/gds_lib`
* `$OPENRAM_TECH/<tech>/sp_lib`
* A few library cells with layout and SPICE:
* Bitcell (and dummy and replica bitcell)
* Sense amplifier
* DFF (from a standard cell library)
* (Removing soon: write driver, tristate)
* P&R border layer defined for placement
* Sense amplifier pitch matched width to bitcell
## Bitcell(s)
* Python code is in `$OPENRAM_HOME/bitcells`
* Layout in `$OPENRAM_TECH/<tech>/gds_lib `
* SPICE in `$OPENRAM_TECH/<tech>/sp_lib`
* Can be a foundry bitcell if you have the GDS and SPICE.
* May include multiple port configurations:
* `bitcell.py` uses `cell_6t.{gds,sp}` - standard 1rw port
* `bitcell_1w_1r.py` uses `cell_1w_1r.{gds,sp}` for 1w and 1r port
* `bitcell_1rw_1r.py` uses `cell_1rw_1r.{gds,sp}` for 1rw and 1r port
* Wish list: pin names are fixed right now as `bl`, `br`, `wl`, `vdd`, `gnd`
## Multiport Bitcells
* Based on 6T SRAM cell
* Standard read-write
* Isolated read-only ports
* Write-only port (not sized for reads)
* Can accommodate foundry bitcells
![Multiport Bitcells](../assets/images/bitcells/multiport_bitcells.png)
## Parameterized Bitcell
* If a custom bitcell is not available, we create one with user design rules.
* Not good for area, but may still be better than DFFs.
* Can be useful for simulation/functional work before custom bitcell is available.
* Example 1 RW pbitcell compared to custom 1RW
<img height="300" src="../assets/images/bitcells/parameterized_1.png">
<img height="300" src="../assets/images/bitcells/parameterized_2.png">
## Sense Amplifier
* Needs a sense amplifier that is pitch matched to the bitcell.
* `$OPENRAM_TECH/gds_lib/sense_amp.gds`
* `$OPENRAM_TECH/sp_lib/sense_amp.sp`
* `$OPENRAM_HOME/modules/sense_amp.py`
* Wish list: pin names are fixed right now as `bl`, `br`, `dout`, `en`, `vdd`, `gnd`
## DFF
* Needs a standard cell DFF for the address and data registers.
* `$OPENRAM_TECH/gds_lib/dff.gds `
* `$OPENRAM_TECH/sp_lib/dff.sp`
* `$OPENRAM_HOME/modules/dff.py`
* Have auxiliary code to create:
* Buffered DFFs (`dff_buf.py`) using dynamically generated inverters (pinv)
* Inverted output DFFs (`dff_inv.py`) using a dynamically generated inverters (pinv)
* 2-D DFF arrays
* Regular DFF arrays (`dff_array.py`)
* Buffered DFF arrays (`dff_buf_array.py`)
* Inverted DFF array (`dff_inv_array.py`)
* Wish list: pin names are fixed right now as `D`, `Q`, `Qb`, `clk`, `vdd`, `gnd`
## 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`)

67
docs/source/results.md Normal file
View File

@ -0,0 +1,67 @@
### [Go Back](./index.md#table-of-contents)
# Results
This page of the documentation explains the results of OpenRAM.
## Table of Contents
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)
## Small Layouts
| <img width="320" src="../assets/images/results/small_layouts_1.png"> | <img width="320" src="../assets/images/results/small_layouts_2.png"> |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
| 512 x 16b x 1rw FreePDK45 | 2048 x 32b x 1rw FreePDK45 |
## Relative Planar Bitcells (0.35um SCMOS)
| <img height="184" src="../assets/images/bitcells/6t.png"> | <img height="278" src="../assets/images/bitcells/10t.png"> | <img height="424" src="../assets/images/bitcells/dff.png"> |
| :-----------------------------------------------: | :------------------------------------------------: | :--------------------------------------------------: |
| Standard 6T (1rw) 6.8um x 9.2um | Isolated Read 10T (1rw, 1r) 10.9um x 13.9um | DFF 21.9um x 21.2um (from OSU standard cell library) |
## SRAM Area
![SRAM Area](../assets/images/results/sram_area.png)
## Generated Layout by OpenRAM for a multiport (6R/2W) SRAM in 32 nm SOI CMOS Technology
![Generated Layout](../assets/images/results/generated_layout.jpg)
## Timing and Density Results for Generated SRAMs
![Timing and Density Results](../assets/images/results/timing_and_density_results.png)
## Comparison with Fabricated SRAMs
| $\textrm{Reference}$ | $\textrm{Feature Size}$ | $\textrm{Technology}$ | $\textrm{Density } (Mb/mm^2)$ |
| :---------------------- | :---------------------: | :-------------------: | :---------------------------: |
| $\textrm{IEEE-VLSI'08}$ | $65 nm$ | $\textrm{CMOS}$ | $0.7700$ |
| $\textrm{JSSC'11}$ | $45 nm$ | $\textrm{CMOS}$ | $0.3300$ |
| $\textrm{JSSC'13}$ | $40 nm$ | $\textrm{CMOS}$ | $0.9400$ |
| $\textrm{OpenRAM}$ | $45 nm$ | $\textrm{FreePDK45}$ | $0.8260$ |
| $\textrm{JSSC'92}$ | $0.5 \mu m$ | $\textrm{CMOS}$ | $0.0036$ |
| $\textrm{JSSC'94}$ | $0.5 \mu m$ | $\textrm{BICMOS}$ | $0.0020$ |
| $\textrm{JSSC'99}$ | $0.5 \mu m$ | $\textrm{CMOS}$ | $0.0050$ |
| $\textrm{OpenRAM}$ | $0.5 \mu m$ | $\textrm{SCMOS}$ | $0.0050$ |
## Conclusions
* The main motivation behind OpenRAM is to promote and simplify memory-related research in academia and provides a platform to implement and test new memory designs.
* 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.

56
docs/source/routing.md Normal file
View File

@ -0,0 +1,56 @@
### [Go Back](./index.md#table-of-contents)
# Routing
This page of the documentation explains the routing of OpenRAM.
## Table of Contents
1. [Power Supply Options](#power-supply-options)
1. [Power Routing](#power-routing)
1. [Power Supply Algorithm](#power-supply-algorithm)
1. [Channel Router](#channel-router)
## Power Supply Options
* Unrouted
* Leave must-connect metal 3 pins for vdd and gnd within the array
* Grid
* Connect in a metal 3 and 4 grid
* Blockage aware
* Can encounter DRC errors with off-grid pins
* Works with commercial tools but not so well with OpenRoad
* Work in Progress: Hanan Grid / Steiner Tree:
* Route tree on Hanan metal 3 and 4 grid instead of full grid
* Blockage aware
## Power Routing
<img align="right" height="200" src="../assets/images/routing/power_routing.png">
* All power pins are brought to M3 and routed as a grid on M3/M4
* Considers blockages of M3/M4 by control and data signals
* Considers wide/long metal spacing rules
## Power Supply Algorithm
* 1st: Route vertical and horizontal grids (blockage aware, allow connection to correct supply)
* 2nd: Check direct overlaps of power pins
* 3rd: Single direction probes to connect
* 4th: A* maze router
## Channel Router
* SRAMs typically try to use minimal layers of metal
* Primarily used to connect decoders, input/output circuitry, or control logic
* Wish list
* Minimize number of tracks
* Must consider impact on floorplan
| <img height="200" src="../assets/images/routing/channel_router_book.png"> | <img height="200" src="../assets/images/routing/channel_router_connection.png"> |
| :-------------------------------------------------------------------------: | :---------------------------------------------------------------------: |
| Credit: Chen & Chang, EDA Handbook, Chapter 12, Global and detailed routing | Sense amp to data flop connection |

View File

@ -0,0 +1,125 @@
### [Go Back](./index.md#table-of-contents)
# Technology Setup
This page of the documentation explains the technology setup of OpenRAM.
## Table of Contents
1. [Technology Directories](#technology-directories)
1. Technology Configuration:
1. [Layer Map](#technology-configuration-layer-map)
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
* Similar to `*nix $PATH`
* Directory structure:
```
techname/
__init__.py -- Sets up PDK environment
tech/ -- Contains technology configuration
__init__.py -- Loads all modules
tech.py -- SPICE, DRC, GDS, and layer config
gds_lib/ -- Contains .gds files for each lib cell
sp_lib/ -- Contains .sp file for each lib cell
models/ -- Contains SPICE device corner models
(tf/) -- May contain some PDK material
(mag_lib/) -- May contain other layout formats
```
## Technology Configuration: Layer Map
* Layer map contains mapping of layer names to GDS layers
* Layer names are used in OpenRAM code directly
```python
layer={}
layer["vtg"] = -1
layer["vth"] = -1
layer["contact"] = 47
layer["pwell"] = 41
...
layer["metal4"] = 31
layer["text"] = 63
layer["boundary"] = 63
layer["blockage"] = 83
```
## Technology Configuration: GDS
* OpenRAM uses the gdsMill library (included and heavily modified)
* Units defined for GDS format
* First number is DB units per user units
* Second number is DB unit in meters
```python
# GDS file info
GDS={}
# gds units
GDS["unit"]=(0.001,1e-6)
# default label zoom
GDS["zoom"] = 0.5
```
* Zoom defines default zoom for labels
* More info on the GDS format at:
* http://boolean.klaasholwerda.nl/interface/bnf/gdsformat.html
## Technology Configuration: DRC
* 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
* Design rules have common naming scheme (names used in OpenRAM)
* `minwidth_<layer>`
* `<layer>_to_<layer>`
* `<layer>_extend_<layer>`
* `minarea_<layer>`
* Allows rule tables for complex rules
```python
# Minimum spacing of metal3 wider than 0.09 & longer than 0.3 = 0.09
# Minimum spacing of metal3 wider than 0.27 & longer than 0.9 = 0.27
# Minimum spacing of metal3 wider than 0.5 & longer than 1.8 = 0.5
# Minimum spacing of metal3 wider than 0.9 & longer than 2.7 = 0.9
# Minimum spacing of metal3 wider than 1.5 & longer than 4.0 = 1.5
drc["metal3_to_metal3"] = drc_lut({(0.00, 0.0) : 0.07,
(0.09, 0.3) : 0.09,
(0.27, 0.9) : 0.27,
(0.50, 1.8) : 0.5,
(0.90, 2.7) : 0.9,
(1.50, 4.0) : 1.5})
```
## Technology Configuration: SPICE
* Device models (and corners)
* Defaults simulation values
* Voltage
* Temperature
* Feasible period for simulation
* Rise/fall input slews
* Analytical parameters
* For example, device capacitance and "on" resistance
* Used for analytical delay and power estimation
## Technology Configuration: Parameters
* Default design parameters
* Being cleaned up and standardized...
* Defaults simulation values
* Voltage
* Temperature
* Feasible period for simulation
* Rise/fall input slews
* Analytical parameters
* Used for analytical delay and power estimation
* E.g. device capacitance and "on" resistance

10
docs/source/tutorials.md Normal file
View File

@ -0,0 +1,10 @@
### [Go Back](./index.md#table-of-contents)
# Tutorials
This page of the documentation includes tutorials for OpenRAM.
## Table of Contents
1. []()
<!-- ADD TUTORIALS HERE -->

View File

@ -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)

View File

@ -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)

15
pyproject.toml Normal file
View File

@ -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"

57
setup.py Normal file
View File

@ -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,
)

View File

@ -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()

View File

@ -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

View File

@ -29,10 +29,10 @@ class sky130_bitcell_array(bitcell_array, sky130_bitcell_base_array):
# This will create a default set of bitline/wordline names
self.create_all_bitline_names()
self.create_all_wordline_names()
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
self.add_supply_pins()
def add_modules(self):
""" Add the modules used in this design """

View File

@ -125,11 +125,23 @@ class sky130_bitcell_base_array(bitcell_base_array):
def add_supply_pins(self):
""" Add the layout pins """
# Copy a vdd/gnd layout pin from every cell
for inst in self.insts:
if "wlstrap" in inst.name:
try:
self.copy_layout_pin(inst, "VPWR", "vdd")
except:
pass
try:
self.copy_layout_pin(inst, "VGND", "gnd")
except:
pass
for row in range(self.row_size):
for col in range(self.column_size):
inst = self.cell_inst[row, col]
for pin_name in ["vdd", "gnd"]:
self.copy_layout_pin(inst, pin_name)
if row == 2: #add only 1 label per col
if 'VPB' or 'vpb' in self.cell_inst[row, col].mod.pins:

View File

@ -5,29 +5,36 @@
# All rights reserved.
#
import debug
from base import design
from base import get_libcell_size
from tech import layer, GDS
from copy import deepcopy
from modules import internal_base
from tech import cell_properties as props
class sky130_internal(design):
class sky130_internal(internal_base):
def __init__(self, version, name=""):
super().__init__(name)
prop = deepcopy(props.internal)
prop.boundary_layer = "mem"
if version == "wlstrap":
self.name = "sky130_fd_bd_sram__sram_sp_wlstrap"
prop.port_order = ["vdd"]
prop.port_types = ["POWER"]
prop.port_map = {'vdd': 'VPWR'}
elif version == "wlstrap_p":
self.name = "sky130_fd_bd_sram__sram_sp_wlstrap_p"
prop.port_order = ["gnd"]
prop.port_types = ["GROUND"]
prop.port_map = {'gnd': 'VGND'}
elif version == "wlstrapa":
self.name = "sky130_fd_bd_sram__sram_sp_wlstrapa"
prop.port_order = ["vdd"]
prop.port_types = ["POWER"]
prop.port_map = {'vdd': 'VPWR'}
elif version == "wlstrapa_p":
self.name = "sky130_fd_bd_sram__sram_sp_wlstrapa_p"
prop.port_order = ["gnd"]
prop.port_types = ["GROUND"]
prop.port_map = {'gnd': 'VGND'}
else:
debug.error("Invalid version", -1)
design.__init__(self, name=self.name)
(self.width, self.height) = get_libcell_size(self.name,
GDS["unit"],
layer["mem"])
# pin_map = get_libcell_pins(pin_names, self.name, GDS["unit"])
super().__init__(name, cell_name=self.name, prop=prop)

View File

@ -228,10 +228,6 @@ class sky130_replica_bitcell_array(replica_bitcell_array, sky130_bitcell_base_ar
self.add_via_stack_center(from_layer=pin.layer,
to_layer='m2',
offset=pin_center+supply_inst.ll()+cell_inst.ll() + vector(connection_offset,0))
#self.add_power_pin(name=pin_name,
# loc=pin_center+supply_inst.ll()+cell_inst.ll() + vector(connection_offset,0),
# start_layer=pin.layer,
# end_layer='m2')
# add well contacts to perimeter cells
@ -277,9 +273,6 @@ class sky130_replica_bitcell_array(replica_bitcell_array, sky130_bitcell_base_ar
self.add_via_stack_center(from_layer=pin.layer,
to_layer='m2',
offset=pin_center+supply_inst.ll()+cell_inst.ll() + vector(connection_offset,0))
#self.add_power_pin(name=pin_name,
# loc=pin_center+supply_inst.ll()+cell_inst.ll() + vector(connection_offset,0),
# start_layer=pin.layer)
min_area = drc["minarea_{}".format('m3')]
for track,supply, offset in zip(range(1,5),['vdd','vdd','gnd','gnd'],[min_area * 6,min_area * 6, 0, 0]):

View File

@ -90,8 +90,8 @@ class sky130_replica_column(sky130_bitcell_base_array):
self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND")
#self.add_pin("top_gate", "INPUT")
#self.add_pin("bot_gate", "INPUT")
self.add_pin("top_gate", "INPUT")
self.add_pin("bot_gate", "INPUT")
def add_modules(self):
self.replica_cell = factory.create(module_type="replica_bitcell_1port", version="opt1")

20
technology/sky130/tech/tech.py Normal file → Executable file
View File

@ -782,14 +782,26 @@ library_prefix_name = "sky130_fd_bd_sram__"
# This will look for a maglef file and copy it over the mag file
# before DRC after extraction
# gds flatglob sky130_fd_bd_sram__openram_sp_cell_opt1a_cell
# gds flatglob sky130_fd_bd_sram__openram_sp_cell_opt1a_replica_ce
# gds flatglob sky130_fd_bd_sram__openram_sp_cell_opt1_replica_cell
# gds flatglob sky130_fd_bd_sram__openram_sp_cell_opt1_replica_ce
# gds flatglob sky130_fd_bd_sram__openram_sp_cell_opt1_replica_cell
# gds flatglob sky130_fd_bd_sram__openram_sp_cell_opt1a_cell
# gds flatglob sky130_fd_bd_sram__sram_sp_cell_fom_serifs
flatglob = ["*_?mos_m*",
"sky130_fd_bd_sram__sram_sp_cell_fom_serifs",
"sky130_fd_bd_sram__openram_sp_cell_opt1a_cell",
"sky130_fd_bd_sram__openram_sp_cell_opt1a_replica_ce",
"sky130_fd_bd_sram__sram_sp_cell",
"sky130_fd_bd_sram__openram_sp_cell_opt1_replica_cell",
"sky130_fd_bd_sram__openram_sp_cell_opt1a_replica_cell",
"sky130_fd_bd_sram__sram_sp_cell_opt1_ce",
"sky130_fd_bd_sram__openram_sp_cell_opt1_replica_ce",
"sky130_fd_bd_sram__openram_sp_cell_opt1a_cell",
"sky130_fd_bd_sram__sram_sp_cell_fom_serifs"]
"sky130_fd_bd_sram__openram_sp_cell_opt1a_replica_ce",
"sky130_fd_bd_sram__sram_sp_wlstrap_ce",
"sky130_fd_bd_sram__sram_sp_wlstrap_p_ce"]
blackbox_cells = ["sky130_fd_bd_sram__openram_dp_cell",
"sky130_fd_bd_sram__openram_dp_cell_dummy",