├── .github └── workflows │ ├── licensing.yml │ └── tests.yml ├── .gitignore ├── .gitmodules ├── .readthedocs.yml ├── AUTHORS ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.rst ├── carry4-flatten.svg ├── compat ├── README.rst ├── setup.py └── sphinxcontrib_verilog_diagrams │ └── __init__.py ├── docs ├── .gitignore ├── Makefile ├── _static │ └── .keepme ├── code │ ├── nmigen │ │ └── counter.py │ ├── rtlil │ │ └── counter.il │ └── verilog │ │ ├── adder.v │ │ ├── carry4-bits.v │ │ ├── carry4-whole.v │ │ ├── counter.v │ │ ├── dff.v │ │ ├── lut4.v │ │ ├── lutff.v │ │ ├── muxcy.v │ │ └── xorcy.v ├── conf.py ├── directives │ ├── hdl-diagram.rst │ ├── index.rst │ └── no-license.rst ├── examples │ ├── carry4.rst │ ├── comb-full-adder.rst │ └── index.rst ├── index.rst └── requirements.txt ├── environment.yml ├── requirements.txt ├── setup.py ├── sphinxcontrib_hdl_diagrams └── __init__.py └── tests ├── Makefile ├── code ├── nmigen │ └── counter.py ├── rtlil │ └── counter.il └── verilog │ ├── adder.v │ ├── fullAdder.v │ └── halfAdder.v ├── conf.py.template ├── test.py ├── test_compat └── test_compat.rst ├── test_flatten └── test_flatten.rst ├── test_nmigen └── test_nmigen.rst ├── test_rtlil └── test_rtlil.rst ├── test_skins ├── skin-purple.svg ├── skin-yellow.svg └── test_skins.rst ├── test_yosys_script ├── test_yosys_script.rst ├── yosys_script.ys └── yosys_script2.ys └── test_yosys_type ├── test_yosys_path.rst ├── test_yosys_system.rst └── test_yosys_yowasp.rst /.github/workflows/licensing.yml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | 18 | name: Licensing 19 | 20 | 21 | on: 22 | push: 23 | pull_request: 24 | 25 | 26 | jobs: 27 | Checks: 28 | runs-on: ubuntu-latest 29 | steps: 30 | - uses: actions/checkout@v2 31 | with: 32 | submodules: recursive 33 | 34 | - uses: SymbiFlow/actions/checks@main 35 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name: CI 18 | 19 | on: 20 | push: 21 | pull_request: 22 | # Run CI daily even without code changes to ensure tests pass with 23 | # updated dependencies. See: 24 | # * https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#scheduled-events 25 | # * https://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab.html#tag_20_25_07 26 | schedule: 27 | - cron: '0 0 * * *' 28 | # Allow triggering a CI run from the web UI. See: 29 | # * https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow 30 | # * https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/ 31 | workflow_dispatch: 32 | 33 | jobs: 34 | 35 | build: 36 | strategy: 37 | fail-fast: false 38 | runs-on: ubuntu-latest 39 | steps: 40 | 41 | - name: 🧰 Repository Checkout 42 | uses: actions/checkout@v2 43 | with: 44 | fetch-depth: 0 # Get complete history 45 | 46 | - name: 🛠️ Install dependencies 47 | run: | 48 | make env 49 | make version 50 | 51 | - name: "Test :skin: option" 52 | run: | 53 | source env/conda/bin/activate sphinxcontrib-hdl-diagrams 54 | cd tests 55 | python -m unittest test.TestSkins 56 | 57 | - name: "Test :yosys_script: option" 58 | run: | 59 | source env/conda/bin/activate sphinxcontrib-hdl-diagrams 60 | cd tests 61 | python3 -m unittest test.TestYosysScript 62 | 63 | - name: "Test :flatten: option" 64 | run: | 65 | source env/conda/bin/activate sphinxcontrib-hdl-diagrams 66 | cd tests 67 | python3 -m unittest test.TestFlatten 68 | 69 | - name: "Test verilog_diagram_yosys config variable" 70 | run: | 71 | source env/conda/bin/activate sphinxcontrib-hdl-diagrams 72 | cd tests 73 | python3 -m unittest test.TestYosysType 74 | 75 | - name: "Test nMigen input format" 76 | run: | 77 | source env/conda/bin/activate sphinxcontrib-hdl-diagrams 78 | cd tests 79 | python3 -m unittest test.TestNMigen 80 | 81 | - name: "Test RTLIL input format" 82 | run: | 83 | source env/conda/bin/activate sphinxcontrib-hdl-diagrams 84 | cd tests 85 | python3 -m unittest test.TestRTLIL 86 | 87 | - name: "Test compatibility package" 88 | run: | 89 | source env/conda/bin/activate sphinxcontrib-hdl-diagrams 90 | cd tests 91 | python3 -m unittest test.TestCompat 92 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # version number 107 | sphinxcontrib_hdl_diagrams/version.py 108 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third_party/make-env"] 2 | path = third_party/make-env 3 | url = https://github.com/SymbiFlow/make-env.git 4 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | # .readthedocs.yml 18 | # Read the Docs configuration file 19 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 20 | 21 | # Required 22 | version: 2 23 | 24 | # Build documentation in the docs/ directory with Sphinx 25 | sphinx: 26 | configuration: docs/conf.py 27 | fail_on_warning: true 28 | 29 | formats: 30 | - htmlzip 31 | 32 | build: 33 | os: ubuntu-22.04 34 | tools: 35 | python: "mambaforge-22.9" 36 | 37 | conda: 38 | environment: environment.yml 39 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the list of Symbiflow's significant contributors. 2 | # 3 | # This does not necessarily list everyone who has contributed code, 4 | # especially since many employees of one corporation may be contributing. 5 | # To see the full list of contributors, see the revision history in 6 | # source control. 7 | 8 | Tim 'mithro' Ansell 9 | Daniel Lim Wee Soong 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | include LICENSE 3 | 4 | recursive-exclude * __pycache__ 5 | recursive-exclude * *.py[co] 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | # The top directory where environment will be created. 18 | TOP_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) 19 | 20 | # A pip `requirements.txt` file. 21 | # https://pip.pypa.io/en/stable/reference/pip_install/#requirements-file-format 22 | REQUIREMENTS_FILE := requirements.txt 23 | 24 | # A conda `environment.yml` file. 25 | # https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html 26 | ENVIRONMENT_FILE := environment.yml 27 | 28 | # Rule to checkout the git submodule if it wasn't cloned. 29 | $(TOP_DIR)/third_party/make-env/conda.mk: $(TOP_DIR)/.gitmodules 30 | cd $(TOP_DIR); git submodule update --init third_party/make-env 31 | touch $(TOP_DIR)/third_party/make-env/conda.mk 32 | 33 | -include $(TOP_DIR)/third_party/make-env/conda.mk 34 | 35 | # Create a version.py file 36 | VERSION_PY = sphinxcontrib_hdl_diagrams/version.py 37 | $(VERSION_PY): 38 | @echo "__version__ = '$$(git describe | sed -e's/v\([0-9]\+\)\.\([0-9]\+\)-\([0-9]\+\)-g[0-9a-f]\+/\1.\2.post\3/')'" > $@ 39 | 40 | .PHONY: $(VERSION_PY) 41 | 42 | version: 43 | @if $$(git rev-parse --is-shallow-repository); then git fetch --unshallow; fi 44 | git fetch origin --tags 45 | @$(MAKE) $(VERSION_PY) 46 | @cat $(VERSION_PY) 47 | 48 | version-clean: 49 | rm -f $(VERSION_PY) 50 | 51 | .PHONY: version-clean 52 | 53 | clean:: version-clean 54 | 55 | # Build the package locally 56 | # ------------------------------------- 57 | 58 | build: $(VERSION_PY) | $(CONDA_ENV_PYTHON) 59 | $(IN_CONDA_ENV) python setup.py sdist bdist_wheel && twine check dist/* 60 | 61 | build-clean: 62 | rm -rf env/downloads/conda-pkgs 63 | rm -rf build dist *.egg-info 64 | find -name *.pyc -delete 65 | find -name __pycache__ -delete 66 | 67 | .PHONY: build build-clean 68 | 69 | clean:: build-clean 70 | 71 | # Upload the package to PyPi 72 | # ------------------------------------- 73 | 74 | #PYPI_TEST = --repository-url https://test.pypi.org/legacy/ 75 | #PYPI_TEST = --repository testpypi 76 | 77 | upload-test: build | $(CONDA_ENV_PYTHON) 78 | $(IN_CONDA_ENV) twine upload ${PYPI_TEST} dist/* 79 | 80 | .PHONY: upload-test 81 | 82 | upload: build | $(CONDA_ENV_PYTHON) 83 | $(IN_CONDA_ENV) twine upload --verbose dist/* 84 | 85 | .PHONY: upload 86 | 87 | # Tests 88 | # ------------------------------------- 89 | 90 | test: $(VERSION_PY) | $(CONDA_ENV_PYTHON) 91 | $(IN_CONDA_ENV) cd docs; make html 92 | $(IN_CONDA_ENV) cd tests; make test 93 | 94 | .PHONY: test 95 | 96 | # Build and upload compatibility package 97 | # ------------------------------------- 98 | 99 | COMPAT_PACKAGE_DIR = compat 100 | 101 | build_compat: $(VERSION_PY) | $(CONDA_ENV_PYTHON) 102 | $(IN_CONDA_ENV) cd $(COMPAT_PACKAGE_DIR); python setup.py sdist bdist_wheel && twine check dist/* 103 | 104 | build_compat-clean: 105 | cd $(COMPAT_PACKAGE_DIR); rm -rf env/downloads/conda-pkgs 106 | cd $(COMPAT_PACKAGE_DIR); rm -rf build dist *.egg-info 107 | cd $(COMPAT_PACKAGE_DIR); find -name *.pyc -delete 108 | cd $(COMPAT_PACKAGE_DIR); find -name __pycache__ -delete 109 | 110 | .PHONY: build_compat build_compat-clean 111 | 112 | clean:: build_compat-clean 113 | 114 | upload_compat-test: build_compat | $(CONDA_ENV_PYTHON) 115 | $(IN_CONDA_ENV) cd $(COMPAT_PACKAGE_DIR); twine upload ${PYPI_TEST} dist/* 116 | 117 | upload_compat: build_compat | $(CONDA_ENV_PYTHON) 118 | $(IN_CONDA_ENV) cd $(COMPAT_PACKAGE_DIR); twine upload --verbose dist/* 119 | 120 | .PHONY: upload_compat-test upload_compat 121 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | sphinxcontrib-hdl-diagrams 2 | ============================== 3 | 4 | 5 | .. image:: https://img.shields.io/pypi/v/sphinxcontrib-hdl-diagrams.svg 6 | :target: https://pypi.python.org/pypi/sphinxcontrib-hdl-diagrams 7 | :alt: PyPI 8 | 9 | 10 | .. image:: https://img.shields.io/pypi/pyversions/sphinxcontrib-hdl-diagrams.svg 11 | :target: https://pypi.python.org/pypi/sphinxcontrib-hdl-diagrams 12 | :alt: PyPI version 13 | 14 | 15 | .. image:: https://readthedocs.org/projects/sphinxcontrib-hdl-diagrams/badge 16 | :target: https://sphinxcontrib-hdl-diagrams.readthedocs.io/en/latest/ 17 | :alt: Documentation 18 | 19 | 20 | .. image:: https://travis-ci.com/SymbiFlow/sphinxcontrib-hdl-diagrams.svg?branch=master 21 | :target: https://travis-ci.com/SymbiFlow/sphinxcontrib-hdl-diagrams 22 | :alt: Build Status 23 | 24 | 25 | .. image:: https://codecov.io/gh/SymbiFlow/sphinxcontrib-hdl-diagrams/branch/master/graph/badge.svg 26 | :target: https://codecov.io/gh/SymbiFlow/sphinxcontrib-hdl-diagrams 27 | :alt: codecov 28 | 29 | 30 | ---- 31 | 32 | Sphinx Extension which generates various types of diagrams from HDL code, supporting Verilog, 33 | nMigen and RTLIL. 34 | 35 | `sphinxcontrib-hdl-diagrams `_ 36 | is a Sphinx extension to make it easier to write nice documentation from 37 | HDL source files. It primarily uses `Yosys `_ to read the source files 38 | and generate the diagrams. 39 | 40 | Check out the `documentation `_ for examples. 41 | 42 | Installation 43 | ------------ 44 | 45 | Python 3.5+ is required. 46 | 47 | .. code-block:: 48 | 49 | pip install sphinxcontrib-hdl-diagrams 50 | 51 | Or, 52 | 53 | .. code-block:: 54 | 55 | python3 -m pip install sphinxcontrib-hdl-diagrams 56 | 57 | Sphinx Integration 58 | ^^^^^^^^^^^^^^^^^^ 59 | 60 | In your conf.py, add the following lines. 61 | 62 | .. code-block:: python 63 | 64 | extensions = [ 65 | ..., 66 | 'sphinxcontrib_hdl_diagrams', 67 | ] 68 | 69 | Non-Python Dependencies 70 | ^^^^^^^^^^^^^^^^^^^^^^^ 71 | 72 | These dependencies can be either installed on your system or install using the 73 | conda ``environment.yml`` file with; 74 | 75 | .. code-block:: bash 76 | 77 | conda XXXX 78 | 79 | Required 80 | ~~~~~~~~ 81 | 82 | * |yosys|_ 83 | 84 | .. |yosys| replace:: ``yosys`` 85 | .. _yosys: https://github.com/YosysHQ/yosys 86 | 87 | By default, ``verilog-diagram`` uses the ``yowasp-yosys`` package provided in PyPI. 88 | It can be installed by running ``pip install -r requirements.txt``. 89 | However, you could also use Yosys that is installed on your system, 90 | or point to the specific Yosys binary using ``verilog_diagram_yosys`` variable 91 | in the Sphinx ``conf.py`` file: 92 | 93 | To use Yosys that is available in your system, use the following setting:: 94 | 95 | verilog_diagram_yosys = "system" 96 | 97 | If you want to point to the specific Yosys binary, provide the path to the program:: 98 | 99 | verilog_diagram_yosys = "" 100 | 101 | Optional 102 | ~~~~~~~~ 103 | 104 | * |netlistsvg|_ 105 | 106 | .. |netlistsvg| replace:: ``netlistsvg`` 107 | .. _netlistsvg: https://github.com/nturley/netlistsvg 108 | 109 | Usage 110 | ----- 111 | 112 | ``hdl-diagram`` 113 | ^^^^^^^^^^^^^^^^^^^ 114 | 115 | The ``hdl-diagram`` RST directive can be used to generate a diagram from Verilog code and include it in your documentation. 116 | Check out the `examples `_ to see how to use it. 117 | 118 | .. code-block:: rst 119 | 120 | .. hdl-diagram:: file.v 121 | :type: XXXXX 122 | :module: XXXX 123 | :skin: XXXX 124 | :yosys_script: XXXX 125 | :flatten: 126 | 127 | Options 128 | ~~~~~~~ 129 | 130 | ``:type:`` - HDL Diagram Types; 131 | 132 | 133 | * ``yosys-blackbox`` - Netlist rendered by Yosys. 134 | * ``yosys-aig`` - Verilog file run through ``aigmap`` before image is generated directly in Yosys. 135 | * ``netlistsvg`` - Render output with `netlistsvg `_ 136 | 137 | ``:module:`` - Which module to diagram. 138 | 139 | ``:flatten:`` - Use the Yosys ``flatten`` command before generating the image. 140 | 141 | Example 142 | ~~~~~~~ 143 | 144 | Here is a diagram of a 4-bit carry chain. 145 | 146 | 147 | .. image:: ./carry4-flatten.svg 148 | :target: ./carry4-flatten.svg 149 | :alt: 4-bit carry chain 150 | 151 | 152 | ``no-license`` 153 | ^^^^^^^^^^^^^^ 154 | 155 | This extension also provides the ``no-license`` directive which can be used to include code blocks from a file, but omitting the license header 156 | at the top of the file. It behaves like the ``literalinclude`` directive, but the ``lines`` option is overridden to only show the lines after the license header. 157 | 158 | .. code-block:: rst 159 | 160 | 161 | .. no-license:: verilog/dff.v 162 | :language: verilog 163 | :linenos: 164 | :caption: verilog/dff.v 165 | 166 | Example 167 | ~~~~~~~ 168 | 169 | Here is a comparison between the ``literalinclude`` and ``no-license`` directives. 170 | 171 | .. code-block:: rst 172 | 173 | .. literalinclude:: verilog/dff.v 174 | :language: verilog 175 | :caption: verilog/dff.v 176 | 177 | .. code-block:: verilog 178 | 179 | /* 180 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 181 | * 182 | * Licensed under the Apache License, Version 2.0 (the "License"); 183 | * you may not use this file except in compliance with the License. 184 | * You may obtain a copy of the License at 185 | * 186 | * https://www.apache.org/licenses/LICENSE-2.0 187 | * 188 | * Unless required by applicable law or agreed to in writing, software 189 | * distributed under the License is distributed on an "AS IS" BASIS, 190 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 191 | * See the License for the specific language governing permissions and 192 | * limitations under the License. 193 | * 194 | * SPDX-License-Identifier: Apache-2.0 195 | */ 196 | 197 | // Single flip-flip test. 198 | module top(input clk, input di, output do); 199 | always @( posedge clk ) 200 | do <= di; 201 | endmodule // top 202 | 203 | .. code-block:: rst 204 | 205 | .. no-license:: verilog/dff.v 206 | :language: verilog 207 | :caption: verilog/dff.v 208 | 209 | .. code-block:: verilog 210 | 211 | // Single flip-flip test. 212 | module top(input clk, input di, output do); 213 | always @( posedge clk ) 214 | do <= di; 215 | endmodule // top 216 | 217 | Licence 218 | ------- 219 | 220 | `Apache 2.0 `_ 221 | -------------------------------------------------------------------------------- /carry4-flatten.svg: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | CO 114 | 115 | 116 | 117 | 118 | 119 | O 120 | 121 | 122 | 123 | 124 | 125 | CI 126 | 127 | 128 | 129 | 130 | 131 | CYINIT 132 | 133 | 134 | 135 | 136 | 137 | DI 138 | 139 | 140 | 141 | 142 | 143 | S 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 0 154 | 155 | 156 | 1 157 | 158 | 159 | 2 160 | 161 | 162 | 3 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 0 171 | 172 | 173 | 1 174 | 175 | 176 | 2 177 | 178 | 179 | 3 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 0 188 | 189 | 190 | 1 191 | 192 | 193 | 2 194 | 195 | 196 | 3 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 0 205 | 206 | 207 | 1 208 | 209 | 210 | 2 211 | 212 | 213 | 3 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | -------------------------------------------------------------------------------- /compat/README.rst: -------------------------------------------------------------------------------- 1 | ``sphinxcontrib-hdl-diagrams`` replaces ``sphinxcontrib-verilog-diagrams`` 2 | ========================================================================== 3 | 4 | sphinxcontrib-verilog-diagrams was renamed to 5 | `sphinxcontrib-hdl-diagrams `_ 6 | as it now supports more langauges than just verilog! 7 | 8 | This stub module remains for backwards compatibility, but you should update to 9 | using the new name. 10 | -------------------------------------------------------------------------------- /compat/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | 20 | import sys 21 | from os import path 22 | 23 | from setuptools import setup, find_packages 24 | 25 | __dir__ = path.dirname(path.abspath(__file__)) 26 | readme_file = path.join(__dir__, 'README.rst') 27 | try: 28 | with open(readme_file) as f: 29 | readme = f.read() 30 | except FileNotFoundError as e: 31 | import traceback 32 | traceback.print_exc() 33 | readme = '' 34 | __version__ = 'error' 35 | 36 | install_requires = [ 37 | 'sphinxcontrib-hdl-diagrams' 38 | ] 39 | 40 | setup( 41 | name='sphinxcontrib-verilog-diagrams', 42 | version="0.1.1", 43 | description='Compatibility stub for renamed to sphinxcontrib-hdl-diagrams.', 44 | long_description=readme, 45 | long_description_content_type="text/x-rst", 46 | author="The SymbiFlow Authors", 47 | author_email='symbiflow@lists.librecores.org', 48 | url='https://github.com/SymbiFlow/sphinxcontrib-hdl-diagrams', 49 | packages=find_packages(), 50 | license="Apache 2.0", 51 | keywords='', 52 | classifiers=[], 53 | install_requires=install_requires, 54 | ) 55 | -------------------------------------------------------------------------------- /compat/sphinxcontrib_verilog_diagrams/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | 20 | import warnings 21 | import sphinxcontrib_hdl_diagrams 22 | 23 | def setup(app): 24 | deprecation_msg = """ 25 | sphinxcontrib-verilog-diagram extension is depreciated! 26 | Please use sphinxcontrib-hdl-diagrams instead: 27 | https://github.com/SymbiFlow/sphinxcontrib-hdl-diagrams""" 28 | warnings.warn(deprecation_msg, DeprecationWarning) 29 | 30 | return sphinxcontrib_hdl_diagrams.setup(app) 31 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | env 2 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | # 17 | # Minimal makefile for Sphinx documentation 18 | 19 | MAKEDIR := $(dir $(lastword $(MAKEFILE_LIST))) 20 | 21 | # You can set these variables from the command line. 22 | SPHINXOPTS = 23 | SPHINXBUILD = [ -e env/bin/activate ] && source env/bin/activate; sphinx-build 24 | SPHINXAUTOBUILD = [ -e env/bin/activate ] && source env/bin/activate; sphinx-autobuild 25 | SPHINXPROJ = SphinxContribHDLDiagramsDocs 26 | SOURCEDIR = . 27 | BUILDDIR = _build 28 | 29 | # Put it first so that "make" without argument is like "make help". 30 | help: 31 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 32 | 33 | livehtml: 34 | @$(SPHINXAUTOBUILD) -b html --ignore \*.swp --ignore \*~ $(SPHINXOPTS) "$(SOURCEDIR)" "$(BUILDDIR)/html" 35 | 36 | .PHONY: help livehtml Makefile 37 | 38 | 39 | env/Miniconda3-latest-Linux-x86_64.sh: 40 | mkdir env 41 | wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O env/Miniconda3-latest-Linux-x86_64.sh 42 | chmod a+x env/Miniconda3-latest-Linux-x86_64.sh 43 | 44 | env: 45 | rm -rf env 46 | make env/Miniconda3-latest-Linux-x86_64.sh 47 | ./env/Miniconda3-latest-Linux-x86_64.sh -p $(PWD)/env -b -f 48 | source env/bin/activate; conda config --system --add envs_dirs $(PWD)/env/envs 49 | source env/bin/activate; conda config --system --add pkgs_dirs $(PWD)/env/pkgs 50 | source env/bin/activate; conda env update --name base --file ../environment.yml 51 | 52 | .PHONY: env 53 | 54 | # Catch-all target: route all unknown targets to Sphinx using the new 55 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 56 | %: Makefile 57 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 58 | -------------------------------------------------------------------------------- /docs/_static/.keepme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SymbiFlow/sphinxcontrib-hdl-diagrams/5166ade92cb855d87c34fd713b8f489e7dd04561/docs/_static/.keepme -------------------------------------------------------------------------------- /docs/code/nmigen/counter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | 20 | 21 | from nmigen import * 22 | from nmigen.back import rtlil 23 | 24 | 25 | class Counter(Elaboratable): 26 | def __init__(self, width): 27 | self.v = Signal(width, reset=2**width-1) 28 | self.o = Signal() 29 | 30 | def elaborate(self, platform): 31 | m = Module() 32 | m.d.sync += self.v.eq(self.v + 1) 33 | m.d.comb += self.o.eq(self.v[-1]) 34 | return m 35 | 36 | 37 | ctr = Counter(width=16) 38 | print(rtlil.convert(ctr, ports=[ctr.o])) 39 | -------------------------------------------------------------------------------- /docs/code/rtlil/counter.il: -------------------------------------------------------------------------------- 1 | attribute \generator "nMigen" 2 | attribute \top 1 3 | attribute \nmigen.hierarchy "top" 4 | module \top 5 | attribute \src "counter.py:9" 6 | wire width 1 output 0 \o 7 | attribute \src "/usr/local/lib/python3.7/site-packages/nmigen/hdl/ir.py:526" 8 | wire width 1 input 1 \clk 9 | attribute \src "/usr/local/lib/python3.7/site-packages/nmigen/hdl/ir.py:526" 10 | wire width 1 input 2 \rst 11 | attribute \src "counter.py:8" 12 | wire width 16 \v 13 | attribute \src "counter.py:8" 14 | wire width 16 \v$next 15 | attribute \src "counter.py:13" 16 | wire width 17 $1 17 | attribute \src "counter.py:13" 18 | wire width 17 $2 19 | attribute \src "counter.py:13" 20 | cell $add $3 21 | parameter \A_SIGNED 1'0 22 | parameter \A_WIDTH 5'10000 23 | parameter \B_SIGNED 1'0 24 | parameter \B_WIDTH 1'1 25 | parameter \Y_WIDTH 5'10001 26 | connect \A \v 27 | connect \B 1'1 28 | connect \Y $2 29 | end 30 | connect $1 $2 31 | process $group_0 32 | assign \v$next \v 33 | assign \v$next $1 [15:0] 34 | attribute \src "/usr/local/lib/python3.7/site-packages/nmigen/hdl/xfrm.py:530" 35 | switch \rst 36 | case 1'1 37 | assign \v$next 16'1111111111111111 38 | end 39 | sync init 40 | update \v 16'1111111111111111 41 | sync posedge \clk 42 | update \v \v$next 43 | end 44 | process $group_1 45 | assign \o 1'0 46 | assign \o \v [15] 47 | sync init 48 | end 49 | end 50 | 51 | -------------------------------------------------------------------------------- /docs/code/verilog/adder.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | module ADDER ( 20 | a, b, cin, 21 | sum, cout 22 | ); 23 | input wire a; 24 | input wire b; 25 | input wire cin; 26 | 27 | output wire sum; 28 | output wire cout; 29 | 30 | // Full adder combinational logic 31 | assign sum = a ^ b ^ cin; 32 | assign cout = ((a ^ b) & cin) | (a & b); 33 | endmodule 34 | -------------------------------------------------------------------------------- /docs/code/verilog/carry4-bits.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | `include "muxcy.v" 20 | `include "xorcy.v" 21 | 22 | module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); 23 | wire CIN = CI | CYINIT; 24 | 25 | MUXCY muxcy0 (.O(CO[0]), .CI(CIN), .DI(DI[0]), .S(S[0])); 26 | MUXCY muxcy1 (.O(CO[1]), .CI(CO[0]), .DI(DI[1]), .S(S[1])); 27 | MUXCY muxcy2 (.O(CO[2]), .CI(CO[1]), .DI(DI[2]), .S(S[2])); 28 | MUXCY muxcy3 (.O(CO[3]), .CI(CO[2]), .DI(DI[3]), .S(S[3])); 29 | 30 | XORCY xorcy0 (.O(O[0]), .CI(CIN), .LI(S[0])); 31 | XORCY xorcy1 (.O(O[1]), .CI(CO[0]), .LI(S[1])); 32 | XORCY xorcy2 (.O(O[2]), .CI(CO[1]), .LI(S[2])); 33 | XORCY xorcy3 (.O(O[3]), .CI(CO[2]), .LI(S[3])); 34 | endmodule 35 | -------------------------------------------------------------------------------- /docs/code/verilog/carry4-whole.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); 20 | assign O = S ^ {CO[2:0], CI | CYINIT}; 21 | assign CO[0] = S[0] ? CI | CYINIT : DI[0]; 22 | assign CO[1] = S[1] ? CO[0] : DI[1]; 23 | assign CO[2] = S[2] ? CO[1] : DI[2]; 24 | assign CO[3] = S[3] ? CO[2] : DI[3]; 25 | endmodule 26 | -------------------------------------------------------------------------------- /docs/code/verilog/counter.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | module top ( 20 | input clk, 21 | output o 22 | ); 23 | reg [2:0] counter = 0; 24 | always @(posedge clk) 25 | counter <= counter + 1; 26 | assign o = counter[2]; 27 | endmodule 28 | -------------------------------------------------------------------------------- /docs/code/verilog/dff.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | // Single flip-flip test. 20 | module top(input clk, input di, output do); 21 | always @( posedge clk ) 22 | do <= di; 23 | endmodule // top 24 | -------------------------------------------------------------------------------- /docs/code/verilog/lut4.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | // 4-input LUT test. 20 | module top(input [3:0] I, output O); 21 | always @(I) 22 | case(I) 23 | 4'b0000 : O = 1; 24 | 4'b1000 : O = 1; 25 | 4'b1100 : O = 1; 26 | 4'b1010 : O = 1; 27 | 4'b1001 : O = 1; 28 | 4'b1111 : O = 1; 29 | default : O = 0; 30 | endcase 31 | endmodule // top 32 | -------------------------------------------------------------------------------- /docs/code/verilog/lutff.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | module top ( 20 | input clk, 21 | input [3:0] i, 22 | output reg o 23 | ); 24 | always @(posedge clk) 25 | o <= ^i; 26 | endmodule 27 | -------------------------------------------------------------------------------- /docs/code/verilog/muxcy.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | module MUXCY(output O, input CI, DI, S); 20 | assign O = S ? CI : DI; 21 | endmodule 22 | -------------------------------------------------------------------------------- /docs/code/verilog/xorcy.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | module XORCY(output O, input CI, LI); 20 | assign O = CI ^ LI; 21 | endmodule 22 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | # Sphinx HDL Diagrams documentation build configuration file, created by 21 | # sphinx-quickstart on Mon Feb 5 11:04:37 2018. 22 | # 23 | # This file is execfile()d with the current directory set to its 24 | # containing dir. 25 | # 26 | # Note that not all possible configuration values are present in this 27 | # autogenerated file. 28 | # 29 | # All configuration values have a default; values that are commented out 30 | # serve to show the default. 31 | 32 | import re 33 | 34 | # If extensions (or modules to document with autodoc) are in another directory, 35 | # add these directories to sys.path here. If the directory is relative to the 36 | # documentation root, use os.path.abspath to make it absolute, like shown here. 37 | # 38 | import os 39 | import sys 40 | sys.path.insert(0, os.path.abspath('..')) 41 | 42 | # -- General configuration ------------------------------------------------ 43 | 44 | # If your documentation needs a minimal Sphinx version, state it here. 45 | # 46 | # needs_sphinx = '1.0' 47 | 48 | # Add any Sphinx extension module names here, as strings. They can be 49 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 50 | # ones. 51 | extensions = [ 52 | 'sphinx.ext.autodoc', 53 | 'sphinx.ext.autosummary', 54 | 'sphinx.ext.doctest', 55 | 'sphinx.ext.imgmath', 56 | 'sphinx.ext.napoleon', 57 | 'sphinx.ext.todo', 58 | 'sphinxcontrib_hdl_diagrams', 59 | ] 60 | 61 | # Add any paths that contain templates here, relative to this directory. 62 | templates_path = ['_templates'] 63 | 64 | # The suffix(es) of source filenames. 65 | # You can specify multiple suffix as a list of string: 66 | source_suffix = ['.rst'] 67 | 68 | # The master toctree document. 69 | master_doc = 'index' 70 | 71 | # General information about the project. 72 | project = u'Sphinx HDL Diagrams' 73 | copyright = u'2018, SymbiFlow Team' 74 | author = u'SymbiFlow Team' 75 | 76 | # Enable github links when not on readthedocs 77 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 78 | if not on_rtd: 79 | html_context = { 80 | "display_github": True, # Integrate GitHub 81 | "github_user": "SymbiFlow", # Username 82 | "github_repo": "sphinxcontrib-hdl-diagrams", # Repo name 83 | "github_version": "master", # Version 84 | "conf_py_path": "/doc/", 85 | } 86 | else: 87 | docs_dir = os.path.abspath(os.path.dirname(__file__)) 88 | print("Docs dir is:", docs_dir) 89 | import subprocess 90 | subprocess.call('git fetch origin --unshallow', cwd=docs_dir, shell=True) 91 | subprocess.check_call('git fetch origin --tags', cwd=docs_dir, shell=True) 92 | 93 | # The version info for the project you're documenting, acts as replacement for 94 | # |version| and |release|, also used in various other places throughout the 95 | # built documents. 96 | # 97 | # The full version, including alpha/beta/rc tags. 98 | release = re.sub('^v', '', os.popen('git describe ').read().strip()) 99 | # The short X.Y version. 100 | version = release 101 | 102 | # The language for content autogenerated by Sphinx. Refer to documentation 103 | # for a list of supported languages. 104 | # 105 | # This is also used if you do content translation via gettext catalogs. 106 | # Usually you set "language" from the command line for these cases. 107 | language = 'en' 108 | 109 | # List of patterns, relative to source directory, that match files and 110 | # directories to ignore when looking for source files. 111 | # This patterns also effect to html_static_path and html_extra_path 112 | exclude_patterns = ['_build', 'env', 'Thumbs.db', '.DS_Store'] 113 | 114 | # The name of the Pygments (syntax highlighting) style to use. 115 | pygments_style = 'default' 116 | 117 | # If true, `todo` and `todoList` produce output, else they produce nothing. 118 | todo_include_todos = True 119 | 120 | # -- Options for HTML output ---------------------------------------------- 121 | 122 | # The theme to use for HTML and HTML Help pages. See the documentation for 123 | # a list of builtin themes. 124 | # 125 | html_theme = 'sphinx_symbiflow_theme' 126 | 127 | # Theme options are theme-specific and customize the look and feel of a theme 128 | # further. For a list of options available for each theme, see the 129 | # documentation. 130 | # 131 | html_theme_options = { 132 | # Customize css colors. 133 | # 134 | # Primary colors: 135 | # red, pink, purple, deep-purple, indigo, blue, light-blue, cyan, 136 | # teal, green, light-green, lime, yellow, amber, orange, deep-orange, 137 | # brown, grey, blue-grey, white 138 | 'color_primary': 'deep-purple', 139 | 140 | # Accent colors: 141 | # red, pink, purple, deep-purple, indigo, blue, light-blue, cyan, 142 | # teal, green, light-green, lime, yellow, amber, orange, deep-orange 143 | 'color_accent': 'indigo', 144 | } 145 | 146 | # Add any paths that contain custom static files (such as style sheets) here, 147 | # relative to this directory. They are copied after the builtin static files, 148 | # so a file named "default.css" will overwrite the builtin "default.css". 149 | html_static_path = ['_static'] 150 | 151 | # -- Options for HTMLHelp output ------------------------------------------ 152 | 153 | # Output file base name for HTML help builder. 154 | htmlhelp_basename = 'sphinxcontrib-hdl-diagrams' 155 | 156 | # -- Options for LaTeX output --------------------------------------------- 157 | 158 | latex_elements = { 159 | # The paper size ('letterpaper' or 'a4paper'). 160 | # 161 | # 'papersize': 'letterpaper', 162 | 163 | # The font size ('10pt', '11pt' or '12pt'). 164 | # 165 | # 'pointsize': '10pt', 166 | 167 | # Additional stuff for the LaTeX preamble. 168 | # 169 | # 'preamble': '', 170 | 171 | # Latex figure (float) alignment 172 | # 173 | # 'figure_align': 'htbp', 174 | } 175 | 176 | # Grouping the document tree into LaTeX files. List of tuples 177 | # (source start file, target name, title, 178 | # author, documentclass [howto, manual, or own class]). 179 | latex_documents = [ 180 | ( 181 | master_doc, 'SphinxHDLDiagrams.tex', 182 | u'Sphinx HDL Diagram Documentation', u'SymbiFlow Team', 'manual'), 183 | ] 184 | 185 | # -- Options for manual page output --------------------------------------- 186 | 187 | # One entry per manual page. List of tuples 188 | # (source start file, name, description, authors, manual section). 189 | man_pages = [ 190 | (master_doc, 'sphinx-hdl-diagrams', u'Sphinx HDL Diagrams Documentation', 191 | [author], 1) 192 | ] 193 | 194 | # -- Options for Texinfo output ------------------------------------------- 195 | 196 | # Grouping the document tree into Texinfo files. List of tuples 197 | # (source start file, target name, title, author, 198 | # dir menu entry, description, category) 199 | texinfo_documents = [ 200 | ( 201 | master_doc, 'SphinxHDLDiagrams', 202 | u'Sphinx HDL Diagrams Documentation', author, 203 | 'SphinxHDLDiagrams', 'Sphinx Extension which generates various types of diagrams from HDL code.', 204 | 'Miscellaneous'), 205 | ] 206 | 207 | # Example configuration for intersphinx: refer to the Python standard library. 208 | intersphinx_mapping = {'https://docs.python.org/': None} 209 | -------------------------------------------------------------------------------- /docs/directives/hdl-diagram.rst: -------------------------------------------------------------------------------- 1 | hdl-diagram 2 | =========== 3 | 4 | The `hdl-diagram` RST directive can be used to generate a diagram from HDL code and include it in your documentation. 5 | 6 | .. code-block:: rst 7 | 8 | .. hdl-diagram:: file.v 9 | :type: XXXXX 10 | :module: XXXX 11 | :flatten: 12 | 13 | .. note:: 14 | 15 | The `verilog-diagram` directive is kept as an alias of this directive for 16 | compatibility purposes. 17 | 18 | Options 19 | ------- 20 | 21 | `:type:` - Verilog Diagram Types; 22 | 23 | - `yosys-blackbox` - Netlist rendered by Yosys. 24 | - `yosys-aig` - Verilog file run through `aigmap` before image is generated directly in Yosys. 25 | - `netlistsvg` - Render output with `netlistsvg `_ 26 | 27 | `:module:` - Which module to diagram. 28 | 29 | `:flatten:` - Use the Yosys `flatten` command before generating the image. 30 | 31 | Input Formats 32 | ------------- 33 | This directive supports 3 input formats: Verilog code, nMigen code, and RTLIL. 34 | 35 | Verilog 36 | +++++++ 37 | 38 | .. no-license:: ../code/verilog/counter.v 39 | :language: verilog 40 | :linenos: 41 | 42 | .. code-block:: rst 43 | :linenos: 44 | :emphasize-lines: 1 45 | 46 | .. hdl-diagram:: ../code/verilog/counter.v 47 | :type: netlistsvg 48 | 49 | .. hdl-diagram:: ../code/verilog/counter.v 50 | :type: netlistsvg 51 | 52 | 53 | nMigen 54 | ++++++ 55 | 56 | .. no-license:: ../code/nmigen/counter.py 57 | :language: python 58 | :linenos: 59 | :emphasize-lines: 5,17,18 60 | 61 | .. code-block:: rst 62 | :linenos: 63 | :emphasize-lines: 1 64 | 65 | .. hdl-diagram:: ../code/nmigen/counter.py 66 | :type: netlistsvg 67 | 68 | .. hdl-diagram:: ../code/nmigen/counter.py 69 | :type: netlistsvg 70 | 71 | .. note:: 72 | 73 | As `hdl-diagram` expects the nMigen script to write RTLIL code to stdout, 74 | make sure to include the following lines of code. 75 | 76 | .. code-block:: py 77 | :linenos: 78 | 79 | from nmigen.back import rtlil 80 | print(rtlil.convert(..., ports=[...])) 81 | 82 | 83 | RTLIL 84 | +++++ 85 | 86 | .. no-license:: ../code/rtlil/counter.il 87 | :language: text 88 | :linenos: 89 | 90 | .. code-block:: rst 91 | :linenos: 92 | :emphasize-lines: 1 93 | 94 | .. hdl-diagram:: ../code/rtlil/counter.il 95 | :type: netlistsvg 96 | 97 | .. hdl-diagram:: ../code/rtlil/counter.il 98 | :type: netlistsvg 99 | 100 | 101 | Diagram Types 102 | ------------- 103 | 104 | Yosys BlackBox Diagram 105 | ++++++++++++++++++++++ 106 | 107 | RST Directive 108 | ************* 109 | 110 | .. code-block:: rst 111 | :linenos: 112 | :emphasize-lines: 2 113 | 114 | .. hdl-diagram:: ../code/verilog/dff.v 115 | :type: yosys-bb 116 | 117 | Result 118 | ****** 119 | 120 | .. hdl-diagram:: ../code/verilog/dff.v 121 | :type: yosys-bb 122 | 123 | 124 | Yosys AIG Diagram 125 | +++++++++++++++++ 126 | 127 | RST Directive 128 | ************* 129 | 130 | .. code-block:: rst 131 | :linenos: 132 | :emphasize-lines: 2 133 | 134 | .. hdl-diagram:: ../code/verilog/dff.v 135 | :type: yosys-aig 136 | 137 | Result 138 | ****** 139 | 140 | .. hdl-diagram:: ../code/verilog/dff.v 141 | :type: yosys-aig 142 | 143 | 144 | NetlistSVG Diagram 145 | ++++++++++++++++++ 146 | 147 | RST Directive 148 | ************* 149 | 150 | .. code-block:: rst 151 | :linenos: 152 | :emphasize-lines: 2 153 | 154 | .. hdl-diagram:: ../code/verilog/dff.v 155 | :type: netlistsvg 156 | 157 | Result 158 | ****** 159 | 160 | .. hdl-diagram:: ../code/verilog/dff.v 161 | :type: netlistsvg -------------------------------------------------------------------------------- /docs/directives/index.rst: -------------------------------------------------------------------------------- 1 | Directives 2 | ========== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :glob: 7 | 8 | hdl-diagram 9 | no-license 10 | -------------------------------------------------------------------------------- /docs/directives/no-license.rst: -------------------------------------------------------------------------------- 1 | no-license 2 | ========== 3 | 4 | The `no-license` RST directive can be used to include code without license headers. 5 | 6 | .. code-block:: rst 7 | 8 | .. no-license:: file.v 9 | :language: verilog 10 | :linenos: 11 | :caption: examples/verilog/dff.v 12 | 13 | Options 14 | +++++++ 15 | 16 | This directive merely overrides the `lines` and `lineno-start` options of the `literalinclude` directive. 17 | So, refer to `literalinclude` for the available options. 18 | 19 | Example 20 | +++++++ 21 | 22 | Verilog Code Block (with license header) 23 | ---------------------------------------- 24 | 25 | RST Directive 26 | ************* 27 | 28 | .. code-block:: rst 29 | :linenos: 30 | 31 | .. literalinclude:: ../code/verilog/dff.v 32 | :language: verilog 33 | :linenos: 34 | 35 | Result 36 | ****** 37 | 38 | .. literalinclude:: ../code/verilog/dff.v 39 | :language: verilog 40 | :linenos: 41 | 42 | 43 | Verilog Code Block (without license header) 44 | ------------------------------------------- 45 | 46 | RST Directive 47 | ************* 48 | 49 | .. code-block:: rst 50 | :linenos: 51 | 52 | .. no-license:: ../code/verilog/dff.v 53 | :language: verilog 54 | :linenos: 55 | 56 | Result 57 | ****** 58 | 59 | .. no-license:: ../code/verilog/dff.v 60 | :language: verilog 61 | :linenos: 62 | -------------------------------------------------------------------------------- /docs/examples/carry4.rst: -------------------------------------------------------------------------------- 1 | CARRY4 example for Series 7 FPGA 2 | ================================ 3 | 4 | CARRY4 defined directly 5 | +++++++++++++++++++++++ 6 | 7 | .. no-license:: ../code/verilog/carry4-whole.v 8 | :language: verilog 9 | :linenos: 10 | 11 | .. code-block:: rst 12 | :linenos: 13 | 14 | .. hdl-diagram:: ../code/verilog/carry4-whole.v 15 | :type: netlistsvg 16 | :module: CARRY4 17 | 18 | .. hdl-diagram:: ../code/verilog/carry4-whole.v 19 | :type: netlistsvg 20 | :module: CARRY4 21 | 22 | 23 | CARRY4 defined by components 24 | ++++++++++++++++++++++++++++ 25 | 26 | .. no-license:: ../code/verilog/carry4-bits.v 27 | :language: verilog 28 | :linenos: 29 | 30 | 31 | .. no-license:: ../code/verilog/muxcy.v 32 | :language: verilog 33 | :linenos: 34 | 35 | 36 | .. no-license:: ../code/verilog/xorcy.v 37 | :language: verilog 38 | :linenos: 39 | 40 | 41 | MUXCY 42 | ***** 43 | 44 | .. code-block:: rst 45 | :linenos: 46 | 47 | .. hdl-diagram:: ../code/verilog/muxcy.v 48 | :type: netlistsvg 49 | :caption: muxcy.v 50 | :module: MUXCY 51 | 52 | 53 | .. hdl-diagram:: ../code/verilog/muxcy.v 54 | :type: netlistsvg 55 | :caption: muxcy.v 56 | :module: MUXCY 57 | 58 | 59 | XORCY 60 | ***** 61 | 62 | .. code-block:: rst 63 | :linenos: 64 | 65 | .. hdl-diagram:: ../code/verilog/xorcy.v 66 | :type: netlistsvg 67 | :caption: xorcy.v 68 | :module: XORCY 69 | 70 | 71 | .. hdl-diagram:: ../code/verilog/xorcy.v 72 | :type: netlistsvg 73 | :caption: xorcy.v 74 | :module: XORCY 75 | 76 | CARRY4 without flatten 77 | ********************** 78 | 79 | .. code-block:: rst 80 | :linenos: 81 | 82 | .. hdl-diagram:: ../code/verilog/carry4-bits.v 83 | :type: netlistsvg 84 | :module: CARRY4 85 | :caption: carry4-bits.v without flatten 86 | 87 | 88 | .. hdl-diagram:: ../code/verilog/carry4-bits.v 89 | :type: netlistsvg 90 | :module: CARRY4 91 | :caption: carry4-bits.v without flatten 92 | 93 | CARRY4 with flatten 94 | ******************* 95 | 96 | .. code-block:: rst 97 | :linenos: 98 | :emphasize-lines: 4 99 | 100 | .. hdl-diagram:: ../code/verilog/carry4-bits.v 101 | :type: netlistsvg 102 | :module: CARRY4 103 | :flatten: 104 | :caption: carry4-bits.v with flatten 105 | 106 | 107 | .. hdl-diagram:: ../code/verilog/carry4-bits.v 108 | :type: netlistsvg 109 | :module: CARRY4 110 | :flatten: 111 | :caption: carry4-bits.v with flatten -------------------------------------------------------------------------------- /docs/examples/comb-full-adder.rst: -------------------------------------------------------------------------------- 1 | Combinational Full Adder 2 | ======================== 3 | 4 | Verilog Code 5 | ++++++++++++ 6 | 7 | RST Directive 8 | ************* 9 | 10 | .. code-block:: rst 11 | :linenos: 12 | 13 | .. no-license:: ../code/verilog/adder.v 14 | :language: verilog 15 | :linenos: 16 | 17 | 18 | Result 19 | ****** 20 | 21 | .. no-license:: ../code/verilog/adder.v 22 | :language: verilog 23 | :linenos: 24 | 25 | 26 | Yosys BlackBox Diagram 27 | ++++++++++++++++++++++ 28 | 29 | RST Directive 30 | ************* 31 | 32 | .. code-block:: rst 33 | :linenos: 34 | :emphasize-lines: 2 35 | 36 | .. hdl-diagram:: ../code/verilog/adder.v 37 | :type: yosys-bb 38 | :module: ADDER 39 | 40 | Result 41 | ****** 42 | 43 | .. hdl-diagram:: ../code/verilog/adder.v 44 | :type: yosys-bb 45 | :module: ADDER 46 | 47 | 48 | Yosys AIG Diagram 49 | +++++++++++++++++ 50 | 51 | RST Directive 52 | ************* 53 | 54 | .. code-block:: rst 55 | :linenos: 56 | :emphasize-lines: 2 57 | 58 | .. hdl-diagram:: ../code/verilog/adder.v 59 | :type: yosys-aig 60 | :module: ADDER 61 | 62 | Result 63 | ****** 64 | 65 | .. hdl-diagram:: ../code/verilog/adder.v 66 | :type: yosys-aig 67 | :module: ADDER 68 | 69 | 70 | NetlistSVG Diagram 71 | ++++++++++++++++++ 72 | 73 | RST Directive 74 | ************* 75 | 76 | .. code-block:: rst 77 | :linenos: 78 | :emphasize-lines: 2 79 | 80 | .. hdl-diagram:: ../code/verilog/adder.v 81 | :type: netlistsvg 82 | :module: ADDER 83 | 84 | 85 | Result 86 | ****** 87 | 88 | .. hdl-diagram:: ../code/verilog/adder.v 89 | :type: netlistsvg 90 | :module: ADDER 91 | -------------------------------------------------------------------------------- /docs/examples/index.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | ========== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :glob: 7 | 8 | comb-full-adder 9 | carry4 -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Sphinx HDL Diagrams 2 | =================== 3 | 4 | sphinx-hdl-diagrams is an extension to Sphinx to make it easier to write 5 | nice documentation from HDL source files, in the form of Verilog, nMigen, 6 | or RTLIL code. 7 | 8 | You use the |hdl-diagram|_ RST directive to generate various styles of 9 | diagrams from HDL code. 10 | 11 | Most of the time there will be a license header at the top of source code, 12 | which we might not want to show in the documentation. 13 | This extension also provides the |no-license|_ RST directive which works exactly 14 | like the `.. literalinclude` directive, but the `lines` option is overridden 15 | to only show the lines after the license header. 16 | 17 | 18 | .. |hdl-diagram| replace:: `.. hdl-diagram` 19 | .. _hdl-diagram: directives/hdl-diagram.html 20 | .. |no-license| replace:: `.. no-license` 21 | .. _no-license: directives/no-license.html 22 | 23 | The project repository is hosted on `GitHub `_. 24 | 25 | Installation 26 | ------------ 27 | 28 | Python 3.5+ is required. 29 | 30 | .. code-block:: bash 31 | 32 | pip install sphinxcontrib-hdl-diagrams 33 | 34 | Or, 35 | 36 | .. code-block:: bash 37 | 38 | python3 -m pip install sphinxcontrib-hdl-diagrams 39 | 40 | Sphinx integration 41 | ~~~~~~~~~~~~~~~~~~ 42 | 43 | In your conf.py, add the following lines. 44 | 45 | .. code-block:: python 46 | 47 | extensions = [ 48 | ..., 49 | 'sphinxcontrib_hdl_diagrams', 50 | ] 51 | 52 | Non-python dependencies 53 | ~~~~~~~~~~~~~~~~~~~~~~~ 54 | These dependencies can either be installed on your system or you can install them using the 55 | conda `environment.yml `_ file. 56 | 57 | - `yosys `_ (required) 58 | - `netlistsvg `_ (optional) 59 | 60 | Usage 61 | ----- 62 | 63 | hdl-diagram 64 | ~~~~~~~~~~~ 65 | 66 | The `hdl-diagram` RST directive can be used to generate a diagram from HDL code and include it in your documentation. 67 | 68 | .. code-block:: rst 69 | 70 | .. hdl-diagram:: file.v 71 | :type: XXXXX 72 | :module: XXXX 73 | :flatten: 74 | 75 | Options 76 | +++++++ 77 | 78 | `:type:` - Verilog Diagram Types; 79 | 80 | - `yosys-blackbox` - Netlist rendered by Yosys. 81 | - `yosys-aig` - Verilog file run through `aigmap` before image is generated directly in Yosys. 82 | - `netlistsvg` - Render output with `netlistsvg `_ 83 | 84 | `:module:` - Which module to diagram. 85 | 86 | `:flatten:` - Use the Yosys `flatten` command before generating the image. 87 | 88 | no-license 89 | ~~~~~~~~~~ 90 | The `no-license` RST directive can be used to include code without license headers. 91 | 92 | .. code-block:: rst 93 | 94 | .. no-license:: file.v 95 | :language: verilog 96 | :linenos: 97 | :caption: examples/verilog/dff.v 98 | 99 | Options 100 | +++++++ 101 | 102 | This directive merely overrides the `lines` and `lineno-start` options of the `literalinclude` directive. 103 | So, refer to `literalinclude` for the available options. 104 | 105 | .. toctree:: 106 | :maxdepth: 1 107 | :glob: 108 | :hidden: 109 | 110 | directives/index 111 | examples/index 112 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | git+http://github.com/SymbiFlow/sphinx_symbiflow_theme.git@main#egg=sphinx_symbiflow_theme 2 | 3 | docutils 4 | sphinx 5 | sphinx-autobuild 6 | sphinxcontrib-napoleon 7 | nmigen 8 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name: sphinxcontrib-hdl-diagrams 18 | channels: 19 | - LiteX-Hub # https://github.com/hdl/conda-eda 20 | - conda-forge 21 | - defaults 22 | dependencies: 23 | - docutils 24 | - graphviz # Needed for dot 25 | - netlistsvg 26 | - nodejs 27 | - pip 28 | - python=3.7 29 | - sphinx 30 | - yosys 31 | - r-rsvg 32 | - pip: # Packages installed from PyPI 33 | - -r requirements.txt 34 | - -r docs/requirements.txt 35 | - . 36 | - compat/. 37 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | setuptools 2 | docutils 3 | sphinx 4 | 5 | yowasp-yosys>=0.9.post4547.dev9 6 | 7 | # Needed to upload to PyPi 8 | twine 9 | 10 | # Needed for tests 11 | jinja2 12 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | 20 | import sys 21 | from os import path 22 | 23 | from setuptools import setup, find_packages 24 | 25 | __dir__ = path.dirname(path.abspath(__file__)) 26 | 27 | # Manually import the version number so dependencies don't need to be installed 28 | # when running setup.py 29 | version_file = path.join(__dir__, "sphinxcontrib_hdl_diagrams", "version.py") 30 | if path.exists(version_file): 31 | exec(open(version_file).read()) 32 | else: 33 | __version__ = "0.0.dev0" 34 | 35 | readme_file = path.join(__dir__, 'README.rst') 36 | try: 37 | with open(readme_file) as f: 38 | readme = f.read() 39 | except FileNotFoundError as e: 40 | import traceback 41 | traceback.print_exc() 42 | readme = '' 43 | __version__ = 'error' 44 | 45 | install_requires = [ 46 | 'setuptools', 47 | 'docutils', 48 | 'sphinx', 49 | 'nmigen', 50 | 'yowasp_yosys' 51 | ] 52 | 53 | setup( 54 | name='sphinxcontrib-hdl-diagrams', 55 | version=__version__, 56 | author="SymbiFlow Authors", 57 | author_email="symbiflow@lists.librecores.org", 58 | license="Apache 2.0", 59 | description="Generate diagrams from HDL in Sphinx.", 60 | long_description=readme, 61 | long_description_content_type="text/x-rst", 62 | url='https://github.com/SymbiFlow/sphinxcontrib-hdl-diagrams', 63 | packages=find_packages(), 64 | keywords='Verilog nMigen RTLIL yosys HDL sphinx sphinx-extension netlistsvg FPGA', 65 | classifiers=[ 66 | 'Development Status :: 4 - Beta', 67 | 'Framework :: Sphinx :: Extension', 68 | 'Intended Audience :: Developers', 69 | #'License :: OSI Approved :: Apache 2.0', 70 | 'License :: OSI Approved :: Apache Software License', 71 | 'Natural Language :: English', 72 | 'Programming Language :: Python :: 3.5', 73 | 'Programming Language :: Python :: 3.6', 74 | 'Topic :: Text Processing', 75 | ], 76 | install_requires=install_requires, 77 | ) 78 | -------------------------------------------------------------------------------- /sphinxcontrib_hdl_diagrams/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | 20 | """ 21 | sphinx_hdl_diagrams 22 | ~~~~~~~~~~~~~~~~~~~~~~~ 23 | 24 | """ 25 | 26 | import os 27 | import re 28 | import codecs 29 | import posixpath 30 | import subprocess 31 | import sys 32 | 33 | from os import path 34 | 35 | from docutils import statemachine, nodes, io, utils 36 | from docutils.parsers.rst import Directive, directives 37 | from docutils.statemachine import ViewList 38 | 39 | import sphinx 40 | from sphinx.directives.code import LiteralInclude 41 | from sphinx.errors import SphinxError 42 | from sphinx.locale import _, __ 43 | from sphinx.util import logging 44 | from sphinx.util.i18n import search_image_for_language 45 | from sphinx.util.osutil import ensuredir 46 | 47 | if False: 48 | # For type annotation 49 | from typing import Any, Dict, List, Tuple # NOQA 50 | from sphinx.application import Sphinx # NOQA 51 | 52 | 53 | try: 54 | from .version import __version__ 55 | except ImportError: 56 | __version__ = "0.0.dev0" 57 | 58 | 59 | logger = logging.getLogger(__name__) 60 | 61 | 62 | import subprocess 63 | 64 | def run_quietly(cmd): 65 | print("Running: {}".format(subprocess.list2cmdline(cmd))) 66 | try: 67 | result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) 68 | except subprocess.CalledProcessError as e: 69 | print(f"Command {subprocess.list2cmdline(cmd)} failed with error {e.returncode}:") 70 | print(e.stdout, file=sys.stderr) 71 | raise 72 | 73 | class HDLDiagramError(SphinxError): 74 | category = 'HDLDiagram error' 75 | 76 | 77 | class hdl_diagram(nodes.General, nodes.Inline, nodes.Element): 78 | '''Base class for hdl_diagram node''' 79 | pass 80 | 81 | 82 | def figure_wrapper(directive, node, caption): 83 | # type: (Directive, nodes.Node, unicode) -> nodes.figure 84 | figure_node = nodes.figure('', node) 85 | if 'align' in node: 86 | figure_node['align'] = node.attributes.pop('align') 87 | 88 | parsed = nodes.Element() 89 | directive.state.nested_parse( 90 | ViewList([caption], source=''), directive.content_offset, parsed) 91 | caption_node = nodes.caption( 92 | parsed[0].rawsource, '', *parsed[0].children) 93 | caption_node.source = parsed[0].source 94 | caption_node.line = parsed[0].line 95 | figure_node += caption_node 96 | return figure_node 97 | 98 | 99 | def align_spec(argument): 100 | # type: (Any) -> bool 101 | return directives.choice(argument, ('left', 'center', 'right')) 102 | 103 | 104 | def hdl_diagram_name(srcpath, srclineno, hdl_path): 105 | srcdir, srcfile = path.split(srcpath) 106 | srcbase, srcext = path.splitext(srcfile) 107 | 108 | hdl_path = path.normpath(path.join(srcdir, hdl_path)) 109 | hdl_path = utils.relative_path(None, hdl_path) 110 | hdl_path = nodes.reprunicode(hdl_path) 111 | 112 | hdl_path_segments = [hdl_path] 113 | while hdl_path_segments[0]: 114 | a, b = path.split(hdl_path_segments[0]) 115 | hdl_path_segments[0:1] = [a, b] 116 | 117 | hdl_file, hdl_ext = path.splitext(hdl_path_segments[-1]) 118 | 119 | return '-'.join( 120 | [srcbase, str(srclineno)] + 121 | hdl_path_segments[1:-1] + 122 | [hdl_file], 123 | ) 124 | 125 | 126 | class NoLicenseInclude(LiteralInclude): 127 | def run(self): 128 | # type: () -> List[nodes.Node] 129 | 130 | rel_filename, filename = self.env.relfn2path(self.arguments[0]) 131 | code = open(filename, 'r').read().strip().split('\n') 132 | 133 | first_line = next( 134 | (idx for idx, line in enumerate(code) if 'SPDX' in line), 1) 135 | if first_line > 1: 136 | first_line += 3 if code[first_line][1] == '*' else 2 137 | last_line = len(code) 138 | 139 | while len(code[first_line - 1]) == 0: 140 | first_line += 1 141 | 142 | self.options['lines'] = '{}-{}'.format(first_line, last_line) 143 | self.options['lineno-start'] = first_line 144 | 145 | try: 146 | return LiteralInclude.run(self) 147 | except Exception as exc: 148 | return [document.reporter.warning(exc, line=self.lineno)] 149 | 150 | 151 | class HDLDiagram(Directive): 152 | """ 153 | Directive to insert diagram generated from HDL code. 154 | """ 155 | 156 | has_content = True 157 | 158 | required_arguments = 1 159 | optional_arguments = 1 160 | 161 | final_argument_whitespace = False 162 | 163 | option_spec = { 164 | 'type': str, 165 | 'module': str, 166 | 'flatten': bool, 167 | 'skin': str, 168 | 'yosys_script': str, 169 | 170 | 'alt': directives.unchanged, 171 | 'align': align_spec, 172 | 'caption': directives.unchanged, 173 | } 174 | 175 | global_variable_options = { 176 | "hdl_diagram_output_format": ["svg", "png"], 177 | "hdl_diagram_skin": ["default"], # or path 178 | "hdl_diagram_yosys_script": ["default"], # or path 179 | "hdl_diagram_yosys": ["yowasp", "system"] # or path 180 | } 181 | 182 | def run(self): 183 | # type: () -> List[nodes.Node] 184 | 185 | if not self.state.document.settings.file_insertion_enabled: 186 | raise self.warning('"%s" directive disabled.' % self.name) 187 | 188 | print("hdl-diagram", self) 189 | 190 | source = self.state_machine.input_lines.source( 191 | self.lineno - self.state_machine.input_offset - 1) 192 | 193 | if self.arguments: 194 | hdl_file = self.arguments[0] 195 | 196 | outname = hdl_diagram_name( 197 | *self.state_machine.get_source_and_line(), hdl_file) 198 | 199 | # self.state.document.settings.record_dependencies.add(hdl_path) 200 | 201 | env = self.state.document.settings.env 202 | argument = search_image_for_language(hdl_file, env) 203 | rel_filename, filename = env.relfn2path(hdl_file) 204 | env.note_dependency(rel_filename) 205 | else: 206 | assert False, "TODO!" 207 | # TODO: ???? 208 | hdl_diagram_code = '\n'.join(self.content) 209 | 210 | node = hdl_diagram() 211 | node['code'] = filename 212 | node['options'] = {} 213 | node['options']['outname'] = outname 214 | node['options']['flatten'] = 'flatten' in self.options 215 | node['options']['module'] = self.options.get('module', 'top') 216 | node['options']['type'] = self.options.get('type', 'netlistsvg') 217 | 218 | if 'alt' in self.options: 219 | node['alt'] = self.options['alt'] 220 | if 'align' in self.options: 221 | node['align'] = self.options['align'] 222 | 223 | yosys_script = self.options.get('yosys_script', None) 224 | if yosys_script not in [None, 'default']: 225 | _, yosys_script_filename = env.relfn2path(yosys_script) 226 | if not path.exists(yosys_script_filename): 227 | raise HDLDiagramError("Yosys script {} does not exist!".format(yosys_script_filename)) 228 | else: 229 | node['options']['yosys_script'] = yosys_script_filename 230 | else: 231 | node['options']['yosys_script'] = yosys_script 232 | 233 | skin = self.options.get('skin', None) 234 | if skin not in [None, 'default']: 235 | _, skin_filename = env.relfn2path(skin) 236 | if not os.path.exists(skin_filename): 237 | raise HDLDiagramError("Skin file {} does not exist!".format(skin_filename)) 238 | else: 239 | node['options']['skin'] = skin_filename 240 | else: 241 | node['options']['skin'] = skin 242 | 243 | caption = self.options.get('caption') 244 | if caption: 245 | node = figure_wrapper(self, node, caption) 246 | 247 | self.add_name(node) 248 | return [node] 249 | 250 | 251 | def run_yosys(src, cmd, yosys='yowasp'): 252 | if yosys == 'yowasp': 253 | import yowasp_yosys 254 | ycmd = ["-q", "-p", "{}".format(cmd), src] 255 | print("Running YoWASP yosys: {}".format(ycmd)) 256 | returncode = yowasp_yosys.run_yosys(ycmd) 257 | if returncode != 0: 258 | raise subprocess.CalledProcessError(returncode, "yowasp_yosys") 259 | 260 | elif yosys == 'system': 261 | ycmd = ["yosys", "-p", cmd, src] 262 | run_quietly(ycmd) 263 | else: 264 | ycmd = [yosys, '-p', cmd, src] 265 | run_quietly(ycmd) 266 | 267 | 268 | def diagram_yosys(ipath, opath, module='top', flatten=False, 269 | yosys_script='default', yosys='yowasp'): 270 | 271 | # Assertions 272 | 273 | assert path.exists(ipath), 'Input file missing: {}'.format(ipath) 274 | assert not path.exists(opath), 'Output file exists: {}'.format(opath) 275 | yosys_options = HDLDiagram.global_variable_options["hdl_diagram_yosys"] 276 | assert yosys in yosys_options or os.path.exists(yosys), "Invalid hdl_diagram_yosys value!" 277 | if yosys_script != 'default': 278 | assert path.exists(yosys_script), 'Yosys script file missing: {}'.format(yosys_script) 279 | oprefix, oext = path.splitext(opath) 280 | assert oext.startswith('.'), oext 281 | 282 | # Diagram generation 283 | 284 | oext = oext[1:] 285 | 286 | if flatten: 287 | flatten = '-flatten' 288 | else: 289 | flatten = '' 290 | 291 | if yosys_script == 'default': 292 | yosys_script_cmd = "" 293 | else: 294 | yosys_script_cmd = "script {}".format(yosys_script) 295 | 296 | yosys_cmd = "prep -top {top} {flatten}; cd {top}; {script}; show -format {fmt} -prefix {oprefix}".format( 297 | top=module, 298 | flatten=flatten, 299 | fmt=oext, 300 | oprefix=oprefix, 301 | script=yosys_script_cmd 302 | ).strip() 303 | run_yosys(ipath, yosys_cmd, yosys) 304 | 305 | if yosys == 'yowasp': 306 | # somehow yowasp_yosys fails to execute `dot` to convert the dot file to svg, 307 | # which works on native yosys, perhaps a limitation with wasm 308 | svgdata = subprocess.check_output(["dot", "-Tsvg", "{}.dot".format(oprefix)]) 309 | tmpfile = "{}.svg".format(oprefix) 310 | with open(tmpfile, "wb") as img: 311 | img.write(svgdata) 312 | 313 | if tmpfile != opath: 314 | convert(tmpfile, opath) 315 | 316 | assert path.exists(opath), 'Output file {} was not created!'.format(opath) 317 | print('Output file created: {}'.format(opath)) 318 | 319 | def run_netlistsvg(ipath, opath, skin='default'): 320 | assert path.exists(ipath), 'Input file missing: {}'.format(ipath) 321 | assert not path.exists(opath), 'Output file exists: {}'.format(opath) 322 | if skin != 'default': 323 | assert path.exists(skin), 'Skin file missing: {}'.format(skin) 324 | 325 | netlistsvg_cmd = ["netlistsvg", ipath, '-o', opath] 326 | if skin != 'default': 327 | netlistsvg_cmd += ['--skin', skin] 328 | 329 | run_quietly(netlistsvg_cmd) 330 | 331 | assert path.exists(opath), 'Output file {} was not created!'.format(opath) 332 | print('netlistsvg - Output file created: {}'.format(opath)) 333 | 334 | 335 | def diagram_netlistsvg(ipath, opath, module='top', flatten=False, 336 | yosys_script='default', skin='default', yosys='yowasp'): 337 | # Assertions 338 | 339 | assert path.exists(ipath), 'Input file missing: {}'.format(ipath) 340 | assert not path.exists(opath), 'Output file exists: {}'.format(opath) 341 | yosys_options = HDLDiagram.global_variable_options["hdl_diagram_yosys"] 342 | assert yosys in yosys_options or os.path.exists(yosys), "Invalid hdl_diagram_yosys value!" 343 | if yosys_script != 'default': 344 | assert path.exists(yosys_script), 'Yosys script file missing: {}'.format(yosys_script) 345 | if skin != 'default': 346 | assert path.exists(skin), 'Skin file missing: {}'.format(skin) 347 | oprefix, oext = path.splitext(opath) 348 | assert oext.startswith('.'), oext 349 | 350 | # Diagram generation 351 | 352 | oext = oext[1:] 353 | 354 | if flatten: 355 | flatten = '-flatten' 356 | else: 357 | flatten = '' 358 | 359 | if yosys_script == 'default': 360 | yosys_script_cmd = "" 361 | else: 362 | yosys_script_cmd = "script {}".format(yosys_script) 363 | 364 | ojson = oprefix + '.json' 365 | if path.exists(ojson): 366 | os.remove(ojson) 367 | 368 | yosys_cmd = """prep -top {top} {flatten}; cd {top}; {script}; write_json {compat} {ojson}""".format( 369 | top=module, 370 | flatten=flatten, 371 | ojson=ojson, 372 | script=yosys_script_cmd, 373 | compat="-compat-int" if yosys == 'yowasp' else "" 374 | ).strip() 375 | run_yosys(ipath, yosys_cmd, yosys) 376 | assert path.exists(ojson), 'Output file {} was not created!'.format(ojson) 377 | 378 | run_netlistsvg(ojson, opath, skin) 379 | print('netlistsvg - Output file created: {}'.format(ojson)) 380 | 381 | 382 | def nmigen_to_rtlil(fname, oname): 383 | assert os.path.exists(fname) 384 | 385 | output_dir = os.path.dirname(oname) 386 | os.makedirs(output_dir, exist_ok=True) 387 | cmd = "{python} {script} > {output}".format(python=sys.executable, script=fname, output=oname) 388 | subprocess.run(cmd, shell=True, check=True) 389 | 390 | def convert(source, destination): 391 | # convertcmd = ['inkscape', source, f"--export-filename={destination}"] 392 | # convertcmd = ['convert', source, destination] 393 | convertcmd = ['rsvg-convert', '-f', 'pdf', source, '-o', destination] 394 | run_quietly(convertcmd) 395 | 396 | def render_diagram(self, code, options, format): 397 | # type: (nodes.NodeVisitor, unicode, Dict, unicode, unicode) -> Tuple[unicode, unicode] 398 | """Render hdl code into a PNG or SVG output file.""" 399 | 400 | yosys_script = self.builder.config.hdl_diagram_yosys_script 401 | if yosys_script != 'default' and not path.exists(yosys_script): 402 | raise HDLDiagramError("Yosys script file {} does not exist! Change hdl_diagram_yosys_script variable".format(yosys_script)) 403 | 404 | skin = self.builder.config.hdl_diagram_skin 405 | if skin != 'default' and not path.exists(skin): 406 | raise HDLDiagramError("Skin file {} does not exist! Change hdl_diagram_skin variable".format(skin)) 407 | 408 | source_path = code 409 | source_fn, source_ext = os.path.splitext(source_path) 410 | 411 | fname = '%s.%s' % (options['outname'], format) 412 | relfn = posixpath.join(self.builder.imgpath, fname) 413 | outfn = path.join(self.builder.outdir, self.builder.imagedir, fname) 414 | 415 | if source_ext == '.py': 416 | module = 'top' 417 | ilfn = path.join(self.builder.outdir, self.builder.imagedir, options['outname'] + '.il') 418 | nmigen_to_rtlil(source_path, ilfn) 419 | source_path = ilfn 420 | elif source_ext == '.il' or source_ext == '.v': 421 | module = options['module'] 422 | else: 423 | raise HDLDiagramError("hdl_diagram_code file extension must be one of '.v', " 424 | "'.il', or '.py', but is %r" % source_ext) 425 | 426 | if path.isfile(outfn): 427 | print('Exiting file:', outfn) 428 | return relfn, outfn 429 | 430 | ensuredir(path.dirname(outfn)) 431 | 432 | yosys_script = options['yosys_script'] if options['yosys_script'] is not None else yosys_script 433 | skin = options['skin'] if options['skin'] is not None else skin 434 | 435 | yosys = self.builder.config.hdl_diagram_yosys 436 | yosys_options = HDLDiagram.global_variable_options["hdl_diagram_yosys"] 437 | if yosys not in yosys_options and not os.path.exists(yosys): 438 | raise HDLDiagramError("Yosys not found!") 439 | else: 440 | yosys = yosys if yosys in yosys_options else os.path.realpath(yosys) 441 | 442 | diagram_type = options['type'] 443 | if diagram_type.startswith('yosys'): 444 | assert diagram_type.startswith('yosys-'), diagram_type 445 | diagram_yosys( 446 | source_path, 447 | outfn, 448 | module=options['module'], 449 | flatten=options['flatten'], 450 | yosys_script=yosys_script, 451 | yosys=yosys) 452 | elif diagram_type == 'netlistsvg': 453 | tmpfile = outfn if format == 'svg' else outfn + '.svg' 454 | diagram_netlistsvg( 455 | source_path, 456 | tmpfile, 457 | module=options['module'], 458 | flatten=options['flatten'], 459 | skin=skin, 460 | yosys=yosys) 461 | if format != 'svg': 462 | convert(tmpfile, outfn) 463 | else: 464 | raise Exception('Invalid diagram type "%s"' % diagram_type) 465 | # raise self.severe(\n' % 466 | # (SafeString(diagram_type),)) 467 | 468 | return relfn, outfn 469 | 470 | 471 | def render_diagram_html( 472 | self, node, code, options, imgcls=None, alt=None): 473 | # type: (nodes.NodeVisitor, hdl_diagram, unicode, Dict, unicode, unicode, unicode) -> Tuple[unicode, unicode] # NOQA 474 | 475 | format = self.builder.config.hdl_diagram_output_format 476 | try: 477 | if format not in ('png', 'svg'): 478 | raise HDLDiagramError("hdl_diagram_output_format must be one of 'png', " 479 | "'svg', but is %r" % format) 480 | fname, outfn = render_diagram(self, code, options, format) 481 | except HDLDiagramError as exc: 482 | logger.warning('hdl_diagram code %r: ' % code + str(exc)) 483 | raise nodes.SkipNode 484 | 485 | if fname is None: 486 | self.body.append(self.encode(code)) 487 | else: 488 | if alt is None: 489 | alt = node.get('alt', self.encode(code).strip()) 490 | imgcss = imgcls and 'class="%s"' % imgcls or '' 491 | if 'align' in node: 492 | self.body.append('
' % 493 | (node['align'], node['align'])) 494 | self.body.append('%s\n' % 495 | (fname, alt, imgcss)) 496 | if 'align' in node: 497 | self.body.append('
\n') 498 | 499 | raise nodes.SkipNode 500 | 501 | 502 | def html_visit_hdl_diagram(self, node): 503 | # type: (nodes.NodeVisitor, hdl_diagram) -> None 504 | render_diagram_html(self, node, node['code'], node['options']) 505 | 506 | 507 | def render_diagram_latex(self, node, code, options): 508 | # type: (nodes.NodeVisitor, hdl_diagram, unicode, Dict, unicode) -> None 509 | 510 | try: 511 | fname, outfn = render_diagram(self, code, options, 'pdf') 512 | except HDLDiagramError as exc: 513 | logger.warning('hdl_diagram code %r: ' % code + str(exc)) 514 | raise nodes.SkipNode 515 | 516 | is_inline = self.is_inline(node) 517 | if is_inline: 518 | para_separator = '' 519 | else: 520 | para_separator = '\n' 521 | 522 | if fname is not None: 523 | post = None # type: unicode 524 | if not is_inline and 'align' in node: 525 | if node['align'] == 'left': 526 | self.body.append('{') 527 | post = '\\hspace*{\\fill}}' 528 | elif node['align'] == 'right': 529 | self.body.append('{\\hspace*{\\fill}') 530 | post = '}' 531 | self.body.append('%s\\includegraphics{%s}%s' % 532 | (para_separator, fname, para_separator)) 533 | if post: 534 | self.body.append(post) 535 | 536 | raise nodes.SkipNode 537 | 538 | 539 | def latex_visit_hdl_diagram(self, node): 540 | # type: (nodes.NodeVisitor, hdl_diagram) -> None 541 | render_diagram_latex(self, node, node['code'], node['options']) 542 | 543 | 544 | def render_diagram_texinfo(self, node, code, options): 545 | # type: (nodes.NodeVisitor, hdl_diagram, unicode, Dict, unicode) -> None 546 | try: 547 | fname, outfn = render_diagram(self, code, options, 'png') 548 | except HDLDiagramError as exc: 549 | logger.warning('hdl_diagram code %r: ' % code + str(exc)) 550 | raise nodes.SkipNode 551 | if fname is not None: 552 | self.body.append('@image{%s,,,[hdl_diagram],png}\n' % fname[:-4]) 553 | raise nodes.SkipNode 554 | 555 | 556 | def texinfo_visit_hdl_diagram(self, node): 557 | # type: (nodes.NodeVisitor, hdl_diagram) -> None 558 | render_diagram_texinfo(self, node, node['code'], node['options']) 559 | 560 | 561 | def text_visit_hdl_diagram(self, node): 562 | # type: (nodes.NodeVisitor, hdl_diagram) -> None 563 | if 'alt' in node.attributes: 564 | self.add_text(_('[diagram: %s]') % node['alt']) 565 | else: 566 | self.add_text(_('[diagram]')) 567 | raise nodes.SkipNode 568 | 569 | 570 | def man_visit_hdl_diagram(self, node): 571 | # type: (nodes.NodeVisitor, hdl_diagram) -> None 572 | if 'alt' in node.attributes: 573 | self.body.append(_('[diagram: %s]') % node['alt']) 574 | else: 575 | self.body.append(_('[diagram]')) 576 | raise nodes.SkipNode 577 | 578 | 579 | def setup(app): 580 | # type: (Sphinx) -> Dict[unicode, Any] 581 | app.add_node(hdl_diagram, 582 | html=(html_visit_hdl_diagram, None), 583 | latex=(latex_visit_hdl_diagram, None), 584 | texinfo=(texinfo_visit_hdl_diagram, None), 585 | text=(text_visit_hdl_diagram, None), 586 | man=(man_visit_hdl_diagram, None)) 587 | app.add_directive('hdl-diagram', HDLDiagram) 588 | app.add_directive('verilog-diagram', HDLDiagram) 589 | app.add_directive('no-license', NoLicenseInclude) 590 | app.add_config_value('hdl_diagram_output_format', 'svg', 'html') 591 | app.add_config_value('hdl_diagram_skin', 'default', 'html') 592 | app.add_config_value('hdl_diagram_yosys_script', 'default', 'html') 593 | app.add_config_value('hdl_diagram_yosys', 'yowasp', 'html') 594 | return {'version': '1.0', 'parallel_read_safe': True} 595 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | test: 18 | make clean 19 | python3 test.py 20 | 21 | clean: 22 | -rm -rf build 23 | 24 | .PHONY: test clean 25 | -------------------------------------------------------------------------------- /tests/code/nmigen/counter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | 20 | from nmigen import * 21 | from nmigen.back import rtlil 22 | 23 | 24 | class Counter(Elaboratable): 25 | def __init__(self, width): 26 | self.v = Signal(width, reset=2**width-1) 27 | self.o = Signal() 28 | 29 | def elaborate(self, platform): 30 | m = Module() 31 | m.d.sync += self.v.eq(self.v + 1) 32 | m.d.comb += self.o.eq(self.v[-1]) 33 | return m 34 | 35 | 36 | ctr = Counter(width=16) 37 | print(rtlil.convert(ctr, ports=[ctr.o])) 38 | -------------------------------------------------------------------------------- /tests/code/rtlil/counter.il: -------------------------------------------------------------------------------- 1 | attribute \generator "nMigen" 2 | attribute \top 1 3 | attribute \nmigen.hierarchy "top" 4 | module \top 5 | attribute \src "counter.py:9" 6 | wire width 1 output 0 \o 7 | attribute \src "/usr/local/lib/python3.7/site-packages/nmigen/hdl/ir.py:526" 8 | wire width 1 input 1 \clk 9 | attribute \src "/usr/local/lib/python3.7/site-packages/nmigen/hdl/ir.py:526" 10 | wire width 1 input 2 \rst 11 | attribute \src "counter.py:8" 12 | wire width 16 \v 13 | attribute \src "counter.py:8" 14 | wire width 16 \v$next 15 | attribute \src "counter.py:13" 16 | wire width 17 $1 17 | attribute \src "counter.py:13" 18 | wire width 17 $2 19 | attribute \src "counter.py:13" 20 | cell $add $3 21 | parameter \A_SIGNED 1'0 22 | parameter \A_WIDTH 5'10000 23 | parameter \B_SIGNED 1'0 24 | parameter \B_WIDTH 1'1 25 | parameter \Y_WIDTH 5'10001 26 | connect \A \v 27 | connect \B 1'1 28 | connect \Y $2 29 | end 30 | connect $1 $2 31 | process $group_0 32 | assign \v$next \v 33 | assign \v$next $1 [15:0] 34 | attribute \src "/usr/local/lib/python3.7/site-packages/nmigen/hdl/xfrm.py:530" 35 | switch \rst 36 | case 1'1 37 | assign \v$next 16'1111111111111111 38 | end 39 | sync init 40 | update \v 16'1111111111111111 41 | sync posedge \clk 42 | update \v \v$next 43 | end 44 | process $group_1 45 | assign \o 1'0 46 | assign \o \v [15] 47 | sync init 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /tests/code/verilog/adder.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | module ADDER ( 20 | a, b, cin, 21 | sum, cout 22 | ); 23 | input wire a; 24 | input wire b; 25 | input wire cin; 26 | 27 | output wire sum; 28 | output wire cout; 29 | 30 | // Full adder combinational logic 31 | assign sum = a ^ b ^ cin; 32 | assign cout = ((a ^ b) & cin) | (a & b); 33 | endmodule 34 | -------------------------------------------------------------------------------- /tests/code/verilog/fullAdder.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | `include "halfAdder.v" 20 | 21 | module fullAdder ( 22 | output wire cout, s, 23 | input wire cin, x, y 24 | ); 25 | wire c1, c2, s1; 26 | 27 | halfAdder h1(c1, s1, x, y); 28 | halfAdder h2(c2, s, cin, s1); 29 | 30 | assign cout = c1 | c2; 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /tests/code/verilog/halfAdder.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 The SymbiFlow Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-License-Identifier: Apache-2.0 17 | */ 18 | 19 | module halfAdder ( 20 | output wire c, s, 21 | input wire x, y 22 | ); 23 | 24 | assign s = x ^ y; 25 | assign c = x & y; 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /tests/conf.py.template: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | 16 | sys.path.insert(0, {{ hdl_diagrams_path }}) 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'Sphinx Verilog Diagrams Tests' 21 | copyright = '2020, SymbiFlow Team' 22 | author = 'SymbiFlow Team' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = '0.1' 26 | 27 | 28 | # -- General configuration --------------------------------------------------- 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | 'sphinxcontrib_hdl_diagrams', 35 | ] 36 | 37 | # Add any paths that contain templates here, relative to this directory. 38 | templates_path = ['_templates'] 39 | 40 | # List of patterns, relative to source directory, that match files and 41 | # directories to ignore when looking for source files. 42 | # This pattern also affects html_static_path and html_extra_path. 43 | exclude_patterns = [] 44 | 45 | 46 | # -- Options for HTML output ------------------------------------------------- 47 | 48 | # The theme to use for HTML and HTML Help pages. See the documentation for 49 | # a list of builtin themes. 50 | # 51 | html_theme = 'alabaster' 52 | 53 | # Add any paths that contain custom static files (such as style sheets) here, 54 | # relative to this directory. They are copied after the builtin static files, 55 | # so a file named "default.css" will overwrite the builtin "default.css". 56 | 57 | master_doc = {{ master_doc }} 58 | {{ custom_variables }} 59 | -------------------------------------------------------------------------------- /tests/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (C) 2020-2021 The SymbiFlow Authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | 20 | import os 21 | import shutil 22 | import unittest 23 | 24 | from jinja2 import Environment, FileSystemLoader 25 | from sphinx.application import Sphinx 26 | from sphinx.util.docutils import docutils_namespace 27 | 28 | HDL_DIAGRAMS_PATH = os.path.abspath("..") 29 | 30 | ## Helpers 31 | 32 | def get_sphinx_dirs(test_build_dir): 33 | sphinx_dirs = { 34 | "srcdir": test_build_dir, 35 | "confdir": test_build_dir, 36 | "outdir": os.path.join(test_build_dir, "build"), 37 | "doctreedir": os.path.join(test_build_dir, "build", "doctrees") 38 | } 39 | return sphinx_dirs 40 | 41 | 42 | def generate_sphinx_config(test_build_dir, **jinja_dict): 43 | sphinx_config_path = os.path.join(test_build_dir, "conf.py") 44 | 45 | with open(sphinx_config_path, "w") as fd: 46 | env = Environment(loader=FileSystemLoader('.')) 47 | template = env.get_template("conf.py.template") 48 | template.stream(**jinja_dict).dump(fd) 49 | 50 | ## Base class for tests 51 | 52 | class TestBase(unittest.TestCase): 53 | 54 | def print_test_header(self, case_name, test_name): 55 | print("") 56 | print("# ---------------------------------------------------------- #") 57 | print("# TEST CASE: {}".format(case_name)) 58 | print("# TEST NAME: {}".format(test_name)) 59 | print("# ---------------------------------------------------------- #") 60 | print("") 61 | 62 | def prepare_test(self, test_name, test_build_dir, test_files, **test_jinja_dict): 63 | self.print_test_header(self.TEST_CASE_NAME, test_name) 64 | 65 | # Create the TestCase build directory 66 | os.makedirs(test_build_dir, exist_ok=True) 67 | 68 | # Generate a Sphinx config 69 | generate_sphinx_config(test_build_dir, **test_jinja_dict) 70 | 71 | # Copy the test files 72 | for src in test_files: 73 | src_basename = os.path.basename(src) 74 | dst = os.path.join(test_build_dir, src_basename) 75 | shutil.copyfile(src, dst) 76 | 77 | 78 | def run_builds(sphinx_dirs): 79 | for builder in ("html", "latex"): 80 | with docutils_namespace(): 81 | app = Sphinx(buildername=builder, warningiserror=True, **sphinx_dirs) 82 | app.build(force_all=True) 83 | 84 | ## Test cases 85 | 86 | class TestSkins(TestBase): 87 | 88 | TEST_CASE_NAME = "TestSkins" 89 | TEST_CASE_BUILD_DIR = os.path.join("build", TEST_CASE_NAME) 90 | 91 | def test_netlistsvg_diagram(self): 92 | TEST_NAME = "test_skins" 93 | TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) 94 | TEST_FILES = [ 95 | "test_skins/test_skins.rst", 96 | "test_skins/skin-purple.svg", 97 | "test_skins/skin-yellow.svg", 98 | "code/verilog/adder.v" 99 | ] 100 | TEST_JINJA_DICT = { 101 | "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), 102 | "master_doc": "'test_skins'", 103 | "custom_variables": "hdl_diagram_skin = os.path.realpath('skin-purple.svg')" 104 | } 105 | 106 | self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) 107 | 108 | # Run the Sphinx 109 | sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) 110 | run_builds(sphinx_dirs) 111 | 112 | 113 | class TestYosysScript(TestBase): 114 | 115 | TEST_CASE_NAME = "TestYosysScript" 116 | TEST_CASE_BUILD_DIR = os.path.join("build", TEST_CASE_NAME) 117 | 118 | def test_yosys_script(self): 119 | TEST_NAME = "test_yosys_script" 120 | TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) 121 | TEST_FILES = [ 122 | "test_yosys_script/test_yosys_script.rst", 123 | "test_yosys_script/yosys_script.ys", 124 | "test_yosys_script/yosys_script2.ys", 125 | "code/verilog/adder.v" 126 | ] 127 | TEST_JINJA_DICT = { 128 | "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), 129 | "master_doc": "'test_yosys_script'", 130 | "custom_variables": "hdl_diagram_yosys_script = os.path.realpath('yosys_script.ys')" 131 | } 132 | 133 | self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) 134 | 135 | # Run the Sphinx 136 | sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) 137 | run_builds(sphinx_dirs) 138 | 139 | 140 | class TestYosysType(TestBase): 141 | 142 | TEST_CASE_NAME = "TestYowasp" 143 | TEST_CASE_BUILD_DIR = os.path.join("build", TEST_CASE_NAME) 144 | 145 | def test_yosys_yowasp(self): 146 | TEST_NAME = "test_yosys_yowasp" 147 | TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) 148 | TEST_FILES = [ 149 | "test_yosys_type/test_yosys_yowasp.rst", 150 | "code/verilog/adder.v" 151 | ] 152 | TEST_JINJA_DICT = { 153 | "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), 154 | "master_doc": "'test_yosys_yowasp'", 155 | "custom_variables": "" 156 | } 157 | 158 | self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) 159 | 160 | # Run the Sphinx 161 | sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) 162 | with docutils_namespace(): 163 | app = Sphinx(buildername="html", warningiserror=True, **sphinx_dirs) 164 | app.build(force_all=True) 165 | 166 | @unittest.skipIf(shutil.which('yosys') is None, 'Skipping test_yosys_system. Yosys is not installed!') 167 | def test_yosys_system(self): 168 | TEST_NAME = "test_yosys_system" 169 | TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) 170 | TEST_FILES = [ 171 | "test_yosys_type/test_yosys_system.rst", 172 | "code/verilog/adder.v" 173 | ] 174 | TEST_JINJA_DICT = { 175 | "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), 176 | "master_doc": "'test_yosys_system'", 177 | "custom_variables": "hdl_diagram_yosys = 'system'" 178 | } 179 | 180 | self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) 181 | 182 | # Run the Sphinx 183 | sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) 184 | with docutils_namespace(): 185 | app = Sphinx(buildername="html", warningiserror=True, **sphinx_dirs) 186 | app.build(force_all=True) 187 | 188 | @unittest.skipIf(shutil.which('yosys') is None, 'Skipping test_yosys_path. Yosys is not installed!') 189 | def test_yosys_path(self): 190 | TEST_NAME = "test_yosys_path" 191 | TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) 192 | TEST_FILES = [ 193 | "test_yosys_type/test_yosys_path.rst", 194 | "code/verilog/adder.v" 195 | ] 196 | 197 | yosys_path = shutil.which("yosys") 198 | 199 | TEST_JINJA_DICT = { 200 | "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), 201 | "master_doc": "'test_yosys_path'", 202 | "custom_variables": "hdl_diagram_yosys = '{}'".format(yosys_path) 203 | } 204 | 205 | self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) 206 | 207 | # Run the Sphinx 208 | sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) 209 | run_builds(sphinx_dirs) 210 | 211 | 212 | class TestNMigen(TestBase): 213 | 214 | TEST_CASE_NAME = "TestNMigen" 215 | TEST_CASE_BUILD_DIR = os.path.join("build", TEST_CASE_NAME) 216 | 217 | def test_yosys_script(self): 218 | TEST_NAME = "test_nmigen" 219 | TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) 220 | TEST_FILES = [ 221 | "test_nmigen/test_nmigen.rst", 222 | "code/nmigen/counter.py" 223 | ] 224 | TEST_JINJA_DICT = { 225 | "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), 226 | "master_doc": "'test_nmigen'", 227 | "custom_variables": "''" 228 | } 229 | 230 | self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) 231 | 232 | # Run the Sphinx 233 | sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) 234 | run_builds(sphinx_dirs) 235 | 236 | 237 | class TestRTLIL(TestBase): 238 | 239 | TEST_CASE_NAME = "TestRTLIL" 240 | TEST_CASE_BUILD_DIR = os.path.join("build", TEST_CASE_NAME) 241 | 242 | def test_yosys_script(self): 243 | TEST_NAME = "test_rtlil" 244 | TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) 245 | TEST_FILES = [ 246 | "test_rtlil/test_rtlil.rst", 247 | "code/rtlil/counter.il" 248 | ] 249 | TEST_JINJA_DICT = { 250 | "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), 251 | "master_doc": "'test_rtlil'", 252 | "custom_variables": "''" 253 | } 254 | 255 | self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) 256 | 257 | # Run the Sphinx 258 | sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) 259 | run_builds(sphinx_dirs) 260 | 261 | 262 | class TestCompat(TestBase): 263 | 264 | TEST_CASE_NAME = "TestCompat" 265 | TEST_CASE_BUILD_DIR = os.path.join("build", TEST_CASE_NAME) 266 | 267 | def test_yosys_script(self): 268 | TEST_NAME = "test_compat" 269 | TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) 270 | TEST_FILES = [ 271 | "test_compat/test_compat.rst", 272 | "code/verilog/adder.v" 273 | ] 274 | TEST_JINJA_DICT = { 275 | "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), 276 | "master_doc": "'test_compat'", 277 | "custom_variables": """ 278 | extensions = [ 279 | 'sphinxcontrib_verilog_diagrams', 280 | ]""" 281 | } 282 | 283 | self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) 284 | 285 | # Run the Sphinx 286 | sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) 287 | run_builds(sphinx_dirs) 288 | 289 | 290 | class TestFlatten(TestBase): 291 | 292 | TEST_CASE_NAME = "TestFlatten" 293 | TEST_CASE_BUILD_DIR = os.path.join("build", TEST_CASE_NAME) 294 | 295 | def test_yosys_script(self): 296 | TEST_NAME = "test_flatten" 297 | TEST_BUILD_DIR = os.path.join("build", self.TEST_CASE_NAME, TEST_NAME) 298 | TEST_FILES = [ 299 | "test_flatten/test_flatten.rst", 300 | "code/verilog/fullAdder.v", 301 | "code/verilog/halfAdder.v" 302 | ] 303 | TEST_JINJA_DICT = { 304 | "hdl_diagrams_path": "'{}'".format(HDL_DIAGRAMS_PATH), 305 | "master_doc": "'test_flatten'", 306 | "custom_variables": "" 307 | } 308 | 309 | self.prepare_test(TEST_NAME, TEST_BUILD_DIR, TEST_FILES, **TEST_JINJA_DICT) 310 | 311 | # Run the Sphinx 312 | sphinx_dirs = get_sphinx_dirs(TEST_BUILD_DIR) 313 | run_builds(sphinx_dirs) 314 | 315 | 316 | if __name__ == '__main__': 317 | unittest.main() 318 | -------------------------------------------------------------------------------- /tests/test_compat/test_compat.rst: -------------------------------------------------------------------------------- 1 | Test Compatibility Package 2 | ========================== 3 | 4 | This test checks whether the ``sphinxcontrib-verilog-diagrams`` compatibility 5 | package works as intended. 6 | 7 | Here is the fragment of the ``conf.py`` script, used to configure the extension:: 8 | 9 | extensions = [ 10 | 'sphinxcontrib_verilog_diagrams', 11 | ] 12 | 13 | Yosys BlackBox Diagram 14 | ---------------------- 15 | 16 | .. code-block:: rst 17 | 18 | .. verilog-diagram:: adder.v 19 | :type: yosys-blackbox 20 | :module: ADDER 21 | 22 | .. verilog-diagram:: adder.v 23 | :type: yosys-blackbox 24 | :module: ADDER 25 | 26 | Yosys AIG Diagram 27 | ----------------- 28 | 29 | .. code-block:: rst 30 | 31 | .. verilog-diagram:: adder.v 32 | :type: yosys-aig 33 | :module: ADDER 34 | 35 | .. verilog-diagram:: adder.v 36 | :type: yosys-aig 37 | :module: ADDER 38 | 39 | Netlistsvg Diagram 40 | ------------------ 41 | 42 | .. code-block:: rst 43 | 44 | .. verilog-diagram:: adder.v 45 | :type: netlistsvg 46 | :module: ADDER 47 | 48 | .. verilog-diagram:: adder.v 49 | :type: netlistsvg 50 | :module: ADDER 51 | -------------------------------------------------------------------------------- /tests/test_flatten/test_flatten.rst: -------------------------------------------------------------------------------- 1 | Test Flatten Option 2 | =================== 3 | 4 | This test checks whether a ``:flatten:`` option in the ``hdl-diagram`` 5 | directive works as intended. The ``:flatten:`` option is used to resolve 6 | the black boxes created by Yosys in place of instantiated modules. 7 | With this option enabled Yosys will convert everything into low-level logic 8 | where only basic logic cells and basic FPGA primitives will be used. 9 | 10 | Netlistsvg Diagram 11 | ------------------ 12 | 13 | Here is the diagram of a half-adder with its RST code:: 14 | 15 | .. hdl-diagram:: halfAdder.v 16 | :type: netlistsvg 17 | :module: halfAdder 18 | 19 | .. hdl-diagram:: halfAdder.v 20 | :type: netlistsvg 21 | :module: halfAdder 22 | 23 | The diagram below has been created without the ``:flatten:`` option:: 24 | 25 | .. hdl-diagram:: fullAdder.v 26 | :type: netlistsvg 27 | :module: fullAdder 28 | 29 | .. hdl-diagram:: fullAdder.v 30 | :type: netlistsvg 31 | :module: fullAdder 32 | 33 | The diagram below has been created using the ``:flatten:`` option. 34 | You can see that the ``halfAdder`` black box is substituted by the appropriate 35 | logic elements:: 36 | 37 | .. hdl-diagram:: fullAdder.v 38 | :type: netlistsvg 39 | :module: fullAdder 40 | :flatten: 41 | 42 | .. hdl-diagram:: fullAdder.v 43 | :type: netlistsvg 44 | :module: fullAdder 45 | :flatten: 46 | 47 | Yosys BlackBox Diagram 48 | ---------------------- 49 | 50 | Here is the diagram of a half-adder with its RST code:: 51 | 52 | .. hdl-diagram:: halfAdder.v 53 | :type: yosys-blackbox 54 | :module: halfAdder 55 | 56 | .. hdl-diagram:: halfAdder.v 57 | :type: yosys-blackbox 58 | :module: halfAdder 59 | 60 | The diagram below has been created without the ``:flatten:`` option:: 61 | 62 | .. hdl-diagram:: fullAdder.v 63 | :type: yosys-blackbox 64 | :module: fullAdder 65 | 66 | .. hdl-diagram:: fullAdder.v 67 | :type: yosys-blackbox 68 | :module: fullAdder 69 | 70 | The diagram below has been created using the ``:flatten:`` option. 71 | You can see that the ``halfAdder`` black box is substituted by the appropriate 72 | logic elements:: 73 | 74 | .. hdl-diagram:: fullAdder.v 75 | :type: yosys-blackbox 76 | :module: fullAdder 77 | :flatten: 78 | 79 | .. hdl-diagram:: fullAdder.v 80 | :type: yosys-blackbox 81 | :module: fullAdder 82 | :flatten: 83 | 84 | Yosys AIG Diagram 85 | ----------------- 86 | 87 | Here is the diagram of a half-adder with its RST code:: 88 | 89 | .. hdl-diagram:: halfAdder.v 90 | :type: yosys-aig 91 | :module: halfAdder 92 | 93 | .. hdl-diagram:: halfAdder.v 94 | :type: yosys-aig 95 | :module: halfAdder 96 | 97 | The diagram below has been created without the ``:flatten:`` option:: 98 | 99 | .. hdl-diagram:: fullAdder.v 100 | :type: yosys-aig 101 | :module: fullAdder 102 | 103 | .. hdl-diagram:: fullAdder.v 104 | :type: yosys-aig 105 | :module: fullAdder 106 | 107 | The diagram below has been created using the ``:flatten:`` option. 108 | You can see that the ``halfAdder`` black box is substituted by the appropriate 109 | logic elements:: 110 | 111 | .. hdl-diagram:: fullAdder.v 112 | :type: yosys-aig 113 | :module: fullAdder 114 | :flatten: 115 | 116 | .. hdl-diagram:: fullAdder.v 117 | :type: yosys-aig 118 | :module: fullAdder 119 | :flatten: 120 | -------------------------------------------------------------------------------- /tests/test_nmigen/test_nmigen.rst: -------------------------------------------------------------------------------- 1 | Test nMigen 2 | =========== 3 | 4 | This test checks diagram generation from nMigen sources. 5 | 6 | Yosys BlackBox Diagram 7 | ---------------------- 8 | 9 | .. code-block:: rst 10 | 11 | .. hdl-diagram:: counter.py 12 | :type: yosys-blackbox 13 | 14 | .. hdl-diagram:: counter.py 15 | :type: yosys-blackbox 16 | 17 | Yosys AIG Diagram 18 | ----------------- 19 | 20 | .. code-block:: rst 21 | 22 | .. hdl-diagram:: counter.py 23 | :type: yosys-aig 24 | 25 | .. hdl-diagram:: counter.py 26 | :type: yosys-aig 27 | 28 | Netlistsvg Diagram 29 | ------------------ 30 | 31 | .. code-block:: rst 32 | 33 | .. hdl-diagram:: counter.py 34 | :type: netlistsvg 35 | 36 | .. hdl-diagram:: counter.py 37 | :type: netlistsvg 38 | -------------------------------------------------------------------------------- /tests/test_rtlil/test_rtlil.rst: -------------------------------------------------------------------------------- 1 | Test RTLIL 2 | =========== 3 | 4 | This test checks diagram generation from RTLIL sources. 5 | 6 | Yosys BlackBox Diagram 7 | ---------------------- 8 | 9 | .. code-block:: rst 10 | 11 | .. hdl-diagram:: counter.il 12 | :type: yosys-blackbox 13 | 14 | .. hdl-diagram:: counter.il 15 | :type: yosys-blackbox 16 | 17 | Yosys AIG Diagram 18 | ----------------- 19 | 20 | .. code-block:: rst 21 | 22 | .. hdl-diagram:: counter.il 23 | :type: yosys-aig 24 | 25 | .. hdl-diagram:: counter.il 26 | :type: yosys-aig 27 | 28 | Netlistsvg Diagram 29 | ------------------ 30 | 31 | .. code-block:: rst 32 | 33 | .. hdl-diagram:: counter.il 34 | :type: netlistsvg 35 | 36 | .. hdl-diagram:: counter.il 37 | :type: netlistsvg 38 | -------------------------------------------------------------------------------- /tests/test_skins/skin-purple.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 52 | 56 | 58 | 59 | 82 | 89 | 91 | 93 | 95 | 100 | 106 | 112 | 118 | 124 | 125 | 126 | 133 | 135 | 137 | 139 | 144 | 150 | 156 | 162 | 163 | 170 | 172 | 174 | 176 | 178 | 183 | 190 | 196 | 202 | 208 | 209 | 210 | 217 | 219 | 221 | 223 | 228 | 233 | 239 | 245 | 251 | 252 | 259 | 261 | 263 | 265 | 267 | 272 | 277 | 284 | 290 | 296 | 302 | 303 | 304 | 311 | 313 | 315 | 317 | 322 | 327 | 333 | 339 | 345 | 346 | 353 | 355 | 357 | 359 | 364 | 369 | 376 | 382 | 388 | 394 | 395 | 396 | 403 | 405 | 407 | 409 | 414 | 421 | 427 | 433 | 434 | 441 | 443 | 450 | 458 | 466 | 472 | 478 | 484 | 485 | 492 | 494 | 501 | 509 | 515 | 521 | 527 | 528 | 535 | 537 | 544 | 552 | 560 | 566 | 572 | 578 | 579 | 586 | 588 | 590 | 592 | 600 | 605 | 611 | 617 | 623 | 629 | 630 | 637 | 639 | 647 | 652 | 659 | 665 | 671 | 677 | 683 | 684 | 691 | 693 | 700 | 708 | 716 | 722 | 728 | 734 | 735 | 742 | 744 | 751 | 759 | 767 | 775 | 781 | 787 | 793 | 794 | 801 | 803 | 810 | 818 | 826 | 834 | 840 | 846 | 852 | 853 | 860 | 862 | 869 | 877 | 885 | 891 | 897 | 903 | 904 | 911 | input 918 | 920 | 925 | 931 | 932 | 939 | constant 946 | 948 | 954 | 960 | 961 | 968 | output 975 | 977 | 982 | 988 | 989 | 996 | 1003 | 1005 | 1011 | 1018 | hi:lo 1023 | 1024 | 1031 | hi:lo 1036 | 1037 | 1038 | 1045 | 1052 | 1054 | 1060 | 1067 | hi:lo 1073 | 1074 | 1081 | hi:lo 1087 | 1088 | 1089 | 1096 | generic 1103 | 1110 | 1117 | out0 1123 | 1124 | 1131 | out1 1137 | 1138 | 1145 | in0 1151 | 1152 | 1159 | in1 1165 | 1166 | 1167 | 1168 | -------------------------------------------------------------------------------- /tests/test_skins/skin-yellow.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 52 | 56 | 58 | 59 | 82 | 89 | 91 | 93 | 95 | 100 | 106 | 112 | 118 | 124 | 125 | 126 | 133 | 135 | 137 | 139 | 144 | 150 | 156 | 162 | 163 | 170 | 172 | 174 | 176 | 178 | 183 | 190 | 196 | 202 | 208 | 209 | 210 | 217 | 219 | 221 | 223 | 228 | 233 | 239 | 245 | 251 | 252 | 259 | 261 | 263 | 265 | 267 | 272 | 277 | 284 | 290 | 296 | 302 | 303 | 304 | 311 | 313 | 315 | 317 | 322 | 327 | 333 | 339 | 345 | 346 | 353 | 355 | 357 | 359 | 364 | 369 | 376 | 382 | 388 | 394 | 395 | 396 | 403 | 405 | 407 | 409 | 414 | 421 | 427 | 433 | 434 | 441 | 443 | 450 | 458 | 466 | 472 | 478 | 484 | 485 | 492 | 494 | 501 | 509 | 515 | 521 | 527 | 528 | 535 | 537 | 544 | 552 | 560 | 566 | 572 | 578 | 579 | 586 | 588 | 590 | 592 | 600 | 605 | 611 | 617 | 623 | 629 | 630 | 637 | 639 | 647 | 652 | 659 | 665 | 671 | 677 | 683 | 684 | 691 | 693 | 700 | 708 | 716 | 722 | 728 | 734 | 735 | 742 | 744 | 751 | 759 | 767 | 775 | 781 | 787 | 793 | 794 | 801 | 803 | 810 | 818 | 826 | 834 | 840 | 846 | 852 | 853 | 860 | 862 | 869 | 877 | 885 | 891 | 897 | 903 | 904 | 911 | input 918 | 920 | 925 | 931 | 932 | 939 | constant 946 | 948 | 954 | 960 | 961 | 968 | output 975 | 977 | 982 | 988 | 989 | 996 | 1003 | 1005 | 1011 | 1018 | hi:lo 1023 | 1024 | 1031 | hi:lo 1036 | 1037 | 1038 | 1045 | 1052 | 1054 | 1060 | 1067 | hi:lo 1073 | 1074 | 1081 | hi:lo 1087 | 1088 | 1089 | 1096 | generic 1103 | 1110 | 1117 | out0 1123 | 1124 | 1131 | out1 1137 | 1138 | 1145 | in0 1151 | 1152 | 1159 | in1 1165 | 1166 | 1167 | 1168 | -------------------------------------------------------------------------------- /tests/test_skins/test_skins.rst: -------------------------------------------------------------------------------- 1 | Test Skin Option 2 | ================ 3 | 4 | This test checks whether the global and per diagram skin setting work as intended. 5 | 6 | Global Skin Option Setting 7 | -------------------------- 8 | 9 | The global skin setting is achieved by setting the ``verilog_diagram_skin`` 10 | variable in the ``conf.py`` script. 11 | 12 | Here is the fragment of the ``conf.py`` script:: 13 | 14 | verilog_diagram_skin = os.path.realpath('skin-purple.svg') 15 | 16 | The following ``hdl-diagram`` diagram should be placed in an RST file:: 17 | 18 | .. hdl-diagram:: adder.v 19 | :type: netlistsvg 20 | :module: ADDER 21 | 22 | Below you can see the output of the directive. The diagram presented below 23 | should be black-purple. 24 | 25 | .. hdl-diagram:: adder.v 26 | :type: netlistsvg 27 | :module: ADDER 28 | 29 | Per Diagram Skin Setting 30 | ------------------------ 31 | 32 | Per diagram skin setting is achieved by using the ``:skin:`` option with 33 | the ``hdl-diagram`` directive. 34 | 35 | The following ``hdl-diagram`` directive should be placed in an RST file:: 36 | 37 | .. hdl-diagram:: adder.v 38 | :type: netlistsvg 39 | :module: ADDER 40 | :skin: skin-yellow.svg 41 | 42 | .. hdl-diagram:: adder.v 43 | :type: netlistsvg 44 | :module: ADDER 45 | :skin: skin-yellow.svg 46 | 47 | Below you can see the output of the directive. The diagram presented below 48 | should be black-yellow. 49 | 50 | Overwrite the Global Skin Setting 51 | --------------------------------- 52 | 53 | It is possible to overwrite the global skin settings using the ``:skin:`` option. 54 | To reset the skin setting to the default value, you can use the ``:skin: default`` 55 | setting. 56 | 57 | The following ``hdl-diagram`` directive should be placed in an RST file:: 58 | 59 | .. hdl-diagram:: adder.v 60 | :type: netlistsvg 61 | :module: ADDER 62 | :skin: default 63 | 64 | Below you can see the output of the directive. The diagram presented below 65 | should be black-white. 66 | 67 | .. hdl-diagram:: adder.v 68 | :type: netlistsvg 69 | :module: ADDER 70 | :skin: default 71 | -------------------------------------------------------------------------------- /tests/test_yosys_script/test_yosys_script.rst: -------------------------------------------------------------------------------- 1 | Test Yosys Script Option 2 | ======================== 3 | 4 | This test checks whether the global and per diagram custom yosys script setting 5 | works as intended. 6 | 7 | Yosys Blackbox Diagram 8 | ---------------------- 9 | 10 | The following examples are related to the Yosys BlackBox diagram. 11 | The same checks are provided for Yosys-AIG diagrams and Netlistsvg diagrams. 12 | There are presented in the next sections of this file. 13 | 14 | Global script test 15 | ++++++++++++++++++ 16 | 17 | The global Yosys script setting is achieved by placing 18 | the ``verilog_diagram_yosys_script`` variable in the ``conf.py`` script. 19 | 20 | Here is the fragment of the ``conf.py`` script:: 21 | 22 | verilog_diagram_yosys_script = os.path.realpath('yosys_script.ys') 23 | 24 | The following ``hdl-diagram`` diagram should be placed in an RST file:: 25 | 26 | .. hdl-diagram:: adder.v 27 | :type: yosys-blackbox 28 | :module: ADDER 29 | 30 | Below you can see the output of the directive: 31 | 32 | .. hdl-diagram:: adder.v 33 | :type: yosys-blackbox 34 | :module: ADDER 35 | 36 | .. note:: Since the commands used in the custom scripts do not modify the design, 37 | the custom script usage will be visible in the sphinx build log. 38 | 39 | Script per diagram 40 | ++++++++++++++++++ 41 | 42 | Per diagram Yosys script setting is achieved by using the ``:yosys_script:`` 43 | option with the ``hdl-diagram`` directive. 44 | 45 | Here is the example of a ``hdl-diagram`` directive that should be 46 | placed in an RST file:: 47 | 48 | .. hdl-diagram:: adder.v 49 | :type: yosys-blackbox 50 | :module: ADDER 51 | :yosys_script: yosys_script2.ys 52 | 53 | Below you can see the output of the directive: 54 | 55 | .. hdl-diagram:: adder.v 56 | :type: yosys-blackbox 57 | :module: ADDER 58 | :yosys_script: yosys_script2.ys 59 | 60 | .. note:: Since the Yosys ommands used in the custom scripts do not modify 61 | the design, the custom script usage will be visible in the sphinx build log. 62 | 63 | Global overwrite 64 | ++++++++++++++++ 65 | 66 | It is possible to overwrite the global Yosys script setting using 67 | the ``:yosys_script:`` option. To reset the setting to the default value, 68 | you can use the ``:yosys_script: default`` setting. 69 | 70 | Here is an example of a ``hdl-diagram`` directive that should be 71 | placed in an RST file:: 72 | 73 | .. hdl-diagram:: adder.v 74 | :type: yosys-blackbox 75 | :module: ADDER 76 | :yosys_script: default 77 | 78 | Below you can see the output of the directive: 79 | 80 | .. hdl-diagram:: adder.v 81 | :type: yosys-blackbox 82 | :module: ADDER 83 | :yosys_script: default 84 | 85 | .. note:: Since the Yosys commands used in the custom scripts do not modify 86 | the design, the custom script usage will be visible in the sphinx build log. 87 | 88 | Yosys Blackbox Diagram 89 | ---------------------- 90 | 91 | Global script test 92 | ++++++++++++++++++ 93 | 94 | .. code-block:: rst 95 | 96 | .. hdl-diagram:: adder.v 97 | :type: yosys-aig 98 | :module: ADDER 99 | 100 | .. hdl-diagram:: adder.v 101 | :type: yosys-aig 102 | :module: ADDER 103 | 104 | Script per diagram 105 | ++++++++++++++++++ 106 | 107 | .. code-block:: rst 108 | 109 | .. hdl-diagram:: adder.v 110 | :type: yosys-aig 111 | :module: ADDER 112 | :yosys_script: yosys_script2.ys 113 | 114 | .. hdl-diagram:: adder.v 115 | :type: yosys-aig 116 | :module: ADDER 117 | :yosys_script: yosys_script2.ys 118 | 119 | Global overwrite 120 | ++++++++++++++++ 121 | 122 | .. code-block:: rst 123 | 124 | .. hdl-diagram:: adder.v 125 | :type: yosys-aig 126 | :module: ADDER 127 | :yosys_script: default 128 | 129 | .. hdl-diagram:: adder.v 130 | :type: yosys-aig 131 | :module: ADDER 132 | :yosys_script: default 133 | 134 | 135 | Netlistsvg diagram 136 | ------------------ 137 | 138 | Global script test 139 | ++++++++++++++++++ 140 | 141 | .. code-block:: rst 142 | 143 | .. hdl-diagram:: adder.v 144 | :type: netlistsvg 145 | :module: ADDER 146 | :yosys_script: default 147 | 148 | .. hdl-diagram:: adder.v 149 | :type: netlistsvg 150 | :module: ADDER 151 | :yosys_script: default 152 | 153 | Script per diagram 154 | ++++++++++++++++++ 155 | 156 | .. code-block:: rst 157 | 158 | .. hdl-diagram:: adder.v 159 | :type: netlistsvg 160 | :module: ADDER 161 | :yosys_script: default 162 | 163 | .. hdl-diagram:: adder.v 164 | :type: netlistsvg 165 | :module: ADDER 166 | :yosys_script: default 167 | 168 | Global overwrite 169 | ++++++++++++++++ 170 | 171 | .. code-block:: rst 172 | 173 | .. hdl-diagram:: adder.v 174 | :type: netlistsvg 175 | :module: ADDER 176 | :yosys_script: default 177 | 178 | .. hdl-diagram:: adder.v 179 | :type: netlistsvg 180 | :module: ADDER 181 | :yosys_script: default 182 | 183 | -------------------------------------------------------------------------------- /tests/test_yosys_script/yosys_script.ys: -------------------------------------------------------------------------------- 1 | stat 2 | -------------------------------------------------------------------------------- /tests/test_yosys_script/yosys_script2.ys: -------------------------------------------------------------------------------- 1 | help 2 | -------------------------------------------------------------------------------- /tests/test_yosys_type/test_yosys_path.rst: -------------------------------------------------------------------------------- 1 | Test Yowasp - path 2 | ================== 3 | 4 | This test checks whether the ability to switch between different Yosys types 5 | works as intended. This functionality is enabled by ``verilog_domain_yosys`` 6 | variable, which can take the following values: 7 | 8 | - ``yowasp`` (default) 9 | - ``system`` 10 | - ```` 11 | 12 | The diagrams presented below have been generated using the ```` option. 13 | 14 | Here is the fragment of the ``conf.py`` script, used to configure the extension: 15 | 16 | .. literalinclude:: conf.py 17 | :lines: 58 18 | 19 | Yosys BlackBox Diagram 20 | ---------------------- 21 | 22 | .. code-block:: rst 23 | 24 | .. hdl-diagram:: adder.v 25 | :type: yosys-blackbox 26 | :module: ADDER 27 | 28 | .. hdl-diagram:: adder.v 29 | :type: yosys-blackbox 30 | :module: ADDER 31 | 32 | Yosys AIG Diagram 33 | ----------------- 34 | 35 | .. code-block:: rst 36 | 37 | .. hdl-diagram:: adder.v 38 | :type: yosys-aig 39 | :module: ADDER 40 | 41 | .. hdl-diagram:: adder.v 42 | :type: yosys-aig 43 | :module: ADDER 44 | 45 | Netlistsvg Diagram 46 | ------------------ 47 | 48 | .. code-block:: rst 49 | 50 | .. hdl-diagram:: adder.v 51 | :type: netlistsvg 52 | :module: ADDER 53 | 54 | .. hdl-diagram:: adder.v 55 | :type: netlistsvg 56 | :module: ADDER 57 | -------------------------------------------------------------------------------- /tests/test_yosys_type/test_yosys_system.rst: -------------------------------------------------------------------------------- 1 | Test Yowasp - system 2 | ==================== 3 | 4 | This test checks whether the ability to switch between different Yosys types 5 | works as intended. This functionality is enabled by ``verilog_domain_yosys`` 6 | variable, which can take the following values: 7 | 8 | - ``yowasp`` (default) 9 | - ``system`` 10 | - ```` 11 | 12 | The diagrams presented below have been generated using the ``system`` option. 13 | 14 | Here is the fragment of the ``conf.py`` script, used to configure the extension:: 15 | 16 | verilog_diagram_yosys = 'system' 17 | 18 | Yosys BlackBox Diagram 19 | ---------------------- 20 | 21 | .. code-block:: rst 22 | 23 | .. hdl-diagram:: adder.v 24 | :type: yosys-blackbox 25 | :module: ADDER 26 | 27 | .. hdl-diagram:: adder.v 28 | :type: yosys-blackbox 29 | :module: ADDER 30 | 31 | Yosys AIG Diagram 32 | ----------------- 33 | 34 | .. code-block:: rst 35 | 36 | .. hdl-diagram:: adder.v 37 | :type: yosys-aig 38 | :module: ADDER 39 | 40 | .. hdl-diagram:: adder.v 41 | :type: yosys-aig 42 | :module: ADDER 43 | 44 | Netlistsvg Diagram 45 | ------------------ 46 | 47 | .. code-block:: rst 48 | 49 | .. hdl-diagram:: adder.v 50 | :type: netlistsvg 51 | :module: ADDER 52 | 53 | .. hdl-diagram:: adder.v 54 | :type: netlistsvg 55 | :module: ADDER 56 | 57 | -------------------------------------------------------------------------------- /tests/test_yosys_type/test_yosys_yowasp.rst: -------------------------------------------------------------------------------- 1 | Test Yowasp - yowasp 2 | ==================== 3 | 4 | This test checks whether the ability to switch between different Yosys types 5 | works as intended. This functionality is enabled by ``verilog_domain_yosys`` 6 | variable, which can take the following values: 7 | 8 | - ``yowasp`` (default) 9 | - ``system`` 10 | - ```` 11 | 12 | The diagrams presented below have been generated using the ```` option. 13 | 14 | Here is the fragment of the ``conf.py`` script, used to configure the extension:: 15 | 16 | verilog_diagram_yosys = 'yowasp' 17 | 18 | .. note:: ``yowasp`` is the default setting. The configuration presented above can be omitted. 19 | 20 | Yosys BlackBox Diagram 21 | ---------------------- 22 | 23 | .. code-block:: rst 24 | 25 | .. hdl-diagram:: adder.v 26 | :type: yosys-blackbox 27 | :module: ADDER 28 | 29 | .. hdl-diagram:: adder.v 30 | :type: yosys-blackbox 31 | :module: ADDER 32 | 33 | Yosys AIG Diagram 34 | ----------------- 35 | 36 | .. code-block:: rst 37 | 38 | .. hdl-diagram:: adder.v 39 | :type: yosys-aig 40 | :module: ADDER 41 | 42 | .. hdl-diagram:: adder.v 43 | :type: yosys-aig 44 | :module: ADDER 45 | 46 | Netlistsvg Diagram 47 | ------------------ 48 | 49 | .. code-block:: rst 50 | 51 | .. hdl-diagram:: adder.v 52 | :type: netlistsvg 53 | :module: ADDER 54 | 55 | .. hdl-diagram:: adder.v 56 | :type: netlistsvg 57 | :module: ADDER 58 | --------------------------------------------------------------------------------