Merge branch 'dev' into char
|
|
@ -6,6 +6,9 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v1
|
||||||
|
- name: Library build
|
||||||
|
run: |
|
||||||
|
make library
|
||||||
- name: Docker build
|
- name: Docker build
|
||||||
run: |
|
run: |
|
||||||
cd ${{ github.workspace }}/docker
|
cd ${{ github.workspace }}/docker
|
||||||
|
|
|
||||||
|
|
@ -14,5 +14,10 @@ technology/sky130/*_lib
|
||||||
technology/sky130/tech/.magicrc
|
technology/sky130/tech/.magicrc
|
||||||
.idea
|
.idea
|
||||||
compiler/tests/results/
|
compiler/tests/results/
|
||||||
sky*/
|
|
||||||
open_pdks/
|
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) && \
|
git clone $(SRAM_LIB_GIT_REPO) $(SRAM_LIB_DIR) && \
|
||||||
cd $(SRAM_LIB_DIR) && git pull && git checkout $(SRAM_LIB_GIT_COMMIT))
|
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 ] || \
|
@[ -d $(PDK_ROOT)/sky130A ] || \
|
||||||
(echo "Warning: $(PDK_ROOT)/sky130A not found!! Run make pdk first." && false)
|
(echo "Warning: $(PDK_ROOT)/sky130A not found!! Run make pdk first." && false)
|
||||||
@[ -d $(PDK_ROOT)/skywater-pdk ] || \
|
@[ -d $(PDK_ROOT)/skywater-pdk ] || \
|
||||||
|
|
@ -215,3 +215,16 @@ wipe: uninstall
|
||||||
@rm -rf $(OPEN_PDKS_DIR)
|
@rm -rf $(OPEN_PDKS_DIR)
|
||||||
@rm -rf $(SKY130_PDKS_DIR)
|
@rm -rf $(SKY130_PDKS_DIR)
|
||||||
.PHONY: wipe
|
.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
|
# Documentation
|
||||||
|
|
||||||
Please take a look at our presentation We have created a detailed
|
Please see our [documentation][documentation] and let us know if anything needs
|
||||||
presentation that serves as our [documentation][documentation].
|
updating.
|
||||||
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.
|
|
||||||
|
|
||||||
# Get Involved
|
# 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
|
# Further Help
|
||||||
|
|
||||||
+ [Additional hints](./HINTS.md)
|
|
||||||
+ [Documentation][documentation]
|
+ [Documentation][documentation]
|
||||||
+ [OpenRAM Slack Workspace][Slack]
|
+ [OpenRAM Slack Workspace][Slack]
|
||||||
+ [OpenRAM Users Group][user-group] ([subscribe here][user-group-subscribe])
|
+ [OpenRAM Users Group][user-group] ([subscribe here][user-group-subscribe])
|
||||||
+ [OpenRAM Developers Group][dev-group] ([subscribe here][dev-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
|
# License
|
||||||
|
|
||||||
OpenRAM is licensed under the [BSD 3-clause License](./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
|
# Contributors & Acknowledgment
|
||||||
|
|
||||||
- [Matthew Guthaus] from [VLSIDA] created the OpenRAM project and is the lead architect.
|
- [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 issues]: https://github.com/VLSIDA/OpenRAM/issues
|
||||||
[Github pull request]: https://github.com/VLSIDA/OpenRAM/pulls
|
[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
|
[dev-group]: mailto:openram-dev-group@ucsc.edu
|
||||||
[user-group]: mailto:openram-user-group@ucsc.edu
|
[user-group]: mailto:openram-user-group@ucsc.edu
|
||||||
[dev-group-subscribe]: mailto:openram-dev-group+subscribe@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 bname=$(basename $(notdir $@)))
|
||||||
$(eval config_path=$(CONFIG_DIR)/$(addsuffix .py, $(notdir $(basename $@))))
|
$(eval config_path=$(CONFIG_DIR)/$(addsuffix .py, $(notdir $(basename $@))))
|
||||||
mkdir -p $(SIM_DIR)/$(bname)
|
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 $@
|
touch $@
|
||||||
|
|
||||||
clean_model:
|
clean_model:
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ def bp():
|
||||||
An empty function so you can set soft breakpoints in pdb.
|
An empty function so you can set soft breakpoints in pdb.
|
||||||
Usage:
|
Usage:
|
||||||
1) Add a breakpoint anywhere in your code with "import debug; debug.bp()".
|
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)
|
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.
|
4) Then run "cont" to continue.
|
||||||
5) You can now set additional breakpoints or display commands
|
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["col_cap_bitcell_2port"] = "col_cap_cell_2rw"
|
||||||
self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw"
|
self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw"
|
||||||
self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw"
|
self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw"
|
||||||
|
self.names["internal"] = "internal"
|
||||||
|
|
||||||
self.use_strap = False
|
self.use_strap = False
|
||||||
self._ptx = _ptx(model_is_subckt=False,
|
self._ptx = _ptx(model_is_subckt=False,
|
||||||
bin_spice_models=False)
|
bin_spice_models=False)
|
||||||
|
|
||||||
self._pgate = _pgate(add_implants=False)
|
self._pgate = _pgate(add_implants=False)
|
||||||
|
|
||||||
|
|
||||||
self._inv_dec = cell(["A", "Z", "vdd", "gnd"],
|
self._inv_dec = cell(["A", "Z", "vdd", "gnd"],
|
||||||
["INPUT", "OUTPUT", "POWER", "GROUND"])
|
["INPUT", "OUTPUT", "POWER", "GROUND"])
|
||||||
|
|
||||||
|
|
@ -231,6 +234,12 @@ class cell_properties():
|
||||||
self._row_cap_2port = bitcell(["wl0", "wl1", "gnd"],
|
self._row_cap_2port = bitcell(["wl0", "wl1", "gnd"],
|
||||||
["INPUT", "INPUT", "POWER", "GROUND"])
|
["INPUT", "INPUT", "POWER", "GROUND"])
|
||||||
|
|
||||||
|
self._internal = cell([],[])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def internal(self):
|
||||||
|
return self._internal
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ptx(self):
|
def ptx(self):
|
||||||
return self._ptx
|
return self._ptx
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import subprocess
|
||||||
|
|
||||||
VERSION = "1.2.0"
|
VERSION = "1.2.0"
|
||||||
NAME = "OpenRAM v{}".format(VERSION)
|
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()
|
OPTS = options.options()
|
||||||
CHECKPOINT_OPTS = None
|
CHECKPOINT_OPTS = None
|
||||||
|
|
@ -141,9 +141,6 @@ def print_banner():
|
||||||
debug.print_raw("|=========" + user_info.center(60) + "=========|")
|
debug.print_raw("|=========" + user_info.center(60) + "=========|")
|
||||||
dev_info = "Development help: openram-dev-group@ucsc.edu"
|
dev_info = "Development help: openram-dev-group@ucsc.edu"
|
||||||
debug.print_raw("|=========" + dev_info.center(60) + "=========|")
|
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("|=========" + "See LICENSE for license info".center(60) + "=========|")
|
||||||
debug.print_raw("|==============================================================================|")
|
debug.print_raw("|==============================================================================|")
|
||||||
|
|
||||||
|
|
@ -432,16 +429,23 @@ def setup_paths():
|
||||||
|
|
||||||
global OPTS
|
global OPTS
|
||||||
|
|
||||||
|
# If $OPENRAM_HOME is defined, use that path for the source code.
|
||||||
|
# Otherwise, use the openram package.
|
||||||
try:
|
try:
|
||||||
OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME"))
|
OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME"))
|
||||||
except:
|
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),
|
debug.check(os.path.isdir(OPENRAM_HOME),
|
||||||
"$OPENRAM_HOME does not exist: {0}".format(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:
|
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
|
# Use a unique temp subdirectory if multithreaded
|
||||||
if OPTS.num_threads > 1 or OPTS.openram_temp == "/tmp":
|
if OPTS.num_threads > 1 or OPTS.openram_temp == "/tmp":
|
||||||
|
|
@ -547,11 +551,30 @@ def import_tech():
|
||||||
debug.info(2,
|
debug.info(2,
|
||||||
"Importing technology: " + OPTS.tech_name)
|
"Importing technology: " + OPTS.tech_name)
|
||||||
|
|
||||||
# environment variable should point to the technology dir
|
OPENRAM_TECH = ""
|
||||||
|
|
||||||
|
# Check if $OPENRAM_TECH is defined
|
||||||
try:
|
try:
|
||||||
OPENRAM_TECH = os.path.abspath(os.environ.get("OPENRAM_TECH"))
|
OPENRAM_TECH = os.path.abspath(os.environ.get("OPENRAM_TECH"))
|
||||||
except:
|
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
|
# Add all of the paths
|
||||||
for tech_path in OPENRAM_TECH.split(":"):
|
for tech_path in OPENRAM_TECH.split(":"):
|
||||||
|
|
|
||||||
|
|
@ -80,3 +80,4 @@ from .write_mask_and_array import *
|
||||||
from .sram_1bank import *
|
from .sram_1bank import *
|
||||||
from .sram_config import *
|
from .sram_config import *
|
||||||
from .sram import *
|
from .sram import *
|
||||||
|
from .internal_base import *
|
||||||
|
|
@ -29,7 +29,3 @@ class bitcell_1port(bitcell_base):
|
||||||
"""
|
"""
|
||||||
self.add_graph_edges(graph, port_nets)
|
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
|
# Port 1 edges
|
||||||
graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self)
|
graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self)
|
||||||
graph.add_edge(pin_dict["wl1"], pin_dict["br1"], 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)
|
delay = math.sqrt(2*tstep*(vdd-spice["nom_threshold"])/m)
|
||||||
|
|
||||||
return delay
|
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
|
Class for holding all of the OpenRAM options. All
|
||||||
of these options can be over-riden in a configuration file
|
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
|
continue
|
||||||
if re.search("debug.py$", code):
|
if re.search("debug.py$", code):
|
||||||
continue
|
continue
|
||||||
if re.search("openram.py$", code):
|
if re.search("sram_compiler.py$", code):
|
||||||
continue
|
continue
|
||||||
if re.search("testutils.py$", code):
|
if re.search("testutils.py$", code):
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ class openram_back_end_test(openram_test):
|
||||||
config_file = "{}/tests/configs/config_back_end".format(os.getenv("OPENRAM_HOME"))
|
config_file = "{}/tests/configs/config_back_end".format(os.getenv("OPENRAM_HOME"))
|
||||||
globals.init_openram(config_file)
|
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_file = "testsram"
|
||||||
out_path = "/tmp/testsram_{0}_{1}_{2}/".format(OPTS.tech_name, getpass.getuser(), os.getpid())
|
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
|
# Always perform code coverage
|
||||||
if OPTS.coverage == 0:
|
if OPTS.coverage == 0:
|
||||||
debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage")
|
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:
|
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)
|
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,
|
cmd = "{0} -o {1} -p {2} {3} {4} 2>&1 > {5}/output.log".format(exe_name,
|
||||||
out_file,
|
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"))
|
config_file = "{}/tests/configs/config_front_end".format(os.getenv("OPENRAM_HOME"))
|
||||||
globals.init_openram(config_file)
|
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_file = "testsram"
|
||||||
out_path = "/tmp/testsram_{0}_{1}_{2}".format(OPTS.tech_name, getpass.getuser(), os.getpid())
|
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
|
# Always perform code coverage
|
||||||
if OPTS.coverage == 0:
|
if OPTS.coverage == 0:
|
||||||
debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage")
|
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:
|
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)
|
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,
|
cmd = "{0} -n -o {1} -p {2} {3} {4} 2>&1 > {5}/output.log".format(exe_name,
|
||||||
out_file,
|
out_file,
|
||||||
|
|
|
||||||
|
|
@ -121,8 +121,11 @@ $(TEST_BASES):
|
||||||
@mkdir -p results/$*/tmp
|
@mkdir -p results/$*/tmp
|
||||||
@$(DOCKER_CMD) sh -c ". /home/cad-user/.bashrc && sleep 1 && python3 -u $(OPENRAM_DIR)/$(getfile).py \
|
@$(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"
|
-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!" && \
|
ifdef KEEP
|
||||||
rm -rf $(TOP_DIR)/compiler/tests/results/$* || echo "$* ... FAIL!"
|
@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)
|
.DELETE_ON_ERROR: $(TEST_STAMPS)
|
||||||
|
|
||||||
.PHONY: docker-pull
|
.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
|
%.ok: configs/%.py
|
||||||
@echo "Building $*"
|
@echo "Building $*"
|
||||||
@mkdir -p $*
|
@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)
|
.DELETE_ON_ERROR: $(STAMPS)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
OPENRAM_HOME := $(abspath $(TOP_DIR)/compiler)
|
OPENRAM_HOME := $(abspath $(TOP_DIR)/compiler)
|
||||||
OPENRAM_TECH := $(abspath $(TOP_DIR)/technology)
|
OPENRAM_TECH := $(abspath $(TOP_DIR)/technology)
|
||||||
OPENRAM_COMPILER := $(OPENRAM_HOME)/openram.py
|
OPENRAM_COMPILER := $(abspath $(TOP_DIR)/sram_compiler.py)
|
||||||
|
|
||||||
PDK_ROOT ?= $(TOP_DIR)
|
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
|
a Liberty (.lib) file for timing analysis/optimization
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
|
try:
|
||||||
|
import openram
|
||||||
|
except:
|
||||||
|
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||||
import globals as g
|
import globals as g
|
||||||
|
|
||||||
(OPTS, args) = g.parse_args()
|
(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) ":"]
|
set openram_paths [split $::env(OPENRAM_TECH) ":"]
|
||||||
foreach p $openram_paths {
|
foreach p $openram_paths {
|
||||||
path sys +$p/scn4m_subm/tech
|
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
|
# This will create a default set of bitline/wordline names
|
||||||
self.create_all_bitline_names()
|
self.create_all_bitline_names()
|
||||||
self.create_all_wordline_names()
|
self.create_all_wordline_names()
|
||||||
|
|
||||||
self.create_netlist()
|
self.create_netlist()
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
self.create_layout()
|
self.create_layout()
|
||||||
|
self.add_supply_pins()
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
""" Add the modules used in this design """
|
""" Add the modules used in this design """
|
||||||
|
|
|
||||||
|
|
@ -125,11 +125,23 @@ class sky130_bitcell_base_array(bitcell_base_array):
|
||||||
def add_supply_pins(self):
|
def add_supply_pins(self):
|
||||||
""" Add the layout pins """
|
""" Add the layout pins """
|
||||||
# Copy a vdd/gnd layout pin from every cell
|
# 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 row in range(self.row_size):
|
||||||
for col in range(self.column_size):
|
for col in range(self.column_size):
|
||||||
inst = self.cell_inst[row, col]
|
inst = self.cell_inst[row, col]
|
||||||
for pin_name in ["vdd", "gnd"]:
|
for pin_name in ["vdd", "gnd"]:
|
||||||
self.copy_layout_pin(inst, pin_name)
|
self.copy_layout_pin(inst, pin_name)
|
||||||
|
|
||||||
if row == 2: #add only 1 label per col
|
if row == 2: #add only 1 label per col
|
||||||
|
|
||||||
if 'VPB' or 'vpb' in self.cell_inst[row, col].mod.pins:
|
if 'VPB' or 'vpb' in self.cell_inst[row, col].mod.pins:
|
||||||
|
|
|
||||||
|
|
@ -5,29 +5,36 @@
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
|
||||||
import debug
|
from copy import deepcopy
|
||||||
from base import design
|
from modules import internal_base
|
||||||
from base import get_libcell_size
|
from tech import cell_properties as props
|
||||||
from tech import layer, GDS
|
|
||||||
|
|
||||||
|
class sky130_internal(internal_base):
|
||||||
class sky130_internal(design):
|
|
||||||
|
|
||||||
def __init__(self, version, name=""):
|
def __init__(self, version, name=""):
|
||||||
super().__init__(name)
|
prop = deepcopy(props.internal)
|
||||||
|
prop.boundary_layer = "mem"
|
||||||
if version == "wlstrap":
|
if version == "wlstrap":
|
||||||
self.name = "sky130_fd_bd_sram__sram_sp_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":
|
elif version == "wlstrap_p":
|
||||||
self.name = "sky130_fd_bd_sram__sram_sp_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":
|
elif version == "wlstrapa":
|
||||||
self.name = "sky130_fd_bd_sram__sram_sp_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":
|
elif version == "wlstrapa_p":
|
||||||
self.name = "sky130_fd_bd_sram__sram_sp_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:
|
else:
|
||||||
debug.error("Invalid version", -1)
|
debug.error("Invalid version", -1)
|
||||||
design.__init__(self, name=self.name)
|
|
||||||
(self.width, self.height) = get_libcell_size(self.name,
|
super().__init__(name, cell_name=self.name, prop=prop)
|
||||||
GDS["unit"],
|
|
||||||
layer["mem"])
|
|
||||||
# pin_map = get_libcell_pins(pin_names, self.name, GDS["unit"])
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
self.add_via_stack_center(from_layer=pin.layer,
|
||||||
to_layer='m2',
|
to_layer='m2',
|
||||||
offset=pin_center+supply_inst.ll()+cell_inst.ll() + vector(connection_offset,0))
|
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
|
# 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,
|
self.add_via_stack_center(from_layer=pin.layer,
|
||||||
to_layer='m2',
|
to_layer='m2',
|
||||||
offset=pin_center+supply_inst.ll()+cell_inst.ll() + vector(connection_offset,0))
|
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')]
|
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]):
|
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("vdd", "POWER")
|
||||||
self.add_pin("gnd", "GROUND")
|
self.add_pin("gnd", "GROUND")
|
||||||
|
|
||||||
#self.add_pin("top_gate", "INPUT")
|
self.add_pin("top_gate", "INPUT")
|
||||||
#self.add_pin("bot_gate", "INPUT")
|
self.add_pin("bot_gate", "INPUT")
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
self.replica_cell = factory.create(module_type="replica_bitcell_1port", version="opt1")
|
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
|
# This will look for a maglef file and copy it over the mag file
|
||||||
# before DRC after extraction
|
# 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*",
|
flatglob = ["*_?mos_m*",
|
||||||
"sky130_fd_bd_sram__sram_sp_cell_fom_serifs",
|
"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_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_opt1_replica_ce",
|
||||||
"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_fom_serifs"]
|
"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",
|
blackbox_cells = ["sky130_fd_bd_sram__openram_dp_cell",
|
||||||
"sky130_fd_bd_sram__openram_dp_cell_dummy",
|
"sky130_fd_bd_sram__openram_dp_cell_dummy",
|
||||||
|
|
|
||||||