Merge branch 'dev' into char
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
15
Makefile
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(":"):
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
"""
|
||||
|
||||
###################
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 338 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 154 KiB |
|
After Width: | Height: | Size: 298 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 261 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 224 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 258 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||

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

|
||||

|
||||

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

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

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

|
||||
* Node names reduced to top-most SPICE level with internal signals maintained.
|
||||
* Internal modules determine edges between nodes
|
||||
|
||||

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

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

|
||||
|
||||
|
||||
|
||||
## Write Timing
|
||||

|
||||
|
||||
|
||||
|
||||
### Write Timing Simulation
|
||||

|
||||
|
||||
|
||||
|
||||
## 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 Diagram (Write)
|
||||

|
||||
|
||||
|
||||
|
||||
## 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`
|
||||
|
|
@ -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`)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
# OpenRAM Documentation
|
||||

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

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

|
||||
|
||||
|
||||
|
||||
## Generated Layout by OpenRAM for a multiport (6R/2W) SRAM in 32 nm SOI CMOS Technology
|
||||

|
||||
|
||||
|
||||
|
||||
## Timing and Density Results for Generated SRAMs
|
||||

|
||||
|
||||
|
||||
|
||||
## 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.
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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
|
||||
|
|
@ -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 -->
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 """
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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]):
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||