mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into multiport_characterization
This commit is contained in:
commit
e8f1c19af6
|
|
@ -7,6 +7,26 @@ list at openram-dev-group@ucsc.edu. We are happy to give insights into
|
|||
the best way to implement a change to ensure your contribution will be
|
||||
accepted and help other OpenRAM users.
|
||||
|
||||
# Directory Structure
|
||||
|
||||
* compiler - openram compiler itself (pointed to by OPENRAM_HOME)
|
||||
* compiler/base - base data structure modules
|
||||
* compiler/pgates - parameterized cells (e.g. logic gates)
|
||||
* compiler/bitcells - various bitcell styles
|
||||
* compiler/modules - high-level modules (e.g. decoders, etc.)
|
||||
* compiler/verify - DRC and LVS verification wrappers
|
||||
* compiler/characterizer - timing characterization code
|
||||
* compiler/gdsMill - GDSII reader/writer
|
||||
* compiler/router - router for signals and power supplies
|
||||
* compiler/tests - unit tests
|
||||
* technology - openram technology directory (pointed to by OPENRAM_TECH)
|
||||
* technology/freepdk45 - example configuration library for [FreePDK45 technology node
|
||||
* technology/scn4m_subm - example configuration library [SCMOS] technology node
|
||||
* technology/scn3me_subm - unsupported configuration (not enough metal layers)
|
||||
* technology/setup_scripts - setup scripts to customize your PDKs and OpenRAM technologies
|
||||
* docs - LaTeX manual (outdated)
|
||||
* lib - IP library of pregenerated memories
|
||||
|
||||
# Code Style
|
||||
|
||||
Our code may not be the best and we acknowledge that. We welcome
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
# 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. 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.
|
||||
|
||||
2. Glade
|
||||
|
||||
You can view errors in Glade as well. I like this because it is on my laptop.
|
||||
You can get it from: http://www.peardrop.co.uk/glade/
|
||||
|
||||
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.
|
||||
|
||||
3. Magic
|
||||
|
||||
Magic is only supported in SCMOS. You will need to install the MOSIS SCMOS rules
|
||||
and Magic from: 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).
|
||||
|
||||
4. 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.
|
||||
338
README.md
338
README.md
|
|
@ -1,238 +1,222 @@
|
|||
# BASIC SETUP
|
||||
# OpenRAM
|
||||
Stable: [](https://github.com/VLSIDA/PrivateRAM/commits/master)
|
||||
Unstable: [](https://github.com/VLSIDA/PrivateRAM/commits/dev)
|
||||
[](https://github.com/VLSIDA/PrivateRAM/archive/master.zip)
|
||||
[](./LICENSE)
|
||||
|
||||
Please look at the OpenRAM ICCAD paper and presentation in the repository:
|
||||
https://github.com/mguthaus/OpenRAM/blob/master/OpenRAM_ICCAD_2016_paper.pdf
|
||||
https://github.com/mguthaus/OpenRAM/blob/master/OpenRAM_ICCAD_2016_presentation.pdf
|
||||
An open-source static random access memory (SRAM) compiler.
|
||||
|
||||
# What is OpenRAM?
|
||||
|
||||
<img align="right" width="25%" src="images/SCMOS_16kb_sram.jpg">
|
||||
|
||||
OpenRAM is an open-source Python framework to create the layout,
|
||||
netlists, timing and power models, placement and routing models, and
|
||||
other views necessary to use SRAMs in ASIC design. OpenRAM supports
|
||||
integration in both commercial and open-source flows with both
|
||||
predictive and fabricable technologies.
|
||||
|
||||
# Basic Setup
|
||||
|
||||
The OpenRAM compiler has very few dependencies:
|
||||
* ngspice-26 (or later) or HSpice I-2013.12-1 (or later) or CustomSim 2017 (or later)
|
||||
* Python 3.5 and higher
|
||||
* Python numpy (pip3 install numpy to install)
|
||||
* flask_table (pip3 install flask to install)
|
||||
* a setup script for each technology you want to use
|
||||
* a technology directory for each technology with the base cells
|
||||
+ [Ngspice] 26 (or later) or HSpice I-2013.12-1 (or later) or CustomSim 2017 (or later)
|
||||
+ Python 3.5 or higher
|
||||
+ Python numpy (pip3 install numpy to install)
|
||||
+ flask_table (pip3 install flask to install)
|
||||
|
||||
If you want to perform DRC and LVS, you will need either:
|
||||
* Calibre (for FreePDK45 or SCMOS)
|
||||
* Magic + Netgen (for SCMOS only)
|
||||
+ Calibre (for [FreePDK45])
|
||||
+ [Magic] + [Netgen] (for [SCMOS])
|
||||
|
||||
You must set two environment variables:
|
||||
+ OPENRAM\_HOME should point to the compiler source directory.
|
||||
+ OPENERAM\_TECH should point to a root technology directory.
|
||||
|
||||
For example add this to your .bashrc:
|
||||
|
||||
You must set two environment variables: OPENRAM_HOME should point to
|
||||
the compiler source directory. OPENERAM_TECH should point to a root
|
||||
technology directory that contains subdirs of all other technologies.
|
||||
For example, in bash, add to your .bashrc:
|
||||
```
|
||||
export OPENRAM_HOME="$HOME/openram/compiler"
|
||||
export OPENRAM_TECH="$HOME/openram/technology"
|
||||
```
|
||||
For example, in csh/tcsh, add to your .cshrc/.tcshrc:
|
||||
|
||||
You may also wish to add OPENRAM\_HOME to your PYTHONPATH:
|
||||
|
||||
```
|
||||
setenv OPENRAM_HOME "$HOME/openram/compiler"
|
||||
setenv OPENRAM_TECH "$HOME/openram/technology"
|
||||
export PYTHONPATH="$PYTHONPATH:$OPENRAM_HOME"
|
||||
```
|
||||
|
||||
We include the tech files necessary for FreePDK and SCMOS. The SCMOS
|
||||
spice models, however, are generic and should be replaced with foundry
|
||||
models.
|
||||
If you are using FreePDK, you should also have that set up and have the
|
||||
environment variable point to the PDK.
|
||||
For example, in bash, add to your .bashrc:
|
||||
We include the tech files necessary for [FreePDK45] and [SCMOS]
|
||||
SCN4M_SUBM. The [SCMOS] spice models, however, are generic and should
|
||||
be replaced with foundry models. If you are using [FreePDK45], you
|
||||
should also have that set up and have the environment variable point
|
||||
to the PDK. For example add this to your .bashrc:
|
||||
|
||||
```
|
||||
export FREEPDK45="/bsoe/software/design-kits/FreePDK45"
|
||||
```
|
||||
For example, in csh/tcsh, add to your .tcshrc:
|
||||
|
||||
You may get the entire [FreePDK45 PDK here][FreePDK45].
|
||||
If you are using [SCMOS], you should install [Magic] and [Netgen].
|
||||
We have included the most recent SCN4M_SUBM design rules from [Qflow].
|
||||
|
||||
# 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:
|
||||
|
||||
```
|
||||
setenv FREEPDK45 "/bsoe/software/design-kits/FreePDK45"
|
||||
# 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_{0}_{1}_{2}".format(word_size,num_words,tech_name)
|
||||
|
||||
# Disable analytical models for full characterization (WARNING: slow!)
|
||||
# analytical_delay = False
|
||||
```
|
||||
We do not distribute the PDK, but you may get it from:
|
||||
https://www.eda.ncsu.edu/wiki/FreePDK45:Contents
|
||||
|
||||
If you are using SCMOS, you should install Magic and netgen from:
|
||||
http://opencircuitdesign.com/magic/
|
||||
http://opencircuitdesign.com/netgen/
|
||||
We have included the SCN4M design rules from QFlow:
|
||||
http://opencircuitdesign.com/qflow/
|
||||
|
||||
# DIRECTORY STRUCTURE
|
||||
|
||||
* compiler - openram compiler itself (pointed to by OPENRAM_HOME)
|
||||
* compiler/base - base data structure modules
|
||||
* compiler/pgates - parameterized cells (e.g. logic gates)
|
||||
* compiler/bitcells - various bitcell styles
|
||||
* compiler/modules - high-level modules (e.g. decoders, etc.)
|
||||
* compiler/verify - DRC and LVS verification wrappers
|
||||
* compiler/characterizer - timing characterization code
|
||||
* compiler/gdsMill - GDSII reader/writer
|
||||
* compiler/router - router for signals and power supplies
|
||||
* compiler/tests - unit tests
|
||||
* technology - openram technology directory (pointed to by OPENRAM_TECH)
|
||||
* technology/freepdk45 - example configuration library for freepdk45 technology node
|
||||
* technology/scn4m_subm - example configuration library SCMOS technology node
|
||||
* technology/scn3me_subm - unsupported configuration (not enough metal layers)
|
||||
* technology/setup_scripts - setup scripts to customize your PDKs and OpenRAM technologies
|
||||
* docs - LaTeX manual (outdated)
|
||||
* lib - IP library of pregenerated memories
|
||||
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
|
||||
|
||||
|
||||
# UNIT TESTS
|
||||
# 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:
|
||||
|
||||
Use the command:
|
||||
```
|
||||
python regress.py
|
||||
python3 regress.py
|
||||
```
|
||||
To run a specific test:
|
||||
```
|
||||
python {unit test}.py
|
||||
python3 {unit test}.py
|
||||
```
|
||||
The unit tests take the same arguments as openram.py itself.
|
||||
|
||||
To increase the verbosity of the test, add one (or more) -v options:
|
||||
```
|
||||
python tests/00_code_format_check_test.py -v -t freepdk45
|
||||
python3 tests/00_code_format_check_test.py -v -t freepdk45
|
||||
```
|
||||
To specify a particular technology use "-t <techname>" such as
|
||||
"-t freepdk45" or "-t scn4m_subm". The default for a unit test is scn4m_subm.
|
||||
"-t freepdk45" or "-t scn4m\_subm". The default for a unit test is scn4m_subm.
|
||||
The default for openram.py is specified in the configuration file.
|
||||
|
||||
|
||||
# CREATING CUSTOM TECHNOLOGIES
|
||||
# Porting to a New Technology
|
||||
|
||||
All setup scripts should be in the setup_scripts directory under the
|
||||
$OPENRAM_TECH directory. Please look at the following file for an
|
||||
If you want to support a enw technology, you will need to create:
|
||||
+ a setup script for each technology you want to use
|
||||
+ a technology directory for each technology with the base cells
|
||||
|
||||
All setup scripts should be in the setup\_scripts directory under the
|
||||
$OPENRAM\_TECH directory. We provide two technology examples for
|
||||
[SCMOS] and [FreePDK45]. Please look at the following file for an
|
||||
example of what is needed for OpenRAM:
|
||||
|
||||
```
|
||||
$OPENRAM_TECH/setup_scripts/setup_openram_freepdk45.py
|
||||
```
|
||||
Each setup script should be named as: setup_openram_{tech name}.py.
|
||||
|
||||
Each specific technology (e.g., freepdk45) should be a subdirectory
|
||||
Each setup script should be named as: setup\_openram\_{tech name}.py.
|
||||
|
||||
Each specific technology (e.g., [FreePDK45]) should be a subdirectory
|
||||
(e.g., $OPENRAM_TECH/freepdk45) and include certain folders and files:
|
||||
1. gds_lib folder with all the .gds (premade) library cells. At a
|
||||
minimum this includes:
|
||||
* ms_flop.gds
|
||||
* sense_amp.gds
|
||||
* write_driver.gds
|
||||
* cell_6t.gds
|
||||
* replica_cell_6t.gds
|
||||
* tri_gate.gds
|
||||
2. sp_lib folder with all the .sp (premade) library netlists for the above cells.
|
||||
3. layers.map
|
||||
4. A valid tech Python module (tech directory with __init__.py and tech.py) with:
|
||||
* References in tech.py to spice models
|
||||
* DRC/LVS rules needed for dynamic cells and routing
|
||||
* Layer information
|
||||
* etc.
|
||||
* gds_lib folder with all the .gds (premade) library cells:
|
||||
* dff.gds
|
||||
* sense_amp.gds
|
||||
* write_driver.gds
|
||||
* cell_6t.gds
|
||||
* replica\_cell\_6t.gds
|
||||
* sp_lib folder with all the .sp (premade) library netlists for the above cells.
|
||||
* layers.map
|
||||
* A valid tech Python module (tech directory with __init__.py and tech.py) with:
|
||||
* References in tech.py to spice models
|
||||
* DRC/LVS rules needed for dynamic cells and routing
|
||||
* Layer information
|
||||
* Spice and supply information
|
||||
* etc.
|
||||
|
||||
# DEBUGGING
|
||||
# Get Involved
|
||||
|
||||
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 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
|
||||
+ Report bugs by submitting [Github issues].
|
||||
+ Develop new features (see [how to contribute](./CONTRIBUTING.md))
|
||||
+ Submit code/fixes using a [Github pull request]
|
||||
+ Follow our [project][Github projects].
|
||||
+ Read and cite our [ICCAD paper][OpenRAMpaper]
|
||||
|
||||
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)
|
||||
# Further Help
|
||||
|
||||
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.
|
||||
+ [Additional hints](./HINTS.md)
|
||||
+ [OpenRAM Slack Workspace][Slack]
|
||||
+ [OpenRAM Users Group][user-group] ([subscribe here][user-group-subscribe])
|
||||
+ [OpenRAM Developers Group][dev-group] ([subscribe here][dev-group-subscribe])
|
||||
|
||||
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.
|
||||
# License
|
||||
|
||||
To debug, you will need a layout viewer. I prefer to use Glade
|
||||
on my Mac, but you can also use Calibre, Magic, etc.
|
||||
OpenRAM is licensed under the [BSD 3-clause License](./LICENSE).
|
||||
|
||||
1. Calibre
|
||||
# Contributors & Acknowledgment
|
||||
|
||||
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.
|
||||
- [Matthew Guthaus] from [VLSIDA] created the OpenRAM project and is the lead architect.
|
||||
- [James Stine] from [VLSIARCH] co-founded the project.
|
||||
- Hunter Nichols maintains and updates the timing characterization.
|
||||
- Michael Grimes created and maintains the multiport netlist code.
|
||||
- Jennifer Sowash is creating the OpenRAM IP library.
|
||||
- Jesse Cirimelli-Low created the datasheet generation.
|
||||
- Samira Ataei created early multi-bank layouts and control logic.
|
||||
- Bin Wu created early parameterized cells.
|
||||
- Yusu Wang is porting parameterized cells to new technologies.
|
||||
- Brian Chen created early prototypes of the timing characterizer.
|
||||
- Jeff Butera created early prototypes of the bank layout.
|
||||
|
||||
In the viewer ">" opens the layout down a level.
|
||||
If I forgot to add you, please let me know!
|
||||
|
||||
2. Glade
|
||||
* * *
|
||||
|
||||
You can view errors in Glade as well. I like this because it is on my laptop.
|
||||
You can get it from: http://www.peardrop.co.uk/glade/
|
||||
[Matthew Guthaus]: https://users.soe.ucsc.edu/~mrg
|
||||
[James Stine]: https://ece.okstate.edu/content/stine-james-e-jr-phd
|
||||
[VLSIDA]: https://vlsida.soe.ucsc.edu
|
||||
[VLSIARCH]: https://vlsiarch.ecen.okstate.edu/
|
||||
[OpenRAMpaper]: https://ieeexplore.ieee.org/document/7827670/
|
||||
|
||||
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).
|
||||
[Github issues]: https://github.com/VLSIDA/PrivateRAM/issues
|
||||
[Github pull request]: https://github.com/VLSIDA/PrivateRAM/pulls
|
||||
[Github projects]: https://github.com/VLSIDA/PrivateRAM/projects
|
||||
|
||||
To load the errors, you simply do Verify->Import Calibre Errors select
|
||||
the .results file from Calibre.
|
||||
[email me]: mailto:mrg+openram@ucsc.edu
|
||||
[dev-group]: mailto:openram-dev-group@ucsc.edu
|
||||
[user-group]: mailto:openram-user-group@ucsc.edu
|
||||
[dev-group-subscribe]: mailto:openram-dev-group+subscribe@ucsc.edu
|
||||
[user-group-subscribe]: mailto:openram-user-group+subscribe@ucsc.edu
|
||||
|
||||
3. Magic
|
||||
[Magic]: http://opencircuitdesign.com/magic/
|
||||
[Netgen]: http://opencircuitdesign.com/netgen/
|
||||
[Qflow]: http://opencircuitdesign.com/qflow/history.html
|
||||
[Ngspice]: http://ngspice.sourceforge.net/
|
||||
|
||||
Magic is only supported in SCMOS. You will need to install the MOSIS SCMOS rules
|
||||
and Magic from: 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).
|
||||
|
||||
4. 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.
|
||||
[OSUPDK]: https://vlsiarch.ecen.okstate.edu/flow/
|
||||
[FreePDK45]: https://www.eda.ncsu.edu/wiki/FreePDK45:Contents
|
||||
[SCMOS]: https://www.mosis.com/files/scmos/scmos.pdf
|
||||
|
||||
[Slack]: https://join.slack.com/t/openram/shared_invite/enQtNDgxMjc3NzU5NTI1LTE4ODMyM2I0Mzk2ZmFiMjgwYTYyMTQ4NTgwMmUwMDhiM2E1MDViNDRjYzU1NjJhZTQxNWZjMzE3M2FlODBmZjA
|
||||
|
|
|
|||
|
|
@ -172,5 +172,5 @@ active = contact(layer_stack=("active", "contact", "poly"))
|
|||
poly = contact(layer_stack=("poly", "contact", "metal1"))
|
||||
m1m2 = contact(layer_stack=("metal1", "via1", "metal2"))
|
||||
m2m3 = contact(layer_stack=("metal2", "via2", "metal3"))
|
||||
#m3m4 = contact(layer_stack=("metal3", "via3", "metal4"))
|
||||
m3m4 = contact(layer_stack=("metal3", "via3", "metal4"))
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ class design(hierarchy_design):
|
|||
|
||||
self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space, self.m2_space)
|
||||
self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space, self.m3_space)
|
||||
# SCMOS doesn't have m4...
|
||||
#self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space)
|
||||
self.m3_pitch = self.m2_pitch
|
||||
self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space)
|
||||
|
||||
def setup_drc_constants(self):
|
||||
""" These are some DRC constants used in many places in the compiler."""
|
||||
|
|
@ -38,6 +36,8 @@ class design(hierarchy_design):
|
|||
self.m2_space = drc("metal2_to_metal2")
|
||||
self.m3_width = drc("minwidth_metal3")
|
||||
self.m3_space = drc("metal3_to_metal3")
|
||||
self.m4_width = drc("minwidth_metal4")
|
||||
self.m4_space = drc("metal4_to_metal4")
|
||||
self.active_width = drc("minwidth_active")
|
||||
self.active_space = drc("active_to_body_active")
|
||||
self.contact_width = drc("minwidth_contact")
|
||||
|
|
|
|||
|
|
@ -200,18 +200,19 @@ class instance(geometry):
|
|||
self.mod.gds_write_file(self.gds)
|
||||
# now write an instance of my module/structure
|
||||
new_layout.addInstance(self.gds,
|
||||
self.mod.name,
|
||||
offsetInMicrons=self.offset,
|
||||
mirror=self.mirror,
|
||||
rotate=self.rotate)
|
||||
|
||||
def place(self, offset, mirror="R0", rotate=0):
|
||||
""" This updates the placement of an instance. """
|
||||
debug.info(3, "placing instance {}".format(self.name))
|
||||
# Update the placement of an already added instance
|
||||
self.offset = vector(offset).snap_to_grid()
|
||||
self.mirror = mirror
|
||||
self.rotate = rotate
|
||||
self.update_boundary()
|
||||
debug.info(3, "placing instance {}".format(self))
|
||||
|
||||
|
||||
def get_pin(self,name,index=-1):
|
||||
|
|
|
|||
|
|
@ -34,20 +34,24 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
|
|||
# because each reference must be a unique name.
|
||||
# These modules ensure unique names or have no changes if they
|
||||
# aren't unique
|
||||
ok_list = ['ms_flop',
|
||||
'dff',
|
||||
'dff_buf',
|
||||
'bitcell',
|
||||
'contact',
|
||||
ok_list = ['contact',
|
||||
'ptx',
|
||||
'pbitcell',
|
||||
'replica_pbitcell',
|
||||
'sram',
|
||||
'hierarchical_predecode2x4',
|
||||
'hierarchical_predecode3x8']
|
||||
if name not in hierarchy_design.name_map:
|
||||
|
||||
# Library cells don't change
|
||||
if self.is_library_cell:
|
||||
return
|
||||
# Name is unique so far
|
||||
elif name not in hierarchy_design.name_map:
|
||||
hierarchy_design.name_map.append(name)
|
||||
else:
|
||||
# Name is in our list of exceptions (they don't change)
|
||||
for ok_names in ok_list:
|
||||
if ok_names in self.__class__.__name__:
|
||||
if ok_names == self.__class__.__name__:
|
||||
break
|
||||
else:
|
||||
debug.error("Duplicate layout reference name {0} of class {1}. GDS2 requires names be unique.".format(name,self.__class__),-1)
|
||||
|
|
|
|||
|
|
@ -447,6 +447,11 @@ class layout(lef.lef):
|
|||
def gds_read(self):
|
||||
"""Reads a GDSII file in the library and checks if it exists
|
||||
Otherwise, start a new layout for dynamic generation."""
|
||||
|
||||
# This must be done for netlist only mode too
|
||||
if os.path.isfile(self.gds_file):
|
||||
self.is_library_cell=True
|
||||
|
||||
if OPTS.netlist_only:
|
||||
self.gds = None
|
||||
return
|
||||
|
|
@ -454,7 +459,6 @@ class layout(lef.lef):
|
|||
# open the gds file if it exists or else create a blank layout
|
||||
if os.path.isfile(self.gds_file):
|
||||
debug.info(3, "opening {}".format(self.gds_file))
|
||||
self.is_library_cell=True
|
||||
self.gds = gdsMill.VlsiLayout(units=GDS["unit"])
|
||||
reader = gdsMill.Gds2reader(self.gds)
|
||||
reader.loadFromFile(self.gds_file)
|
||||
|
|
|
|||
|
|
@ -148,13 +148,13 @@ class VlsiLayout:
|
|||
structureNames=[]
|
||||
for name in self.structures:
|
||||
structureNames.append(name)
|
||||
|
||||
for name in self.structures:
|
||||
if(len(self.structures[name].srefs)>0): #does this structure reference any others?
|
||||
for sref in self.structures[name].srefs: #go through each reference
|
||||
if sref.sName in structureNames: #and compare to our list
|
||||
structureNames.remove(sref.sName)
|
||||
|
||||
debug.check(len(structureNames)==1,"Multiple possible root structures in the layout: {}".format(str(structureNames)))
|
||||
self.rootStructureName = structureNames[0]
|
||||
|
||||
def traverseTheHierarchy(self, startingStructureName=None, delegateFunction = None,
|
||||
|
|
@ -304,6 +304,7 @@ class VlsiLayout:
|
|||
debug.info(1,"DEBUG: Structure %s Found"%StructureName)
|
||||
StructureFound = True
|
||||
|
||||
debug.check(StructureFound,"Could not find layout to instantiate {}".format(StructureName))
|
||||
|
||||
|
||||
# If layoutToAdd is a unique object (not this), then copy hierarchy,
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ class bank(design.design):
|
|||
#self.add_lvs_correspondence_points()
|
||||
|
||||
# Remember the bank center for further placement
|
||||
self.bank_center=self.offset_all_coordinates().scale(-1,-1)
|
||||
self.bank_array_ll = self.offset_all_coordinates().scale(-1,-1)
|
||||
self.bank_array_ur = self.bitcell_array_inst.ur()
|
||||
|
||||
self.DRC_LVS()
|
||||
|
||||
|
|
@ -232,8 +233,8 @@ class bank(design.design):
|
|||
self.row_decoder_offsets[port] = vector(-x_offset,0)
|
||||
|
||||
# LOWER LEFT QUADRANT
|
||||
# Place the col decoder right aligned with row decoder (x_offset doesn't change)
|
||||
# Below the bitcell array
|
||||
# Place the col decoder left aligned with row decoder (x_offset doesn't change)
|
||||
# Below the bitcell array with well spacing
|
||||
if self.col_addr_size > 0:
|
||||
y_offset = self.column_decoder.height
|
||||
else:
|
||||
|
|
@ -290,8 +291,11 @@ class bank(design.design):
|
|||
|
||||
# UPPER RIGHT QUADRANT
|
||||
# Place the col decoder right aligned with row decoder (x_offset doesn't change)
|
||||
# Below the bitcell array
|
||||
y_offset = self.bitcell_array.height + self.m2_gap
|
||||
# Above the bitcell array with a well spacing
|
||||
if self.col_addr_size > 0:
|
||||
y_offset = self.bitcell_array.height + self.column_decoder.height
|
||||
else:
|
||||
y_offset = self.bitcell_array.height
|
||||
y_offset += 2*drc("well_to_well")
|
||||
self.column_decoder_offsets[port] = vector(x_offset,y_offset)
|
||||
|
||||
|
|
@ -723,7 +727,7 @@ class bank(design.design):
|
|||
|
||||
for port in self.all_ports:
|
||||
if port%2 == 1:
|
||||
mirror = "MY"
|
||||
mirror = "XY"
|
||||
else:
|
||||
mirror = "R0"
|
||||
self.column_decoder_inst[port].place(offset=offsets[port], mirror=mirror)
|
||||
|
|
@ -1189,8 +1193,8 @@ class bank(design.design):
|
|||
|
||||
# clk to wordline_driver
|
||||
control_signal = self.prefix+"clk_buf{}".format(port)
|
||||
pin_pos = self.wordline_driver_inst[port].get_pin("en").uc()
|
||||
mid_pos = pin_pos + vector(0,self.m1_pitch)
|
||||
pin_pos = self.wordline_driver_inst[port].get_pin("en").bc()
|
||||
mid_pos = pin_pos - vector(0,self.m1_pitch)
|
||||
control_x_offset = self.bus_xoffset[port][control_signal].x
|
||||
control_pos = vector(control_x_offset, mid_pos.y)
|
||||
self.add_wire(("metal1","via1","metal2"),[pin_pos, mid_pos, control_pos])
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from tech import drc, spice
|
|||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
|
||||
unique_id = 1
|
||||
|
||||
class bitcell_array(design.design):
|
||||
"""
|
||||
|
|
@ -12,8 +12,13 @@ class bitcell_array(design.design):
|
|||
and word line is connected by abutment.
|
||||
Connects the word lines and bit lines.
|
||||
"""
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, cols, rows, name=""):
|
||||
|
||||
def __init__(self, cols, rows, name="bitcell_array"):
|
||||
if name == "":
|
||||
name = "bitcell_array_{0}x{1}_{2}".format(rows,cols,bitcell_array.unique_id)
|
||||
bitcell_array.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@ class dff_buf(design.design):
|
|||
with two inverters, of variable size, to provide q
|
||||
and qbar. This is to enable driving large fanout loads.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, inv1_size=2, inv2_size=4, name=""):
|
||||
|
||||
if name=="":
|
||||
name = "dff_buf_{0}_{1}".format(inv1_size, inv2_size)
|
||||
name = "dff_buf_{0}".format(dff_buf.unique_id)
|
||||
dff_buf.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(self.name))
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,15 @@ class dff_buf_array(design.design):
|
|||
This is a simple row (or multiple rows) of flops.
|
||||
Unlike the data flops, these are never spaced out.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, rows, columns, inv1_size=2, inv2_size=4, name=""):
|
||||
self.rows = rows
|
||||
self.columns = columns
|
||||
|
||||
if name=="":
|
||||
name = "dff_buf_array_{0}x{1}".format(rows, columns)
|
||||
name = "dff_buf_array_{0}x{1}_{2}".format(rows, columns, dff_buf_array.unique_id)
|
||||
dff_buf_array.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(self.name))
|
||||
self.inv1_size = inv1_size
|
||||
|
|
|
|||
|
|
@ -11,11 +11,13 @@ class dff_inv(design.design):
|
|||
This is a simple DFF with an inverted output. Some DFFs
|
||||
do not have Qbar, so this will create it.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, inv_size=2, name=""):
|
||||
|
||||
if name=="":
|
||||
name = "dff_inv_{0}".format(inv_size)
|
||||
name = "dff_inv_{0}".format(dff_inv.unique_id)
|
||||
dff_inv.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(self.name))
|
||||
self.inv_size = inv_size
|
||||
|
|
|
|||
|
|
@ -11,13 +11,15 @@ class dff_inv_array(design.design):
|
|||
This is a simple row (or multiple rows) of flops.
|
||||
Unlike the data flops, these are never spaced out.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, rows, columns, inv_size=2, name=""):
|
||||
self.rows = rows
|
||||
self.columns = columns
|
||||
|
||||
if name=="":
|
||||
name = "dff_inv_array_{0}x{1}".format(rows, columns)
|
||||
name = "dff_inv_array_{0}x{1}_{2}".format(rows, columns, dff_inv_array.unique_id)
|
||||
dff_inv_array.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(self.name))
|
||||
self.inv_size = inv_size
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class replica_bitline(design.design):
|
|||
self.add_mod(self.bitcell)
|
||||
|
||||
# This is the replica bitline load column that is the height of our array
|
||||
self.rbl = bitcell_array(name="bitline_load", cols=1, rows=self.bitcell_loads)
|
||||
self.rbl = bitcell_array(cols=1, rows=self.bitcell_loads)
|
||||
self.add_mod(self.rbl)
|
||||
|
||||
# FIXME: The FO and depth of this should be tuned
|
||||
|
|
|
|||
|
|
@ -495,6 +495,16 @@ class pin_group:
|
|||
self.grids = pg1.grids | pg2.grids # OR the set of grid locations
|
||||
self.secondary_grids = pg1.secondary_grids | pg2.secondary_grids
|
||||
|
||||
def add_group(self, pg):
|
||||
"""
|
||||
Combine the pin group into this one. This will add to the first item in the pins
|
||||
so this should be used before there are disconnected pins.
|
||||
"""
|
||||
debug.check(len(self.pins)==1,"Don't know which group to add pins to.")
|
||||
self.pins[0].update(*pg.pins) # Join the two lists of pins
|
||||
self.grids |= pg.grids # OR the set of grid locations
|
||||
self.secondary_grids |= pg.secondary_grids
|
||||
|
||||
def add_enclosure(self, cell):
|
||||
"""
|
||||
Add the enclosure shape to the given cell.
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ from pin_layout import pin_layout
|
|||
from pin_group import pin_group
|
||||
from vector import vector
|
||||
from vector3d import vector3d
|
||||
from globals import OPTS
|
||||
from globals import OPTS,print_time
|
||||
from pprint import pformat
|
||||
import grid_utils
|
||||
from datetime import datetime
|
||||
|
||||
class router(router_tech):
|
||||
"""
|
||||
|
|
@ -31,16 +32,18 @@ class router(router_tech):
|
|||
|
||||
# If didn't specify a gds blockage file, write it out to read the gds
|
||||
# This isn't efficient, but easy for now
|
||||
#start_time = datetime.now()
|
||||
if not gds_filename:
|
||||
gds_filename = OPTS.openram_temp+"temp.gds"
|
||||
self.cell.gds_write(gds_filename)
|
||||
|
||||
|
||||
# Load the gds file and read in all the shapes
|
||||
self.layout = gdsMill.VlsiLayout(units=GDS["unit"])
|
||||
self.reader = gdsMill.Gds2reader(self.layout)
|
||||
self.reader.loadFromFile(gds_filename)
|
||||
self.top_name = self.layout.rootStructureName
|
||||
|
||||
#print_time("GDS read",datetime.now(), start_time)
|
||||
|
||||
### The pin data structures
|
||||
# A map of pin names to a set of pin_layout structures
|
||||
self.pins = {}
|
||||
|
|
@ -127,8 +130,12 @@ class router(router_tech):
|
|||
Pin can either be a label or a location,layer pair: [[x,y],layer].
|
||||
"""
|
||||
debug.info(1,"Finding pins for {}.".format(pin_name))
|
||||
#start_time = datetime.now()
|
||||
self.retrieve_pins(pin_name)
|
||||
#print_time("Retrieved pins",datetime.now(), start_time)
|
||||
#start_time = datetime.now()
|
||||
self.analyze_pins(pin_name)
|
||||
#print_time("Analyzed pins",datetime.now(), start_time)
|
||||
|
||||
def find_blockages(self):
|
||||
"""
|
||||
|
|
@ -152,97 +159,98 @@ class router(router_tech):
|
|||
self.find_pins(pin)
|
||||
|
||||
# This will get all shapes as blockages and convert to grid units
|
||||
# This ignores shapes that were pins
|
||||
# This ignores shapes that were pins
|
||||
#start_time = datetime.now()
|
||||
self.find_blockages()
|
||||
#print_time("Find blockags",datetime.now(), start_time)
|
||||
|
||||
# Convert the blockages to grid units
|
||||
#start_time = datetime.now()
|
||||
self.convert_blockages()
|
||||
#print_time("Find blockags",datetime.now(), start_time)
|
||||
|
||||
# This will convert the pins to grid units
|
||||
# It must be done after blockages to ensure no DRCs between expanded pins and blocked grids
|
||||
#start_time = datetime.now()
|
||||
for pin in pin_list:
|
||||
self.convert_pins(pin)
|
||||
|
||||
#print_time("Convert pins",datetime.now(), start_time)
|
||||
|
||||
#start_time = datetime.now()
|
||||
for pin in pin_list:
|
||||
self.combine_adjacent_pins(pin)
|
||||
#print_time("Combine pins",datetime.now(), start_time)
|
||||
#self.write_debug_gds("debug_combine_pins.gds",stop_program=True)
|
||||
|
||||
# Separate any adjacent grids of differing net names to prevent wide metal DRC violations
|
||||
# Must be done before enclosing pins
|
||||
#start_time = datetime.now()
|
||||
self.separate_adjacent_pins(self.supply_rail_space_width)
|
||||
#print_time("Separate pins",datetime.now(), start_time)
|
||||
# For debug
|
||||
#self.separate_adjacent_pins(1)
|
||||
|
||||
# Enclose the continguous grid units in a metal rectangle to fix some DRCs
|
||||
#start_time = datetime.now()
|
||||
self.enclose_pins()
|
||||
#print_time("Enclose pins",datetime.now(), start_time)
|
||||
#self.write_debug_gds("debug_enclose_pins.gds",stop_program=True)
|
||||
|
||||
|
||||
def combine_adjacent_pins_pass(self, pin_name):
|
||||
def combine_adjacent_pins(self, pin_name):
|
||||
"""
|
||||
Find pins that have adjacent routing tracks and merge them into a
|
||||
single pin_group. The pins themselves may not be touching, but
|
||||
enclose_pis in the next step will ensure they are touching.
|
||||
"""
|
||||
|
||||
# Make a copy since we are going to add to (and then reduce) this list
|
||||
pin_groups = self.pin_groups[pin_name].copy()
|
||||
|
||||
# Start as None to signal the first iteration
|
||||
remove_indices = set()
|
||||
|
||||
debug.info(1,"Combining adjacent pins for {}.".format(pin_name))
|
||||
# Find all adjacencies
|
||||
adjacent_pins = {}
|
||||
for index1,pg1 in enumerate(self.pin_groups[pin_name]):
|
||||
# Cannot combine more than once
|
||||
if index1 in remove_indices:
|
||||
continue
|
||||
for index2,pg2 in enumerate(self.pin_groups[pin_name]):
|
||||
# Cannot combine with yourself
|
||||
if index1==index2:
|
||||
# Cannot combine with yourself, also don't repeat
|
||||
if index1<=index2:
|
||||
continue
|
||||
# Cannot combine more than once
|
||||
if index2 in remove_indices:
|
||||
continue
|
||||
|
||||
# Combine if at least 1 grid cell is adjacent
|
||||
if pg1.adjacent(pg2):
|
||||
combined = pin_group(pin_name, [], self)
|
||||
combined.combine_groups(pg1, pg2)
|
||||
debug.info(3,"Combining {0} {1} {2}:".format(pin_name, index1, index2))
|
||||
debug.info(3, " {0}\n {1}".format(pg1.pins, pg2.pins))
|
||||
debug.info(3," --> {0}\n {1}".format(combined.pins,combined.grids))
|
||||
remove_indices.update([index1,index2])
|
||||
pin_groups.append(combined)
|
||||
break
|
||||
if not index1 in adjacent_pins.keys():
|
||||
adjacent_pins[index1] = set([index2])
|
||||
else:
|
||||
adjacent_pins[index1].add(index2)
|
||||
|
||||
# Remove them in decreasing order to not invalidate the indices
|
||||
debug.info(4,"Removing {}".format(sorted(remove_indices)))
|
||||
for i in sorted(remove_indices, reverse=True):
|
||||
del pin_groups[i]
|
||||
|
||||
# Use the new pin group!
|
||||
self.pin_groups[pin_name] = pin_groups
|
||||
# Make a list of indices to ensure every group gets in the new set
|
||||
all_indices = set([x for x in range(len(self.pin_groups[pin_name]))])
|
||||
|
||||
removed_pairs = int(len(remove_indices)/2)
|
||||
debug.info(1, "Combined {0} pin pairs for {1}".format(removed_pairs,pin_name))
|
||||
# Now reconstruct the new groups
|
||||
new_pin_groups = []
|
||||
for index1,index2_set in adjacent_pins.items():
|
||||
# Remove the indices if they are added to the new set
|
||||
all_indices.discard(index1)
|
||||
all_indices.difference_update(index2_set)
|
||||
|
||||
# Create the combined group starting with the first item
|
||||
combined = self.pin_groups[pin_name][index1]
|
||||
# Add all of the other items that overlapped
|
||||
for index2 in index2_set:
|
||||
pg = self.pin_groups[pin_name][index2]
|
||||
combined.add_group(pg)
|
||||
debug.info(3,"Combining {0} {1}:".format(pin_name, index2))
|
||||
debug.info(3, " {0}\n {1}".format(combined.pins, pg.pins))
|
||||
debug.info(3," --> {0}\n {1}".format(combined.pins,combined.grids))
|
||||
new_pin_groups.append(combined)
|
||||
|
||||
# Add the pin groups that weren't added to the new set
|
||||
for index in all_indices:
|
||||
new_pin_groups.append(self.pin_groups[pin_name][index])
|
||||
|
||||
old_size = len(self.pin_groups[pin_name])
|
||||
# Use the new pin group!
|
||||
self.pin_groups[pin_name] = new_pin_groups
|
||||
removed_pairs = old_size - len(new_pin_groups)
|
||||
debug.info(1, "Combined {0} pin groups for {1}".format(removed_pairs,pin_name))
|
||||
|
||||
return removed_pairs
|
||||
|
||||
def combine_adjacent_pins(self, pin_name):
|
||||
"""
|
||||
Make multiple passes of the combine adjacent pins until we have no
|
||||
more combinations or hit an iteration limit.
|
||||
"""
|
||||
debug.info(1,"Combining adjacent pins for {}.".format(pin_name))
|
||||
# Start as None to signal the first iteration
|
||||
num_removed_pairs = None
|
||||
|
||||
# Just used in case there's a circular combination or something weird
|
||||
for iteration_count in range(10):
|
||||
num_removed_pairs = self.combine_adjacent_pins_pass(pin_name)
|
||||
if num_removed_pairs==0:
|
||||
break
|
||||
else:
|
||||
debug.warning("Did not converge combining adjacent pins in supply router.")
|
||||
|
||||
def separate_adjacent_pins(self, separation):
|
||||
"""
|
||||
|
|
@ -271,7 +279,7 @@ class router(router_tech):
|
|||
debug.info(1,"Comparing {0} and {1} adjacency".format(pin_name1, pin_name2))
|
||||
for index1,pg1 in enumerate(self.pin_groups[pin_name1]):
|
||||
for index2,pg2 in enumerate(self.pin_groups[pin_name2]):
|
||||
# FIXME: Use separation distance and edge grids only
|
||||
# FIgXME: Use separation distance and edge grids only
|
||||
grids_g1, grids_g2 = pg1.adjacent_grids(pg2, separation)
|
||||
# These should have the same length, so...
|
||||
if len(grids_g1)>0:
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@ import gdsMill
|
|||
import tech
|
||||
import math
|
||||
import debug
|
||||
from globals import OPTS
|
||||
from globals import OPTS,print_time
|
||||
from contact import contact
|
||||
from pin_group import pin_group
|
||||
from pin_layout import pin_layout
|
||||
from vector3d import vector3d
|
||||
from router import router
|
||||
from direction import direction
|
||||
from datetime import datetime
|
||||
import grid
|
||||
import grid_utils
|
||||
|
||||
|
|
@ -68,10 +69,13 @@ class supply_router(router):
|
|||
self.compute_supply_rail_dimensions()
|
||||
|
||||
# Get the pin shapes
|
||||
#start_time = datetime.now()
|
||||
self.find_pins_and_blockages([self.vdd_name, self.gnd_name])
|
||||
#print_time("Pins and blockages",datetime.now(), start_time)
|
||||
#self.write_debug_gds("pin_enclosures.gds",stop_program=True)
|
||||
|
||||
# Add the supply rails in a mesh network and connect H/V with vias
|
||||
#start_time = datetime.now()
|
||||
# Block everything
|
||||
self.prepare_blockages(self.gnd_name)
|
||||
# Determine the rail locations
|
||||
|
|
@ -82,15 +86,20 @@ class supply_router(router):
|
|||
# Determine the rail locations
|
||||
self.route_supply_rails(self.vdd_name,1)
|
||||
#self.write_debug_gds("debug_rails.gds",stop_program=True)
|
||||
|
||||
#print_time("Supply rails",datetime.now(), start_time)
|
||||
|
||||
#start_time = datetime.now()
|
||||
self.route_simple_overlaps(vdd_name)
|
||||
self.route_simple_overlaps(gnd_name)
|
||||
#print_time("Simple overlaps",datetime.now(), start_time)
|
||||
#self.write_debug_gds("debug_simple_route.gds",stop_program=False)
|
||||
|
||||
# Route the supply pins to the supply rails
|
||||
# Route vdd first since we want it to be shorter
|
||||
#start_time = datetime.now()
|
||||
self.route_pins_to_rails(vdd_name)
|
||||
self.route_pins_to_rails(gnd_name)
|
||||
#print_time("Routing",datetime.now(), start_time)
|
||||
#self.write_debug_gds("debug_pin_routes.gds",stop_program=True)
|
||||
|
||||
#self.write_debug_gds("final.gds",False)
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ class sram_1bank(sram_base):
|
|||
|
||||
self.data_dff_insts = self.create_data_dff()
|
||||
|
||||
def place_modules(self):
|
||||
def place_instances(self):
|
||||
"""
|
||||
This places the modules for a single bank SRAM with control
|
||||
logic.
|
||||
This places the instances for a single bank SRAM with control
|
||||
logic and up to 2 ports.
|
||||
"""
|
||||
|
||||
# No orientation or offset
|
||||
|
|
@ -57,39 +57,73 @@ class sram_1bank(sram_base):
|
|||
# the sense amps/column mux and cell array)
|
||||
# The x-coordinate is placed to allow a single clock wire (plus an extra pitch)
|
||||
# up to the row address DFFs.
|
||||
for port in self.all_ports:
|
||||
control_pos = vector(-self.control_logic_rw.width - 2*self.m2_pitch,
|
||||
self.bank.bank_center.y - self.control_logic_rw.control_logic_center.y)
|
||||
self.control_logic_insts[port].place(control_pos)
|
||||
control_pos = [None]*len(self.all_ports)
|
||||
row_addr_pos = [None]*len(self.all_ports)
|
||||
col_addr_pos = [None]*len(self.all_ports)
|
||||
data_pos = [None]*len(self.all_ports)
|
||||
|
||||
# This is M2 pitch even though it is on M1 to help stem via spacings on the trunk
|
||||
data_gap = self.m2_pitch*(self.word_size+1)
|
||||
|
||||
# The row address bits are placed above the control logic aligned on the right.
|
||||
row_addr_pos = vector(self.control_logic_insts[0].rx() - self.row_addr_dff.width,
|
||||
self.control_logic_insts[0].uy())
|
||||
self.row_addr_dff_insts[port].place(row_addr_pos)
|
||||
# Port 0
|
||||
port = 0
|
||||
# This includes 2 M2 pitches for the row addr clock line
|
||||
control_pos[port] = vector(-self.control_logic_insts[port].width - 2*self.m2_pitch,
|
||||
self.bank.bank_array_ll.y - self.control_logic_insts[port].mod.control_logic_center.y)
|
||||
self.control_logic_insts[port].place(control_pos[port])
|
||||
|
||||
# The row address bits are placed above the control logic aligned on the right.
|
||||
row_addr_pos[port] = vector(self.control_logic_insts[port].rx() - self.row_addr_dff_insts[port].width,
|
||||
self.control_logic_insts[port].uy())
|
||||
self.row_addr_dff_insts[port].place(row_addr_pos[port])
|
||||
|
||||
# Add the col address flops below the bank to the left of the lower-left of bank array
|
||||
if self.col_addr_dff:
|
||||
col_addr_pos[port] = vector(self.bank.bank_array_ll.x - self.col_addr_dff_insts[port].width - self.bank.central_bus_width,
|
||||
-data_gap - self.col_addr_dff_insts[port].height)
|
||||
self.col_addr_dff_insts[port].place(col_addr_pos[port])
|
||||
|
||||
# This is M2 pitch even though it is on M1 to help stem via spacings on the trunk
|
||||
data_gap = -self.m2_pitch*(self.word_size+1)
|
||||
|
||||
# Add the column address below the bank under the control
|
||||
# The column address flops are aligned with the data flops
|
||||
# Add the data flops below the bank to the right of the lower-left of bank array
|
||||
# This relies on the lower-left of the array of the bank
|
||||
# decoder in upper left, bank in upper right, sensing in lower right.
|
||||
# These flops go below the sensing and leave a gap to channel route to the
|
||||
# sense amps.
|
||||
if port in self.write_ports:
|
||||
data_pos[port] = vector(self.bank.bank_array_ll.x,
|
||||
-data_gap - self.data_dff_insts[port].height)
|
||||
self.data_dff_insts[port].place(data_pos[port])
|
||||
|
||||
|
||||
if len(self.all_ports)>1:
|
||||
# Port 1
|
||||
port = 1
|
||||
# This includes 2 M2 pitches for the row addr clock line
|
||||
control_pos[port] = vector(self.bank_inst.rx() + self.control_logic_insts[port].width + 2*self.m2_pitch,
|
||||
self.bank.bank_array_ll.y - self.control_logic_insts[port].mod.control_logic_center.y)
|
||||
self.control_logic_insts[port].place(control_pos[port], mirror="MY")
|
||||
|
||||
# The row address bits are placed above the control logic aligned on the left.
|
||||
row_addr_pos[port] = vector(control_pos[port].x - self.control_logic_insts[port].width + self.row_addr_dff_insts[port].width,
|
||||
self.control_logic_insts[port].uy())
|
||||
self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="MY")
|
||||
|
||||
# Add the col address flops above the bank to the right of the upper-right of bank array
|
||||
if self.col_addr_dff:
|
||||
col_addr_pos = vector(self.bank.bank_center.x - self.col_addr_dff.width - self.bank.central_bus_width,
|
||||
data_gap - self.col_addr_dff.height)
|
||||
self.col_addr_dff_insts[port].place(col_addr_pos)
|
||||
col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.central_bus_width,
|
||||
self.bank_inst.uy() + data_gap + self.col_addr_dff_insts[port].height)
|
||||
self.col_addr_dff_insts[port].place(col_addr_pos[port], mirror="MX")
|
||||
|
||||
# Add the data flops below the bank to the right of the center of bank:
|
||||
# This relies on the center point of the bank:
|
||||
# Add the data flops above the bank to the left of the upper-right of bank array
|
||||
# This relies on the upper-right of the array of the bank
|
||||
# decoder in upper left, bank in upper right, sensing in lower right.
|
||||
# These flops go below the sensing and leave a gap to channel route to the
|
||||
# sense amps.
|
||||
data_pos = vector(self.bank.bank_center.x,
|
||||
data_gap - self.data_dff.height)
|
||||
self.data_dff_insts[port].place(data_pos)
|
||||
|
||||
# two supply rails are already included in the bank, so just 2 here.
|
||||
# self.width = self.bank.width + self.control_logic.width + 2*self.supply_rail_pitch
|
||||
# self.height = self.bank.height
|
||||
if port in self.write_ports:
|
||||
data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width,
|
||||
self.bank.uy() + data_gap + self.data_dff_insts[port].height)
|
||||
self.data_dff_insts[port].place(data_pos[port], mirror="MX")
|
||||
|
||||
|
||||
def add_layout_pins(self):
|
||||
"""
|
||||
Add the top-level pins for a single bank SRAM with control.
|
||||
|
|
@ -114,7 +148,7 @@ class sram_1bank(sram_base):
|
|||
for bit in range(self.word_size):
|
||||
self.copy_layout_pin(self.data_dff_insts[port], "din_{}".format(bit), "DIN{0}[{1}]".format(port,bit))
|
||||
|
||||
def route(self):
|
||||
def route_layout(self):
|
||||
""" Route a single bank SRAM """
|
||||
|
||||
self.add_layout_pins()
|
||||
|
|
@ -151,20 +185,27 @@ class sram_1bank(sram_base):
|
|||
dff_clk_pos = dff_clk_pin.center()
|
||||
mid_pos = vector(bank_clk_buf_pos.x, dff_clk_pos.y)
|
||||
self.add_wire(("metal3","via2","metal2"),[dff_clk_pos, mid_pos, bank_clk_buf_pos])
|
||||
|
||||
data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk")
|
||||
data_dff_clk_pos = data_dff_clk_pin.center()
|
||||
mid_pos = vector(bank_clk_buf_pos.x, data_dff_clk_pos.y)
|
||||
self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, bank_clk_buf_pos])
|
||||
|
||||
# This uses a metal2 track to the right of the control/row addr DFF
|
||||
# to route vertically.
|
||||
if port in self.write_ports:
|
||||
data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk")
|
||||
data_dff_clk_pos = data_dff_clk_pin.center()
|
||||
mid_pos = vector(bank_clk_buf_pos.x, data_dff_clk_pos.y)
|
||||
self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, bank_clk_buf_pos])
|
||||
|
||||
# This uses a metal2 track to the right (for port0) of the control/row addr DFF
|
||||
# to route vertically. For port1, it is to the left.
|
||||
control_clk_buf_pin = self.control_logic_insts[port].get_pin("clk_buf")
|
||||
control_clk_buf_pos = control_clk_buf_pin.rc()
|
||||
row_addr_clk_pin = self.row_addr_dff_insts[port].get_pin("clk")
|
||||
row_addr_clk_pos = row_addr_clk_pin.rc()
|
||||
mid1_pos = vector(self.row_addr_dff_insts[port].rx() + self.m2_pitch,
|
||||
row_addr_clk_pos.y)
|
||||
if port%2:
|
||||
control_clk_buf_pos = control_clk_buf_pin.lc()
|
||||
row_addr_clk_pos = row_addr_clk_pin.lc()
|
||||
mid1_pos = vector(self.row_addr_dff_insts[port].lx() - self.m2_pitch,
|
||||
row_addr_clk_pos.y)
|
||||
else:
|
||||
control_clk_buf_pos = control_clk_buf_pin.rc()
|
||||
row_addr_clk_pos = row_addr_clk_pin.rc()
|
||||
mid1_pos = vector(self.row_addr_dff_insts[port].rx() + self.m2_pitch,
|
||||
row_addr_clk_pos.y)
|
||||
mid2_pos = vector(mid1_pos.x,
|
||||
control_clk_buf_pos.y)
|
||||
# Note, the via to the control logic is taken care of when we route
|
||||
|
|
|
|||
|
|
@ -76,8 +76,9 @@ class sram_base(design):
|
|||
|
||||
def create_layout(self):
|
||||
""" Layout creation """
|
||||
self.place_modules()
|
||||
self.route()
|
||||
self.place_instances()
|
||||
|
||||
self.route_layout()
|
||||
|
||||
self.add_lvs_correspondence_points()
|
||||
|
||||
|
|
@ -398,9 +399,13 @@ class sram_base(design):
|
|||
def create_data_dff(self):
|
||||
""" Add and place all data flops """
|
||||
insts = []
|
||||
for port in self.write_ports:
|
||||
insts.append(self.add_inst(name="data_dff{}".format(port),
|
||||
mod=self.data_dff))
|
||||
for port in self.all_ports:
|
||||
if port in self.write_ports:
|
||||
insts.append(self.add_inst(name="data_dff{}".format(port),
|
||||
mod=self.data_dff))
|
||||
else:
|
||||
insts.append(None)
|
||||
continue
|
||||
|
||||
# inputs, outputs/output/bar
|
||||
inputs = []
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Run a test on a multiport replica bitline
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from testutils import header,openram_test
|
||||
import sys,os
|
||||
sys.path.append(os.path.join(sys.path[0],".."))
|
||||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
|
||||
class replica_bitline_multiport_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
import replica_bitline
|
||||
|
||||
stages=4
|
||||
fanout=4
|
||||
rows=13
|
||||
|
||||
OPTS.bitcell = "bitcell_1rw_1r"
|
||||
OPTS.replica_bitcell = "replica_bitcell_1rw_1r"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
|
||||
debug.info(2, "Testing 1rw 1r RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
# check replica bitline in pbitcell multi-port
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.replica_bitcell = "replica_pbitcell"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
debug.info(2, "Testing RBL pbitcell 1rw with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
|
||||
debug.info(2, "Testing RBL pbitcell 1rw 1w 1r with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = globals.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main()
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Run a test on a delay chain
|
||||
Run a test on a replica bitline
|
||||
"""
|
||||
|
||||
import unittest
|
||||
|
|
@ -32,61 +32,6 @@ class replica_bitline_test(openram_test):
|
|||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
#check replica bitline in handmade multi-port 1rw+1r cell
|
||||
OPTS.bitcell = "bitcell_1rw_1r"
|
||||
OPTS.replica_bitcell = "replica_bitcell_1rw_1r"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 1
|
||||
stages=4
|
||||
fanout=4
|
||||
rows=13
|
||||
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
stages=8
|
||||
rows=100
|
||||
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
# check replica bitline in pbitcell multi-port
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.replica_bitcell = "replica_pbitcell"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 0
|
||||
|
||||
stages=4
|
||||
fanout=4
|
||||
rows=13
|
||||
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
stages=8
|
||||
rows=100
|
||||
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
|
||||
stages=4
|
||||
fanout=4
|
||||
rows=13
|
||||
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
stages=8
|
||||
rows=100
|
||||
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Run a regression test on a 1 bank, 2 port SRAM
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from testutils import header,openram_test
|
||||
import sys,os
|
||||
sys.path.append(os.path.join(sys.path[0],".."))
|
||||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
|
||||
class sram_1bank_2mux_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
|
||||
OPTS.bitcell = "bitcell_1rw_1r"
|
||||
OPTS.replica_bitcell = "replica_bitcell_1rw_1r"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
|
||||
c = sram_config(word_size=4,
|
||||
num_words=32,
|
||||
num_banks=1)
|
||||
|
||||
c.words_per_row=2
|
||||
debug.info(1, "Single bank, two way column mux 1rw, 1r with control logic")
|
||||
a = sram(c, "sram")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = globals.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main()
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Run a regression test on a 1 bank, 2 port SRAM
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from testutils import header,openram_test
|
||||
import sys,os
|
||||
sys.path.append(os.path.join(sys.path[0],".."))
|
||||
import globals
|
||||
from globals import OPTS
|
||||
import debug
|
||||
|
||||
class sram_1bank_nomux_1rw_1r_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||
from sram import sram
|
||||
from sram_config import sram_config
|
||||
|
||||
OPTS.bitcell = "bitcell_1rw_1r"
|
||||
OPTS.replica_bitcell = "replica_bitcell_1rw_1r"
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_r_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
|
||||
c.words_per_row=1
|
||||
debug.info(1, "Single bank, no column mux 1rw, 1r with control logic")
|
||||
a = sram(c, "sram")
|
||||
self.local_check(a, final_verification=True)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = globals.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main()
|
||||
Binary file not shown.
|
|
@ -1,568 +1,113 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="sense_amp_schem.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="78.947962"
|
||||
inkscape:cy="503.38478"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="3440"
|
||||
inkscape:window-height="1392"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2989" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 465.75 458.25" width="465.75pt" height="458.25pt" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata> Produced by OmniGraffle 7.6.1
|
||||
<dc:date>2018-11-16 00:52:28 +0000</dc:date>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g3496-2"
|
||||
transform="matrix(0,-1,1,0,-62.34811,791.36093)">
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,240,223.19311)"
|
||||
id="g3011-2">
|
||||
<path
|
||||
id="path3013-5"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 31.199,119.324 29.539,0 0,-14.66 36.922,0 0,14.66 29.539,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
<defs>
|
||||
<font-face font-family="Helvetica" font-size="12" units-per-em="1000" underline-position="-75.68359" underline-thickness="49.316406" slope="0" x-height="522.9492" cap-height="717.28516" ascent="770.0195" descent="-229.98047" font-weight="500">
|
||||
<font-face-src>
|
||||
<font-face-name name="Helvetica"/>
|
||||
</font-face-src>
|
||||
</font-face>
|
||||
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledCenterBall_Marker" viewBox="-1 -4 8 8" markerWidth="8" markerHeight="8" color="black">
|
||||
<g>
|
||||
<circle cx="2.9999986" cy="0" r="2.999997" fill="currentColor" stroke="currentColor" stroke-width="1"/>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,240,223.19311)"
|
||||
id="g3015-0">
|
||||
<path
|
||||
id="path3017-5"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 61.09,100.621 36.57,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,240,223.19311)"
|
||||
id="g3019-3">
|
||||
<path
|
||||
id="path3021-5"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 58.523,104.664 40.614,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3496-3"
|
||||
transform="matrix(0,1,-1,0,802.34811,113.36343)">
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,240,223.19311)"
|
||||
id="g3011-6">
|
||||
<path
|
||||
id="path3013-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 31.199,119.324 29.539,0 0,-14.66 36.922,0 0,14.66 29.539,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,240,223.19311)"
|
||||
id="g3015-2">
|
||||
<path
|
||||
id="path3017-1"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 61.09,100.621 36.57,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,240,223.19311)"
|
||||
id="g3019-35">
|
||||
<path
|
||||
id="path3021-51"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 58.523,104.664 40.614,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3496-8"
|
||||
transform="matrix(0,-1,1,0,-2.34811,920.37376)">
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,240,223.19311)"
|
||||
id="g3011-0">
|
||||
<path
|
||||
id="path3013-66"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 31.199,119.324 29.539,0 0,-14.66 36.922,0 0,14.66 29.539,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,240,223.19311)"
|
||||
id="g3015-3">
|
||||
<path
|
||||
id="path3017-52"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 61.09,100.621 36.57,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,240,223.19311)"
|
||||
id="g3019-1">
|
||||
<path
|
||||
id="path3021-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 58.523,104.664 40.614,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3630"
|
||||
transform="matrix(0,-1,1,0,-332.3481,1091.3609)">
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,370,363.1931)"
|
||||
id="g3035">
|
||||
<path
|
||||
id="path3037"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 31.199,271.324 -16,0 0,-16 0,32"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,370,363.1931)"
|
||||
id="g3039">
|
||||
<path
|
||||
id="path3041"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 7.199,263.324 0,16"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,370,363.1931)"
|
||||
id="g3043">
|
||||
<path
|
||||
id="path3045"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 0.801,266.523 0,9.602"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3689"
|
||||
transform="translate(1.00125,0.01406962)">
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,-200,23.193113)"
|
||||
id="g3223">
|
||||
<path
|
||||
id="path3225"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.30079997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 434.398,221.727 c 0,2.207 -1.789,4 -4,4 -2.207,0 -4,-1.793 -4,-4 0,-2.211 1.793,-4 4,-4 2.211,0 4,1.789 4,4 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
|
||||
id="g3227">
|
||||
<path
|
||||
id="path3229"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 175.324,-407.199 29.539,0 0,-14.66 36.922,0 0,14.66 29.539,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
|
||||
id="g3231">
|
||||
<path
|
||||
id="path3233"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 205.215,-425.902 36.57,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
|
||||
id="g3235">
|
||||
<path
|
||||
id="path3237"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 202.648,-421.859 40.614,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3689-1"
|
||||
transform="matrix(-1,0,0,1,738.99875,0.01406962)">
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,-200,23.193113)"
|
||||
id="g3223-4">
|
||||
<path
|
||||
id="path3225-0"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.30079997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 434.398,221.727 c 0,2.207 -1.789,4 -4,4 -2.207,0 -4,-1.793 -4,-4 0,-2.211 1.793,-4 4,-4 2.211,0 4,1.789 4,4 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
|
||||
id="g3227-8">
|
||||
<path
|
||||
id="path3229-5"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 175.324,-407.199 29.539,0 0,-14.66 36.922,0 0,14.66 29.539,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
|
||||
id="g3231-3">
|
||||
<path
|
||||
id="path3233-9"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 205.215,-425.902 36.57,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
|
||||
id="g3235-8">
|
||||
<path
|
||||
id="path3237-5"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 202.648,-421.859 40.614,0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 310,362.36218 0,30"
|
||||
id="path3810"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 430,362.36218 0,30"
|
||||
id="path4580"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 310,242.36218 0,-20 120,0 0,20"
|
||||
id="path4582"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 370,222.36218 0,-40 30,0 -60,0"
|
||||
id="path4584"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 310,512.36218 120,0 -60,0 0,10"
|
||||
id="path4588"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2.23606801;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 370,632.36218 0,50"
|
||||
id="path4590"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 130,452.36218 -30,0 0,-120 0,220 0,10"
|
||||
id="path4592"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 604,452.36218 h 30 v -120 230"
|
||||
id="path4594"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 184,416.36218 v -20 -10"
|
||||
id="path4598"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 544,416.36218 v -30"
|
||||
id="path4600"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 490,452.36218 -40,0"
|
||||
id="path4602"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 250,452.36218 40,0"
|
||||
id="path4604"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 350,582.36218 -30,0"
|
||||
id="path4606"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g3319-2"
|
||||
transform="matrix(1.25,0,0,1,-140,173.20718)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 409.934,339.155 c 0,1.338 -0.864,2.417 -1.934,2.417 -1.07,0 -1.934,-1.079 -1.934,-2.417 0,-1.333 0.864,-2.417 1.934,-2.417 1.07,0 1.934,1.084 1.934,2.417 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.93475199;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3321-6" />
|
||||
</g>
|
||||
<g
|
||||
id="g3319-9"
|
||||
transform="matrix(1.25,0,0,1,-410,113.20718)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 409.934,339.155 c 0,1.338 -0.864,2.417 -1.934,2.417 -1.07,0 -1.934,-1.079 -1.934,-2.417 0,-1.333 0.864,-2.417 1.934,-2.417 1.07,0 1.934,1.084 1.934,2.417 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.93475199;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3321-1" />
|
||||
</g>
|
||||
<g
|
||||
id="g3319-3"
|
||||
transform="matrix(1.25,0,0,1,125,112.20718)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 409.934,339.155 c 0,1.338 -0.864,2.417 -1.934,2.417 -1.07,0 -1.934,-1.079 -1.934,-2.417 0,-1.333 0.864,-2.417 1.934,-2.417 1.07,0 1.934,1.084 1.934,2.417 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.93475199;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path3321-5" />
|
||||
</g>
|
||||
<g
|
||||
id="g3319"
|
||||
transform="matrix(1.25,0,0,1,-139,-116.79282)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 409.934,339.155 c 0,1.338 -0.864,2.417 -1.934,2.417 -1.07,0 -1.934,-1.079 -1.934,-2.417 0,-1.333 0.864,-2.417 1.934,-2.417 1.07,0 1.934,1.084 1.934,2.417 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.93475199;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3321" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 370,302.36218 0,70 -60,0"
|
||||
id="path4656"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 430,372.36218 80,0 0,-70 0,0 -10,10 10,-10 10,10"
|
||||
id="path4658"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g3319-4"
|
||||
transform="matrix(1.25,0,0,1,-201,33.207183)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 409.934,339.155 c 0,1.338 -0.864,2.417 -1.934,2.417 -1.07,0 -1.934,-1.079 -1.934,-2.417 0,-1.333 0.864,-2.417 1.934,-2.417 1.07,0 1.934,1.084 1.934,2.417 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.93475199;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3321-58" />
|
||||
</g>
|
||||
<g
|
||||
id="g3319-91"
|
||||
transform="matrix(1.25,0,0,1,-79,33.207183)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 409.934,339.155 c 0,1.338 -0.864,2.417 -1.934,2.417 -1.07,0 -1.934,-1.079 -1.934,-2.417 0,-1.333 0.864,-2.417 1.934,-2.417 1.07,0 1.934,1.084 1.934,2.417 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.93475199;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3321-4" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 345,300.36218 50,0"
|
||||
id="path4680"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g3319-1"
|
||||
transform="matrix(1.25,0,0,1,-140,-37.792817)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 409.934,339.155 c 0,1.338 -0.864,2.417 -1.934,2.417 -1.07,0 -1.934,-1.079 -1.934,-2.417 0,-1.333 0.864,-2.417 1.934,-2.417 1.07,0 1.934,1.084 1.934,2.417 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.93475199;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3321-42" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="390"
|
||||
y="172.36218"
|
||||
id="text4691"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4693"
|
||||
x="390"
|
||||
y="172.36218"
|
||||
style="font-size:16px;line-height:1.25;font-family:sans-serif">vdd</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="488"
|
||||
y="297.36218"
|
||||
id="text4695"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4697"
|
||||
x="488"
|
||||
y="297.36218"
|
||||
style="font-size:16px;line-height:1.25;font-family:sans-serif">DATA</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="621"
|
||||
y="577.36218"
|
||||
id="text4699"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4701"
|
||||
x="621"
|
||||
y="577.36218"
|
||||
style="font-size:16px;line-height:1.25;font-family:sans-serif">br</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="89"
|
||||
y="580.36218"
|
||||
id="text4703"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4705"
|
||||
x="89"
|
||||
y="580.36218"
|
||||
style="font-size:16px;line-height:1.25;font-family:sans-serif">bl</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="295"
|
||||
y="588.36218"
|
||||
id="text4707"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4709"
|
||||
x="295"
|
||||
y="588.36218"
|
||||
style="font-size:16px;line-height:1.25;font-family:sans-serif">en</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="538"
|
||||
y="382.36218"
|
||||
id="text4711"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4713"
|
||||
x="538"
|
||||
y="382.36218"
|
||||
style="font-size:16px;line-height:1.25;font-family:sans-serif">en</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="177.87868"
|
||||
y="376.02765"
|
||||
id="text4715"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4717"
|
||||
x="177.87868"
|
||||
y="376.02765"
|
||||
style="font-size:16px;line-height:1.25;font-family:sans-serif">en</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
|
||||
d="m 680,572.36218 0,-440 -620,0 0,610 620,0 z"
|
||||
id="path4738"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
transform="rotate(-90,322.13078,437.55515)"
|
||||
id="g161">
|
||||
<g
|
||||
id="g147"
|
||||
transform="matrix(1.25,0,0,1.25,-200,23.193113)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 434.398,221.727 c 0,2.207 -1.789,4 -4,4 -2.207,0 -4,-1.793 -4,-4 0,-2.211 1.793,-4 4,-4 2.211,0 4,1.789 4,4 z"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.30079997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path145" />
|
||||
</g>
|
||||
<g
|
||||
id="g151"
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 175.324,-407.199 h 29.539 v -14.66 h 36.922 v 14.66 h 29.539"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path149" />
|
||||
</g>
|
||||
<g
|
||||
id="g155"
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 205.215,-425.902 h 36.57"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path153" />
|
||||
</g>
|
||||
<g
|
||||
id="g159"
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 202.648,-421.859 h 40.614"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path157" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g179"
|
||||
transform="rotate(-90,502.65766,258.08202)">
|
||||
<g
|
||||
transform="matrix(1.25,0,0,1.25,-200,23.193113)"
|
||||
id="g165">
|
||||
<path
|
||||
id="path163"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.30079997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 434.398,221.727 c 0,2.207 -1.789,4 -4,4 -2.207,0 -4,-1.793 -4,-4 0,-2.211 1.793,-4 4,-4 2.211,0 4,1.789 4,4 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
|
||||
id="g169">
|
||||
<path
|
||||
id="path167"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 175.324,-407.199 h 29.539 v -14.66 h 36.922 v 14.66 h 29.539"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
|
||||
id="g173">
|
||||
<path
|
||||
id="path171"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 205.215,-425.902 h 36.57"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
|
||||
id="g177">
|
||||
<path
|
||||
id="path175"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 202.648,-421.859 h 40.614"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledCenterBall_Marker_2" viewBox="-7 -4 8 8" markerWidth="8" markerHeight="8" color="black">
|
||||
<g>
|
||||
<circle cx="-2.9999986" cy="0" r="2.999997" fill="currentColor" stroke="currentColor" stroke-width="1"/>
|
||||
</g>
|
||||
</marker>
|
||||
</defs>
|
||||
<g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1">
|
||||
<title>Canvas 1</title>
|
||||
<rect fill="white" width="465.75" height="458.25"/>
|
||||
<g>
|
||||
<title>Layer 1</title>
|
||||
<path d="M 187.875 285.375 L 187.875 257.684 L 174.133 257.684 L 174.133 223.066 L 187.875 223.066 L 187.875 195.375" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="170.34" y1="257.352" x2="170.34" y2="223.066" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="174.133" y1="259.758" x2="174.133" y2="221.684" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 277.875 195.375 L 277.875 223.066 L 291.617 223.066 L 291.617 257.684 L 277.875 257.684 L 277.875 285.375" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="295.41" y1="223.398" x2="295.41" y2="257.684" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="291.617" y1="220.992" x2="291.617" y2="259.066" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 232.875 382.133 L 232.875 354.441 L 219.133 354.441 L 219.133 319.828 L 232.875 319.828 L 232.875 292.133" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="215.34" y1="354.113" x2="215.34" y2="319.828" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="219.133" y1="356.52" x2="219.133" y2="318.441" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 232.875 412.875 L 232.875 427.875 L 217.875 427.875 L 247.875 427.875" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="225.375" y1="435.375" x2="240.375" y2="435.375" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="228.375" y1="441.375" x2="237.375" y2="441.375" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 161.391 126.7792 C 161.391 128.8452 163.071 130.5292 165.141 130.5292 C 167.211 130.5292 168.891 128.8452 168.891 126.7792 C 168.891 124.7052 167.211 123.0292 165.141 123.0292 C 163.071 123.0292 161.391 124.7052 161.391 126.7792 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 188.188 82.1252 L 188.188 109.8162 L 174.446 109.8162 L 174.446 144.4342 L 188.188 144.4342 L 188.188 172.1252" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="169.754" y1="108.0882" x2="169.754" y2="146.1622" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 300.125 128.041 C 300.125 130.107 301.805 131.791 303.875 131.791 C 305.945 131.791 307.625 130.107 307.625 128.041 C 307.625 125.967 305.945 124.291 303.875 124.291 C 301.805 124.291 300.125 125.967 300.125 128.041 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 277.562 83.041 L 277.562 110.732 L 291.304 110.732 L 291.304 145.35 L 277.562 145.35 L 277.562 173.041" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="299.125" y1="108.0882" x2="299.125" y2="146.1622" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="187.875" y1="172.875" x2="187.875" y2="195.375" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="277.875" y1="172.875" x2="277.875" y2="195.375" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 187.875 82.875 L 187.875 67.875 L 277.875 67.875 L 277.875 82.875" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 232.875 67.875 L 232.875 37.875 L 255.375 37.875 L 210.375 37.875" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 187.875 285.375 L 277.875 285.375 L 232.875 285.375 L 232.875 292.875" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="232.875" y1="375.375" x2="232.875" y2="412.875" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 52.875 240.375 L 30.375 240.375 L 30.375 150.375 L 30.375 322.875" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 408.375 240.375 L 430.875 240.375 L 430.875 150.375 L 430.875 322.875" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="93.375" y1="213.375" x2="93.375" y2="190.875" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="363.375" y1="213.375" x2="363.375" y2="190.875" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="322.875" y1="240.375" x2="292.875" y2="240.375" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="142.875" y1="240.375" x2="172.875" y2="240.375" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="217.875" y1="337.875" x2="195.375" y2="337.875" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 234.688 285.3752 C 234.688 286.3792 233.879 287.1872 232.875 287.1872 C 231.871 287.1872 231.062 286.3792 231.062 285.3752 C 231.062 284.3752 231.871 283.5624 232.875 283.5624 C 233.879 283.5624 234.688 284.3752 234.688 285.3752 Z" fill="black"/>
|
||||
<path d="M 234.688 285.3752 C 234.688 286.3792 233.879 287.1872 232.875 287.1872 C 231.871 287.1872 231.062 286.3792 231.062 285.3752 C 231.062 284.3752 231.871 283.5624 232.875 283.5624 C 233.879 283.5624 234.688 284.3752 234.688 285.3752 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 32.188 240.3752 C 32.188 241.3792 31.379 242.1872 30.375 242.1872 C 29.371 242.1872 28.562 241.3792 28.562 240.3752 C 28.562 239.3752 29.371 238.5624 30.375 238.5624 C 31.379 238.5624 32.188 239.3752 32.188 240.3752 Z" fill="black"/>
|
||||
<path d="M 32.188 240.3752 C 32.188 241.3792 31.379 242.1872 30.375 242.1872 C 29.371 242.1872 28.562 241.3792 28.562 240.3752 C 28.562 239.3752 29.371 238.5624 30.375 238.5624 C 31.379 238.5624 32.188 239.3752 32.188 240.3752 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 433.438 239.6248 C 433.438 240.6288 432.629 241.4376 431.625 241.4376 C 430.621 241.4376 429.812 240.6288 429.812 239.6248 C 429.812 238.6248 430.621 237.8128 431.625 237.8128 C 432.629 237.8128 433.438 238.6248 433.438 239.6248 Z" fill="black"/>
|
||||
<path d="M 433.438 239.6248 C 433.438 240.6288 432.629 241.4376 431.625 241.4376 C 430.621 241.4376 429.812 240.6288 429.812 239.6248 C 429.812 238.6248 430.621 237.8128 431.625 237.8128 C 432.629 237.8128 433.438 238.6248 433.438 239.6248 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 235.438 67.8752 C 235.438 68.8792 234.629 69.6872 233.625 69.6872 C 232.621 69.6872 231.812 68.8792 231.812 67.8752 C 231.812 66.8752 232.621 66.0624 233.625 66.0624 C 234.629 66.0624 235.438 66.8752 235.438 67.8752 Z" fill="black"/>
|
||||
<path d="M 235.438 67.8752 C 235.438 68.8792 234.629 69.6872 233.625 69.6872 C 232.621 69.6872 231.812 68.8792 231.812 67.8752 C 231.812 66.8752 232.621 66.0624 233.625 66.0624 C 234.629 66.0624 235.438 66.8752 235.438 67.8752 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 307.625 126 L 307.625 191 L 308 240.375" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 185.312 180.375 L 125.312 180.375 L 125.312 127.875 L 132.812 135.375 L 125.312 127.875 L 117.812 135.375" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 188.938 180.3752 C 188.938 181.3792 188.129 182.1872 187.125 182.1872 C 186.121 182.1872 185.312 181.3792 185.312 180.3752 C 185.312 179.3752 186.121 178.5624 187.125 178.5624 C 188.129 178.5624 188.938 179.3752 188.938 180.3752 Z" fill="black"/>
|
||||
<path d="M 188.938 180.3752 C 188.938 181.3792 188.129 182.1872 187.125 182.1872 C 186.121 182.1872 185.312 181.3792 185.312 180.3752 C 185.312 179.3752 186.121 178.5624 187.125 178.5624 C 188.129 178.5624 188.938 179.3752 188.938 180.3752 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<text transform="translate(247.875 16.375002)" fill="black">
|
||||
<tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="0" y="11">vdd</tspan>
|
||||
</text>
|
||||
<text transform="translate(97.875 108.0882)" fill="black">
|
||||
<tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="0" y="11">DA</tspan>
|
||||
<tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="15.785156" y="11">T</tspan>
|
||||
<tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="22.23047" y="11">A</tspan>
|
||||
</text>
|
||||
<text transform="translate(421.125 320.125)" fill="black">
|
||||
<tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="0" y="11">br</tspan>
|
||||
</text>
|
||||
<text transform="translate(22.125 322.375)" fill="black">
|
||||
<tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="0" y="11">bl</tspan>
|
||||
</text>
|
||||
<text transform="translate(176.625 328.375)" fill="black">
|
||||
<tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="0" y="11">en</tspan>
|
||||
</text>
|
||||
<text transform="translate(358.875 173.875)" fill="black">
|
||||
<tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="0" y="11">en</tspan>
|
||||
</text>
|
||||
<text transform="translate(88.784 169.1241)" fill="black">
|
||||
<tspan font-family="Helvetica" font-size="12" font-weight="500" fill="black" x="0" y="11">en</tspan>
|
||||
</text>
|
||||
<path d="M 94.07 213.621 C 96.141 213.621 97.82 215.297 97.82 217.371 C 97.82 219.438 96.141 221.121 94.07 221.121 C 91.996 221.121 90.32 219.438 90.32 217.371 C 90.32 215.297 91.996 213.621 94.07 213.621 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 52.875 239.906 L 80.571 239.906 L 80.571 226.164 L 115.184 226.164 L 115.184 239.906 L 142.875 239.906" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="80.7325" y1="221.367" x2="115.0175" y2="221.367" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 364.07 214.41 C 366.141 214.41 367.82 216.086 367.82 218.16 C 367.82 220.23 366.141 221.91 364.07 221.91 C 361.996 221.91 360.32 220.23 360.32 218.16 C 360.32 216.086 361.996 214.41 364.07 214.41 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 320.566 239.91 L 348.262 239.91 L 348.262 226.164 L 382.875 226.164 L 382.875 239.91 L 410.566 239.91" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="348.59" y1="222.375" x2="382.875" y2="222.375" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<line x1="346.184" y1="226.164" x2="384.258" y2="226.164" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 160.391 125.535 L 160.391 190.535 L 160.766 239.91" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 161.391 165.5978 C 161.391 166.6018 160.582 167.4098 159.578 167.4098 C 158.574 167.4098 157.765 166.6018 157.765 165.5978 C 157.765 164.5978 158.574 163.785 159.578 163.785 C 160.582 163.785 161.391 164.5978 161.391 165.5978 Z" fill="black"/>
|
||||
<path d="M 161.391 165.5978 C 161.391 166.6018 160.582 167.4098 159.578 167.4098 C 158.574 167.4098 157.765 166.6018 157.765 165.5978 C 157.765 164.5978 158.574 163.785 159.578 163.785 C 160.582 163.785 161.391 164.5978 161.391 165.5978 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 163.391 165.9136 L 165.391 165.9136 L 218.9765 165.42652 L 272.562 164.93945 L 274.562 164.93945" marker-end="url(#FilledCenterBall_Marker)" marker-start="url(#FilledCenterBall_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
|
||||
<path d="M 190.8749 202.82488 L 246.992 202.3623 L 303.1091 201.89973" marker-end="url(#FilledCenterBall_Marker)" marker-start="url(#FilledCenterBall_Marker_2)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
|
||||
<path d="M 162.704 239.6256 C 162.704 240.6296 161.895 241.4376 160.891 241.4376 C 159.887 241.4376 159.078 240.6296 159.078 239.6256 C 159.078 238.6256 159.887 237.8128 160.891 237.8128 C 161.895 237.8128 162.704 238.6256 162.704 239.6256 Z" fill="black"/>
|
||||
<path d="M 162.704 239.6256 C 162.704 240.6296 161.895 241.4376 160.891 241.4376 C 159.887 241.4376 159.078 240.6296 159.078 239.6256 C 159.078 238.6256 159.887 237.8128 160.891 237.8128 C 161.895 237.8128 162.704 238.6256 162.704 239.6256 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
<path d="M 309.688 240.0294 C 309.688 241.0334 308.879 241.8414 307.875 241.8414 C 306.871 241.8414 306.062 241.0334 306.062 240.0294 C 306.062 239.0294 306.871 238.2166 307.875 238.2166 C 308.879 238.2166 309.688 239.0294 309.688 240.0294 Z" fill="black"/>
|
||||
<path d="M 309.688 240.0294 C 309.688 241.0334 308.879 241.8414 307.875 241.8414 C 306.871 241.8414 306.062 241.0334 306.062 240.0294 C 306.062 239.0294 306.871 238.2166 307.875 238.2166 C 308.879 238.2166 309.688 239.0294 309.688 240.0294 Z" stroke="black" stroke-linecap="round" stroke-linejoin="miter" stroke-width="1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 414 KiB |
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="112" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="112" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h71v20H0z"/><path fill="#007ec6" d="M71 0h41v20H71z"/><path fill="url(#b)" d="M0 0h112v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><text x="365" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="610">download </text><text x="365" y="140" transform="scale(.1)" textLength="610">download </text><text x="905" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="310">latest</text><text x="905" y="140" transform="scale(.1)" textLength="310">latest</text></g> </svg>
|
||||
|
After Width: | Height: | Size: 1004 B |
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="136" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="136" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h51v20H0z"/><path fill="#007ec6" d="M51 0h85v20H51z"/><path fill="url(#b)" d="M0 0h136v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="265" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">License</text><text x="265" y="140" transform="scale(.1)" textLength="410">License</text><text x="925" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="750">BSD 3-Clause</text><text x="925" y="140" transform="scale(.1)" textLength="750">BSD 3-Clause</text></g> </svg>
|
||||
|
After Width: | Height: | Size: 971 B |
Loading…
Reference in New Issue