├── .github └── workflows │ ├── codeql-analysis.yml │ ├── coverage.yml │ ├── macos-build.yml │ ├── reuse.yml │ ├── ubuntu-build.yml │ └── valgrind.yml ├── .gitignore ├── .gitmodules ├── .reuse └── dep5 ├── AUTHORS ├── CMakeLists.txt ├── LICENSE ├── LICENSES ├── Apache-2.0.txt └── CC0-1.0.txt ├── README.md ├── cmake ├── CMakeLists.txt └── FindNajaVerilog.cmake ├── src ├── CMakeLists.txt ├── NajaVerilogSnippet.cpp ├── VerilogConstructor.cpp ├── VerilogConstructor.h ├── VerilogException.h ├── VerilogParser.yy ├── VerilogScanner.h ├── VerilogScanner.ll ├── VerilogTypes.cpp └── VerilogTypes.h ├── test ├── CMakeLists.txt ├── NajaVerilogTest012.cpp ├── NajaVerilogTest10.cpp ├── NajaVerilogTest11.cpp ├── NajaVerilogTest12.cpp ├── NajaVerilogTest13.cpp ├── NajaVerilogTest14.cpp ├── NajaVerilogTest15.cpp ├── NajaVerilogTest3.cpp ├── NajaVerilogTest4.cpp ├── NajaVerilogTest5.cpp ├── NajaVerilogTest6.cpp ├── NajaVerilogTest7.cpp ├── NajaVerilogTest8.cpp ├── NajaVerilogTest9.cpp ├── NajaVerilogTestErrors.cpp ├── NajaVerilogTestMultipleFiles.cpp ├── VerilogConstructorTest.cpp ├── VerilogConstructorTest.h └── benchmarks │ ├── errors │ ├── error0.v │ ├── error1.v │ └── error2.v │ ├── multifiles │ ├── mod0.v │ ├── mod1.v │ └── top.v │ ├── test0.v │ ├── test1.v │ ├── test10.v │ ├── test11.v │ ├── test12.v │ ├── test13.v │ ├── test14.v │ ├── test15.v │ ├── test2.v │ ├── test3.v │ ├── test4.v │ ├── test5.v │ ├── test6.v │ ├── test7.v │ ├── test8.v │ └── test9.v └── thirdparty └── CMakeLists.txt /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "main" ] 20 | #schedule: 21 | # - cron: '23 14 * * 6' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'cpp' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | with: 43 | fetch-depth: 0 44 | submodules: true 45 | 46 | # install dependencies 47 | - name: Install dependencies 48 | run: sudo apt-get update && sudo apt-get install -yq libfl-dev 49 | 50 | # Initializes the CodeQL tools for scanning. 51 | - name: Initialize CodeQL 52 | uses: github/codeql-action/init@v2 53 | with: 54 | languages: ${{ matrix.language }} 55 | # If you wish to specify custom queries, you can do so here or in a config file. 56 | # By default, queries listed here will override any specified in a config file. 57 | # Prefix the list here with "+" to use these queries and those in the config file. 58 | 59 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 60 | # queries: security-extended,security-and-quality 61 | 62 | 63 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 64 | # If this step fails, then you should remove it and run the build manually (see below) 65 | - name: Autobuild 66 | uses: github/codeql-action/autobuild@v2 67 | 68 | # ℹ️ Command-line programs to run using the OS shell. 69 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 70 | 71 | # If the Autobuild fails above, remove it and uncomment the following three lines. 72 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 73 | 74 | # - run: | 75 | # echo "Run, Build Application using script" 76 | # ./location_of_script_within_repo/buildscript.sh 77 | 78 | - name: Perform CodeQL Analysis 79 | uses: github/codeql-action/analyze@v2 80 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: coverage 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 11 | BUILD_TYPE: Debug 12 | 13 | jobs: 14 | build: 15 | # The CMake configure and build commands are platform agnostic and should work equally 16 | # well on Windows or Mac. You can convert this to a matrix build if you need 17 | # cross-platform coverage. 18 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 19 | runs-on: ubuntu-22.04 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | submodules: true 26 | 27 | - name: Install dependencies 28 | # install dependencies 29 | run: sudo apt-get update && sudo apt-get install -yq libfl-dev lcov 30 | 31 | - name: Clean build directory 32 | run: rm -rf ${{github.workspace}}/build 33 | 34 | - name: Configure CMake 35 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 36 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 37 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCODE_COVERAGE=ON 38 | 39 | - name: Build 40 | # Build your program with the given configuration 41 | run: cmake --build ${{github.workspace}}/build -j 4 --config ${{env.BUILD_TYPE}} 42 | 43 | - name: Test 44 | working-directory: ${{github.workspace}}/build 45 | # Execute tests defined by the CMake configuration. 46 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 47 | run: ctest -VV -C ${{env.BUILD_TYPE}} 48 | 49 | - name: lcov 50 | working-directory: ${{github.workspace}}/build 51 | run: | 52 | lcov --directory . --capture --output-file coverage.info 53 | lcov --remove coverage.info --output-file coverage.info '/usr/*' '*/naja-verilog/test/*' '*/naja-verilog/thirdparty/*' 54 | lcov --list coverage.info 55 | - name: Upload coverage to Codecov 56 | uses: codecov/codecov-action@v4 57 | env: 58 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 59 | with: 60 | fail_ci_if_error: true 61 | file: ${{github.workspace}}/build/coverage.info 62 | disable_search: true 63 | flags: unittests 64 | name: codecov-umbrella 65 | verbose: true 66 | -------------------------------------------------------------------------------- /.github/workflows/macos-build.yml: -------------------------------------------------------------------------------- 1 | name: macOS Build 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 11 | BUILD_TYPE: Debug 12 | 13 | jobs: 14 | build: 15 | # The CMake configure and build commands are platform agnostic and should work equally 16 | # well on Windows or Mac. You can convert this to a matrix build if you need 17 | # cross-platform coverage. 18 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 19 | runs-on: ${{ matrix.os }} 20 | 21 | strategy: 22 | matrix: 23 | os: [macos-13, macos-14, macos-15] 24 | 25 | steps: 26 | - uses: actions/checkout@v4 27 | with: 28 | submodules: true 29 | # install dependencies 30 | - name: Install dependencies 31 | run: brew install bison flex 32 | 33 | - name: set env variable for macos-13 34 | run: echo "/usr/local/opt/flex/bin" >> $GITHUB_PATH; echo "/usr/local/opt/bison/bin" >> $GITHUB_PATH 35 | 36 | - name: set env variable for macos-14 and further 37 | run: echo "/opt/homebrew/opt/flex/bin" >> $GITHUB_PATH; echo "/opt/homebrew/opt/bison/bin" >> $GITHUB_PATH 38 | 39 | - name: Configure CMake 40 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 41 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 42 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_SANITIZERS=OFF 43 | 44 | - name: Build 45 | # Build your program with the given configuration 46 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 47 | 48 | - name: Test 49 | working-directory: ${{github.workspace}}/build 50 | # Execute tests defined by the CMake configuration. 51 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 52 | run: ctest -VV -C ${{env.BUILD_TYPE}} 53 | -------------------------------------------------------------------------------- /.github/workflows/reuse.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. 2 | # 3 | # SPDX-License-Identifier: CC0-1.0 4 | 5 | name: REUSE Compliance Check 6 | 7 | on: [push, pull_request] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: REUSE Compliance Check 15 | uses: fsfe/reuse-action@v2 16 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu-build.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu Build 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 11 | BUILD_TYPE: Debug 12 | 13 | jobs: 14 | build: 15 | # The CMake configure and build commands are platform agnostic and should work equally 16 | # well on Windows or Mac. You can convert this to a matrix build if you need 17 | # cross-platform coverage. 18 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 19 | runs-on: ${{ matrix.os }} 20 | 21 | strategy: 22 | matrix: 23 | os: [ubuntu-24.04, ubuntu-22.04] 24 | 25 | steps: 26 | - uses: actions/checkout@v4 27 | with: 28 | submodules: true 29 | # install dependencies 30 | - name: Install dependencies 31 | run: sudo apt-get update && sudo apt-get install -yq libfl-dev ninja-build #clang 32 | #run: sudo apt-get update #&& sudo apt-get install -yq libboost-dev capnproto libcapnp-dev ninja-build clang 33 | 34 | - name: Configure CMake 35 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 36 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 37 | #xtof: 14/03/2024: deactivate sanitizer for the moment as it is crashing for no reason 38 | #that seems related to naja-verilog in tests 39 | #run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -GNinja -DCMAKE_C_COMPILER=clang -DENABLE_SANITIZERS=ON 40 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -GNinja -DCMAKE_C_COMPILER=clang 41 | 42 | - name: Build 43 | # Build your program with the given configuration 44 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 45 | 46 | - name: Test 47 | working-directory: ${{github.workspace}}/build 48 | # Execute tests defined by the CMake configuration. 49 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 50 | run: ctest --timeout 3000 -VV -C ${{env.BUILD_TYPE}} 51 | -------------------------------------------------------------------------------- /.github/workflows/valgrind.yml: -------------------------------------------------------------------------------- 1 | name: valgrind 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 11 | BUILD_TYPE: Release 12 | 13 | jobs: 14 | build: 15 | # The CMake configure and build commands are platform agnostic and should work equally 16 | # well on Windows or Mac. You can convert this to a matrix build if you need 17 | # cross-platform coverage. 18 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | submodules: true 26 | 27 | - name: Install dependencies 28 | run: sudo apt-get update && sudo apt-get install -yq libfl-dev valgrind 29 | 30 | - name: Configure CMake 31 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 32 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 33 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} 34 | 35 | - name: Build 36 | # Build your program with the given configuration 37 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 38 | 39 | - name: Test 40 | working-directory: ${{github.workspace}}/build/test 41 | run: valgrind --error-exitcode=1 --show-leak-kinds=all --leak-check=full --errors-for-leak-kinds=all ./naja_verilog_tests 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | install 3 | *~ 4 | *.swp -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "thirdparty/googletest"] 2 | path = thirdparty/googletest 3 | url = https://github.com/google/googletest 4 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: naja-verilog 3 | Upstream-Contact: Christophe Alexandre 4 | Source: https://github.com/najaeda/naja-verilog 5 | 6 | Files: .github/workflows/* .gitmodules .gitignore .codecov.yml 7 | Copyright: 2023 The Naja verilog Authors. 8 | License: Apache-2.0 9 | 10 | Files: README.md AUTHORS 11 | Copyright: 2023 The Naja verilog Authors. 12 | License: Apache-2.0 13 | 14 | Files: test/benchmarks/* 15 | Copyright: 2023 The Naja verilog Authors. 16 | License: Apache-2.0 17 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the list of Naja verilog authors for copyright purposes. 2 | # 3 | # This does not necessarily list everyone who has contributed code, since in 4 | # some cases, their employer may be the copyright holder. To see the full list 5 | # of contributors, see the revision history in source control. 6 | Christophe Alexandre 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | cmake_minimum_required(VERSION 3.21) 6 | 7 | project(naja-verilog LANGUAGES CXX) 8 | 9 | set(CMAKE_CXX_STANDARD 20) 10 | 11 | include(GNUInstallDirs) 12 | 13 | #For Finding flex include path on MacOS with homebrew installation 14 | set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /opt/homebrew/opt/flex/include) 15 | set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /usr/local/opt/flex/include) 16 | 17 | find_package(BISON REQUIRED) 18 | find_package(FLEX REQUIRED) 19 | 20 | add_library(naja_verilog_coverage_config INTERFACE) 21 | option(CODE_COVERAGE "Enable coverage reporting" OFF) 22 | if(CODE_COVERAGE) 23 | # Add required flags (GCC & LLVM/Clang) 24 | target_compile_options(naja_verilog_coverage_config INTERFACE 25 | -O0 # no optimization 26 | -g # generate debug info 27 | --coverage # sets all required flags 28 | ) 29 | target_link_options(naja_verilog_coverage_config INTERFACE --coverage) 30 | endif(CODE_COVERAGE) 31 | 32 | add_library(naja_verilog_sanitizers_config INTERFACE) 33 | option(ENABLE_SANITIZERS "Enable sanitizers in compilation" OFF) 34 | if(ENABLE_SANITIZERS) 35 | target_compile_options(naja_verilog_sanitizers_config INTERFACE 36 | -fsanitize=address 37 | -fno-omit-frame-pointer 38 | #-fsanitize=thread 39 | ) 40 | target_link_options(naja_verilog_sanitizers_config INTERFACE 41 | -fsanitize=address 42 | #-fsanitize=thread 43 | ) 44 | endif(ENABLE_SANITIZERS) 45 | 46 | add_subdirectory(src) 47 | 48 | if(PROJECT_IS_TOP_LEVEL) 49 | add_subdirectory(cmake) 50 | if(EXISTS "${PROJECT_SOURCE_DIR}/thirdparty/googletest/CMakeLists.txt") 51 | #Build tests only if module is top level 52 | #and if googletest submodule has been added. 53 | add_subdirectory(thirdparty) 54 | include(CTest) 55 | enable_testing() 56 | add_subdirectory(test) 57 | endif() 58 | endif(PROJECT_IS_TOP_LEVEL) -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 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, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 30 | 31 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 32 | 33 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 34 | 35 | (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and 36 | 37 | (b) You must cause any modified files to carry prominent notices stating that You changed the files; and 38 | 39 | (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 40 | 41 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 42 | 43 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 44 | 45 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 46 | 47 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 48 | 49 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 50 | 51 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 52 | 53 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 54 | 55 | END OF TERMS AND CONDITIONS 56 | 57 | APPENDIX: How to apply the Apache License to your work. 58 | 59 | To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. 60 | 61 | Copyright [yyyy] [name of copyright owner] 62 | 63 | Licensed under the Apache License, Version 2.0 (the "License"); 64 | you may not use this file except in compliance with the License. 65 | You may obtain a copy of the License at 66 | 67 | http://www.apache.org/licenses/LICENSE-2.0 68 | 69 | Unless required by applicable law or agreed to in writing, software 70 | distributed under the License is distributed on an "AS IS" BASIS, 71 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 72 | See the License for the specific language governing permissions and 73 | limitations under the License. 74 | -------------------------------------------------------------------------------- /LICENSES/CC0-1.0.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # naja-verilog 2 | 3 | ![build](https://github.com/najaeda/naja-verilog/actions/workflows/ubuntu-build.yml/badge.svg) 4 | [![codecov](https://codecov.io/gh/najaeda/naja-verilog/branch/main/graph/badge.svg?token=EWV8ZI20EI)](https://codecov.io/gh/najaeda/naja-verilog) 5 | [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 6 | *** 7 | 8 | ## Introduction 9 | 10 | Naja-Verilog is a structural (gate-level) Verilog parser and can be used to read synthesis generated netlists. 11 | 12 | This library provides a verilog interface to [Naja SNL](https://github.com/najaeda/naja), however both projects are not tied and naja-verilog can be integrated in any project needing structural verilog support. 13 | 14 | :information_desk_person: If you have any questions, bug to report or request, please open an issue or send me a [mail](mailto:christophe.alex@gmail.com). 15 | 16 | :star: If you find **Naja-Verilog** interesting, and would like to stay up-to-date, consider starring this repo to help spread the word. 17 | 18 | ### Acknowledgement 19 | 20 | [](https://nlnet.nl/project/Naja) 21 | [](https://nlnet.nl/project/Naja) 22 | 23 | This project is supported and funded by NLNet through the [NGI0 Entrust](https://nlnet.nl/entrust) Fund. 24 | 25 | ### Gate level netlist 26 | 27 | This parser is dedicated to a very small part of [verilog](https://en.wikipedia.org/wiki/Verilog): the subset allowing to describe hierarchical gate level netlists. This is the format found at the output of synthesis tools such as [Yosys](https://github.com/YosysHQ/yosys). 28 | 29 | To parse complete RTL level verilog or system verilog, please use projects such as: [Verible](https://github.com/chipsalliance/verible). 30 | Apart the language support, the main difference with such RTL level parsing systems is that naja-verilog does not construct any AST but allows to construct the netlist on the fly while visiting the verilog source. Purpose is to reduce memory footprint and accelerate parsing time. 31 | 32 | A comparable project can be found here: [Parser-Verilog](https://github.com/OpenTimer/Parser-Verilog). 33 | 34 | 35 |
[ ↑ Back to top ↑ ]
36 | 37 | *** 38 | 39 | ## Compilation 40 | 41 | ### Getting sources 42 | 43 | ```bash 44 | # First clone the repository and go inside it 45 | git clone https://github.com/najaeda/naja-verilog.git 46 | cd naja-verilog 47 | git submodule init 48 | git submodule update 49 | ``` 50 | 51 | ### Dependencies 52 | 53 | Mandatory dependencies: 54 | 1. [cmake](https://cmake.org): at least 3.22 version. 55 | 2. [Bison](https://www.gnu.org/software/bison) 56 | 3. [Flex](https://github.com/westes/flex) 57 | 58 | Embedded dependencies, through git sub module: [google test](https://github.com/google/googletest). 59 | 60 | On Ubuntu: 61 | 62 | ```bash 63 | sudo apt-get install bison 64 | sudo apt-get install flex 65 | ``` 66 | 67 | Using nix-shell: 68 | 69 | ```bash 70 | nix-shell -p cmake bison flex 71 | ``` 72 | 73 | On macOS, using [Homebrew](https://brew.sh/): 74 | 75 | ```bash 76 | brew install cmake bison flex 77 | ``` 78 | 79 | Ensure the versions of `bison` and `flex` installed via Homebrew take precedence over the macOS defaults by modifying your $PATH environment variable as follows: 80 | 81 | ```bash 82 | export PATH="/opt/homebrew/opt/flex/bin:/opt/homebrew/opt/bison/bin:$PATH" 83 | ``` 84 | 85 | 86 | ### Building and Installing 87 | 88 | ```bash 89 | #First define an env variable that points to the directory where you want naja-verilog to be installed: 90 | export NAJA_INSTALL= 91 | # Create a build dir and go inside it 92 | mkdir build 93 | cd build 94 | cmake -DCMAKE_INSTALL_PREFIX=$NAJA_INSTALL 95 | #For instance: cmake ~/srcs/naja-verilog -DCMAKE_INSTALL_PREFIX=$NAJA_INSTALL 96 | make 97 | make test 98 | make install 99 | ``` 100 | 101 | 102 | 103 | *** 104 | 105 | ## Create your own parser 106 | 107 | Best starting point is to copy existing examples/implementations: 108 | 109 | * [NajaVerilogSnippet](https://github.com/najaeda/naja-verilog/blob/main/src/NajaVerilogSnippet.cpp): very simple snippet application verbosely printing visited objects. 110 | * [VerilogConstructorTest](https://github.com/najaeda/naja-verilog/blob/main/test/VerilogConstructorTest.h): Example class used in Naja-verilog unit tests: visit verilog and collect in simple data structures. 111 | * [Unit tests](https://github.com/najaeda/naja-verilog/blob/main/test): covers trough unit testing most of the parser aspects. 112 | * [SNLVRLConstructor](https://github.com/najaeda/naja/blob/main/src/snl/formats/verilog/frontend/SNLVRLConstructor.h): More concrete example showing Naja SNL (C++ gate netlist data structure) construction. 113 | 114 | The principle of the parser is straightforward: inherit from [VerilogConstructor](https://github.com/najaeda/naja-verilog/blob/main/src/VerilogConstructor.h) and override [callback](#callbacks) methods launched while visiting verilog source. 115 | 116 | ### Two passes Parsing 117 | 118 | As ordering of verilog modules in single or across multiple files is not preknown and module interfaces need to be created before instances and connectivity are created, parsing can be done in a two pass way with: 119 | 120 | 1. Parse modules, ports and parameters. Ignore instances and connectivity. Construct all interfaces. 121 | 2. Reparse. Ignore ports and parameters. Parse instances and nets. Construct connectivity. 122 | 123 | 124 | 125 | ## Callbacks 126 | 127 | Stuctures (Identifier, Net, Port, Expression) details constructed by following callbacks can be found in [VerilogType.h](https://github.com/najaeda/naja-verilog/blob/main/src/VerilogTypes.h) header. 128 | 129 | An Identifier is a struct that holds the unescaped string. It also includes a boolean flag indicating whether the collected identifier was escaped or not. 130 | 131 | ### Callbacks for Module 132 | 133 | #### Starting a Module 134 | 135 | ```c++ 136 | void startModule(const naja::verilog::Identifier& module); 137 | ``` 138 | 139 | This callback is invoked when a module declaration begins. It receives the identifier of the module as an argument. 140 | 141 | For instance, the callback is called with **identifier:{name_="foo",escaped_=false}** for the Verilog module declaration below: 142 | 143 | ```verilog 144 | module foo; 145 | ``` 146 | 147 | #### Ending a Module 148 | 149 | ```c++ 150 | void endModule(); 151 | ``` 152 | 153 | This function is called upon reaching the end of a module declaration. It serves as a notifier for the end of the module's scope, allowing for any necessary cleanup. 154 | 155 | The corresponding verilog end declaration is: 156 | 157 | ```verilog 158 | endmodule //foo 159 | ``` 160 | 161 | ### Callbacks for Ports 162 | 163 | #### Simple Port Declaration in Module Interface 164 | 165 | ```c++ 166 | void moduleInterfaceSimplePort(const naja::verilog::Identifier& port) 167 | ``` 168 | 169 | Triggered when a module uses a simple declaration (only the port identifier) for ports. It will be called multiple times depending on the number of ports declared. 170 | 171 | For example, it is called with **identifier.name_="a", identifier.{name_="b@", escaped_=true}, and identifier.name_="c"** for: 172 | 173 | ```verilog 174 | module foo(a, \b@ , c); 175 | ``` 176 | 177 | #### Port details in module implementation 178 | 179 | Associated to previous method, following method collects port details: direction and size in module implementation section. 180 | 181 | ```c++ 182 | void moduleImplementationPort(const Port& port) 183 | ``` 184 | 185 | is called for each port listed in the implementation section of a module. 186 | 187 | ```verilog 188 | module foo(\a# , b, c); 189 | input a; 190 | output [3:0] b; 191 | inout c; 192 | //will invoke 3 times moduleImplementationPort with: 193 | //Port identifier_={a#,true}, direction=Input, isBus()=true, range_.msb_=3, range_.lsb_=0 194 | //Port identifier_={b,false}, direction=Output, isBus()=true, range_.msb_=0, range_.lsb_=3 195 | //Port identifier_={c,false}, direction=InOut, isBus()=false 196 | ``` 197 | 198 | #### Port complete declaration in Module interface 199 | 200 | ```c++ 201 | void moduleInterfaceCompletePort(const Port& port) 202 | ``` 203 | 204 | Invoked for a complete interface port declaration, detailing port direction (input/output/inout) and in case of bus: msb and lsb. 205 | 206 | ```verilog 207 | module foo(input[3:0] a, output[0:3] b, inout c); 208 | //will invoke 3 times moduleInterfaceCompletePort with: 209 | //Port identifier_={a,false}, direction=Input, isBus()=true, range_.msb_=3, range_.lsb_=0 210 | //Port identifier_={b,false}, direction=Output, isBus()=true, range_.msb_=0, range_.lsb_=3 211 | //Port identifier_={c,false}, direction=InOut, isBus()=false 212 | ``` 213 | 214 | ### Callbacks for Nets 215 | 216 | ```c++ 217 | void addNet(const Net& net) 218 | ``` 219 | 220 | This callback is invoked for each net declaration within a module and will construct **Net** structure containing net details: msb, lsb (for busses) and type: Wire, Supply0 or Supply1. 221 | 222 | ```verilog 223 | wire net0, net1, net2; // constructs 3 Net(s) named net0, net1, net2, type_=Wire, isBus()=false 224 | wire [31:0] net3; // construct 1 Net named net3, type_=Wire, isBus()=true, range_.msb_=31, range_.lsb_=0 225 | wire [-2:1] net4; // construct 1 Net named net4, type_=Wire, isBus()=true, range_.msb_=-2, range_.lsb_=1 226 | supply0 constant0; // construct 1 Net named constant0, type_=Supply0, isBus()=false 227 | supply1 constant1; // construct 1 Net named constant1, type_=Supply1, isBus()=false 228 | ``` 229 | 230 | #### Assign statements 231 | 232 | ```c++ 233 | void addAssign(const Identifiers& identifiers, const Expression& expression) 234 | ``` 235 | 236 | is called for each assign statement, facilitating the capture of signal assignments. 237 | 238 | Below are Verilog examples followed by pseudo C++ representations of the data structures that might be constructed by this callback. 239 | 240 | ```verilog 241 | assign n0 = n1; 242 | //identifiers = { {identifier_={n0,false}, range_.valid_=false} } 243 | //expressions = 244 | // { 245 | // { 246 | // value_.index()=naja::verilog::Expression::Type::IDENTIFIER 247 | // with auto id=std::get(value_) 248 | // id.identifier_={"n1",false}, id.range_.valid_=false 249 | // } 250 | // } 251 | ``` 252 | 253 | ```verilog 254 | assign n1 = 1'b0; 255 | //identifiers = { {identifier_={n1,false}, range_.valid_=false} } 256 | //expressions = 257 | // { 258 | // { 259 | // value_.index()=naja::verilog::Expression::Type::NUMBER 260 | // with auto nb=std::get(value_) 261 | // nb.base_=naja::verilog::BasedNumber::BINARY 262 | // nb.sign_=true, nb.signed_=false, nb.size_=1, nb.digits_="0" 263 | // } 264 | // } 265 | ``` 266 | 267 | ```verilog 268 | assign { n2[3:2], n2[1:0] } = { n0, n1, 2'h2 }; 269 | //identifiers = 270 | // { 271 | // { identifier_={n2,false}, range_.valid_=true, range_.msb_=3, range_.lsb=3 }, 272 | // { identifier_={n2,false}, range_.valid_=true, range_.msb_=1, range_.lsb=0 }, 273 | // } 274 | //expressions = 275 | // { 276 | // { 277 | // value_.index()=naja::verilog::Expression::Type::CONCATENATION 278 | // with auto concat=std::get(value_) 279 | // concat[0] is an Identifier identifier_={n0,false}, range_.valid_=false 280 | // concat[1] is an Identifier identifier_={n1,false}, range_.valid_=false 281 | // concat[2] is an NUMBER with: 282 | // nb.base_=naja::verilog::BasedNumber::HEX 283 | // nb.size_=2, nb.digits_="2" 284 | // } 285 | // } 286 | ``` 287 | 288 | ### Callback for instances 289 | 290 | #### Starting Instantiation 291 | 292 | ```c++ 293 | void startInstantiation(const naja::verilog::Identifier& model) 294 | ``` 295 | 296 | allows to collect module (used as a model) name for one or multiple instanciations. This method will collect `model={Model,false}` for the two following declarations: 297 | 298 | ```verilog 299 | Model ins(); 300 | Model ins0(), ins1(), ins2(); 301 | ``` 302 | 303 | #### Adding an Instance 304 | 305 | ```c++ 306 | void addInstance(const naja::verilog::Identifier& instance) 307 | ``` 308 | 309 | will be called 3 times with `instance={ins1,false}, {ins2,false}, {ins3,false}` for following declaration: 310 | 311 | ```verilog 312 | Model ins(), ins2(), ins3(); 313 | ``` 314 | 315 | #### Ending Instantiation 316 | 317 | ```c++ 318 | void endInstantiation(); 319 | ``` 320 | 321 | is called at the conclusion of an instance declaration, it signals that all instances have been processed and allows for post-processing cleanup. 322 | 323 | ### Callbacks for Instance Connections 324 | 325 | #### Named Port Connection 326 | 327 | ```c++ 328 | void addInstanceConnection(const naja::verilog::Identifier& port, const Expression& expression); 329 | ``` 330 | 331 | This function is called for each named port connection in an instance, capturing the relationship between the port and its connected net or expression. 332 | 333 | ```verilog 334 | mod1 inst2(.i0(net4[3:6]), .o0(net5)); 335 | //addInstanceConnection is called 2 times with: 336 | //port=Identifier{"i0",false} 337 | //expression_.value_.index() = naja::verilog::Expression::Type::IDENTIFIER, 338 | //with auto id = std::get(expression.value_) 339 | //id.identifier_={"net4",false}, id.isBus=true, id.range_.msb_=3, is.range_.lsb_=6 340 | //and: 341 | //port=Identifier{"o0",false} 342 | //expression_.value_.index() = naja::verilog::Expression::Type::IDENTIFIER, 343 | //with auto id = std::get(expression.value_) 344 | //id.identifier_={"net5",false}, id.isBus=false 345 | ``` 346 | 347 | #### Ordered Port Connection 348 | 349 | ```c++ 350 | void addOrderedInstanceConnection(size_t portIndex, const Expression& expression); 351 | ``` 352 | 353 | is invoked for each port connection when ports are connected by order rather than by name. 354 | 355 | ```verilog 356 | mod1 inst4(net4[7:10], {net0, net1, net2, net3}); 357 | //addOrderedInstanceConnection is called 2 times with: 358 | //portIndex=0 359 | //expression_.value_.index() = naja::verilog::Expression::Type::IDENTIFIER, 360 | //with auto id = std::get(expression.value_) 361 | //id.identifier_={"net4",false}, id.isBus=true, id.range_.msb_=7, is.range_.lsb_=10 362 | //and: 363 | //portIndex=1 364 | //expression_.value_.index() = naja::verilog::Expression::Type::CONCATENATION, 365 | //with auto concat = std::get(expression.value_) 366 | //concat.size()=4 and all values are simple Identifiers 367 | ``` 368 | 369 | ### Callback for Parameter Assignment 370 | 371 | ```c++ 372 | void addParameterAssignment(const naja::verilog::Identifier& parameter, const Expression& expression); 373 | ``` 374 | 375 | This callback function is designed to handle parameter assignments within module instantiations. 376 | 377 | ```verilog 378 | module test(); 379 | mod #( 380 | .PARAM0("VAL"), 381 | ) ins(); 382 | endmodule 383 | //addParameterAssignment is called one time with: 384 | //parameter={"PARAM0",false} and expression is a RangeIdentifier with name="VAL" 385 | ``` 386 | 387 | 388 | -------------------------------------------------------------------------------- /cmake/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | install(FILES FindNajaVerilog.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/naja-verilog/cmake) 6 | -------------------------------------------------------------------------------- /cmake/FindNajaVerilog.cmake: -------------------------------------------------------------------------------- 1 | #[=======================================================================[.rst: 2 | # SPDX-FileCopyrightText: 2023 The Naja verilog authors 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | FindNajaVerilog 6 | ----------- 7 | 8 | Find the naja libraries. 9 | 10 | ``NajaVerilog::NajaVerilog`` 11 | Naja Verilog libraries 12 | 13 | ^^^^^^^^^^^^^^^^ 14 | 15 | This module will set the following variables in your project: 16 | 17 | ``NajaVerilog_FOUND`` 18 | true if Naja Verilog headers and libraries were found 19 | ``NAJA_VERILOG_INCLUDE_DIRS`` 20 | list of the include directories needed to use Naja Verilog 21 | ``NAJA_VERILOG_LIBRARIES`` 22 | Naja Verilog libraries to be linked 23 | 24 | Cache variables 25 | ^^^^^^^^^^^^^^^ 26 | 27 | The following cache variables may also be set: 28 | 29 | ``NAJA_VERILOG_INCLUDE_DIR`` 30 | the directory containing Naja Verilog headers 31 | ``NAJA_VERILOG_LIBRARY`` 32 | path to the Naja Verilog library 33 | ``NAJA_VERILOG_LIBRARY`` 34 | path to the Naja Verilog library 35 | #]=======================================================================] 36 | 37 | find_path(NAJA_VERILOG_INCLUDE_DIR NAMES VerilogConstructor.h 38 | HINTS 39 | $ENV{NAJA_INSTALL}/include 40 | ) 41 | 42 | find_library(NAJA_VERILOG_LIBRARY NAMES naja_verilog 43 | HINTS 44 | $ENV{NAJA_INSTALL}/lib 45 | ) 46 | 47 | set(NAJA_VERILOG_INCLUDE_DIRS ${NAJA_VERILOG_INCLUDE_DIR}) 48 | 49 | include(FindPackageHandleStandardArgs) 50 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(NajaVerilog 51 | REQUIRED_VARS NAJA_VERILOG_INCLUDE_DIR NAJA_VERILOG_LIBRARY) 52 | 53 | if(NajaVerilog_FOUND AND NOT TARGET NajaVerilog::NajaVerilog) 54 | add_library(NajaVerilog::NajaVerilog UNKNOWN IMPORTED) 55 | set_target_properties(NajaVerilog::NajaVerilog PROPERTIES 56 | IMPORTED_LOCATION "${NAJA_VERILOG_LIBRARY}" 57 | INTERFACE_INCLUDE_DIRECTORIES "${NAJA_VERILOG_INCLUDE_DIRS}") 58 | endif() 59 | 60 | mark_as_advanced(NAJA_VERILOG_INCLUDE_DIR NAJA_VERILOG_LIBRARY) 61 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | BISON_TARGET(VerilogParser VerilogParser.yy 6 | ${CMAKE_CURRENT_BINARY_DIR}/VerilogParser.cpp 7 | COMPILE_FLAGS "-Wconflicts-sr -d -v") 8 | FLEX_TARGET(VerilogScanner VerilogScanner.ll 9 | ${CMAKE_CURRENT_BINARY_DIR}/VerilogScanner.cpp) 10 | ADD_FLEX_BISON_DEPENDENCY(VerilogScanner VerilogParser) 11 | 12 | set(SOURCES 13 | ${BISON_VerilogParser_OUTPUTS} 14 | ${FLEX_VerilogScanner_OUTPUTS} 15 | VerilogTypes.cpp 16 | VerilogConstructor.cpp 17 | ) 18 | 19 | set(HEADERS 20 | VerilogTypes.h 21 | VerilogConstructor.h 22 | VerilogException.h 23 | ) 24 | 25 | add_library(naja_verilog STATIC ${SOURCES}) 26 | set_property(TARGET naja_verilog PROPERTY POSITION_INDEPENDENT_CODE ON) 27 | target_link_libraries(naja_verilog PUBLIC naja_verilog_coverage_config naja_verilog_sanitizers_config) 28 | target_include_directories(naja_verilog 29 | PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${FLEX_INCLUDE_DIRS} 30 | PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 31 | 32 | if(PROJECT_IS_TOP_LEVEL) 33 | set_target_properties(naja_verilog PROPERTIES PUBLIC_HEADER "${HEADERS}") 34 | install(TARGETS naja_verilog 35 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 36 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 37 | add_executable(naja_verilog_test NajaVerilogSnippet.cpp) 38 | target_link_libraries(naja_verilog_test naja_verilog) 39 | endif() -------------------------------------------------------------------------------- /src/NajaVerilogSnippet.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "VerilogConstructor.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace { 11 | 12 | void commandLine() { 13 | std::cerr << "naja_verilog_test design.v" << std::endl; 14 | } 15 | 16 | class VerilogConstructorExample: public naja::verilog::VerilogConstructor { 17 | public: 18 | void startModule(const naja::verilog::Identifier& id) override { 19 | std::cout << "Construct Module: " << id.getDescription() << std::endl; 20 | } 21 | void moduleInterfaceSimplePort(const naja::verilog::Identifier& port) override { 22 | std::cout << "Simple Port: " << port.getString() << std::endl; 23 | } 24 | void moduleInterfaceCompletePort(const naja::verilog::Port& port) override { 25 | std::cout << "Complete Port: " << port.getString() << std::endl; 26 | } 27 | void moduleImplementationPort(const naja::verilog::Port& port) override { 28 | std::cout << "Construct Port: " << port.getString() << std::endl; 29 | } 30 | void addNet(const naja::verilog::Net& net) override { 31 | std::cout << "Construct Net: " << net.getString() << std::endl; 32 | } 33 | void startInstantiation(const naja::verilog::Identifier& model) override { 34 | std::cout << "startInstantiation: " << model.getString() << std::endl; 35 | } 36 | void addInstance(const naja::verilog::Identifier& instance) override { 37 | std::cout << "addInstance: " << instance.getString() << std::endl; 38 | } 39 | void addInstanceConnection(const naja::verilog::Identifier& port, const naja::verilog::Expression& expression) override { 40 | std::cout << "addInstanceConnection: " << port.getString() << ": " << expression.getString() << std::endl; 41 | } 42 | void endInstantiation() override { 43 | std::cout << "endInstantiation" << std::endl; 44 | } 45 | void addParameterAssignment(const naja::verilog::Identifier& parameter, const naja::verilog::Expression& expression) override { 46 | std::cout << "addParameterAssignment: " << parameter.getString() << ": " << expression.getString() << std::endl; 47 | } 48 | virtual void addDefParameterAssignment( 49 | const naja::verilog::Identifiers& hierarchicalParameter, 50 | const naja::verilog::ConstantExpression& expression) override { 51 | std::ostringstream oss; 52 | for (size_t i = 0; i < hierarchicalParameter.size(); i++) { 53 | oss << hierarchicalParameter[i].getString(); 54 | if (i < hierarchicalParameter.size() - 1) { 55 | oss << "."; 56 | } 57 | } 58 | std::cout << "addDefParameterAssignment: " 59 | << oss.str() 60 | << ": " << expression.getString() << std::endl; 61 | } 62 | void endModule() override { 63 | std::cout << "endModule" << std::endl; 64 | } 65 | }; 66 | 67 | } 68 | 69 | int main(int argc, char* argv[]) { 70 | if (argc < 2) { 71 | commandLine(); 72 | exit(1); 73 | } 74 | 75 | VerilogConstructorExample constructor; 76 | std::filesystem::path filePath(argv[1]); 77 | constructor.parse(filePath); 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /src/VerilogConstructor.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "VerilogConstructor.h" 6 | 7 | #include 8 | #include "VerilogException.h" 9 | #include "VerilogScanner.h" 10 | #include "VerilogParser.hpp" 11 | 12 | namespace naja { namespace verilog { 13 | 14 | VerilogConstructor::ModuleInterfaceType::ModuleInterfaceType(const ModuleInterfaceTypeEnum& typeEnum): 15 | typeEnum_(typeEnum) 16 | {} 17 | 18 | //LCOV_EXCL_START 19 | std::string VerilogConstructor::ModuleInterfaceType::getString() const { 20 | switch (typeEnum_) { 21 | case ModuleInterfaceType::Unknown: return "Standard"; 22 | case ModuleInterfaceType::PortDeclaration: return "PortDeclaration"; 23 | case ModuleInterfaceType::Port: return "Port"; 24 | } 25 | return "Error"; 26 | } 27 | //LCOV_EXCL_STOP 28 | 29 | //LCOV_EXCL_START 30 | VerilogConstructor::Location VerilogConstructor::getCurrentLocation() const { 31 | return Location(getCurrentPath(), line_, column_); 32 | } 33 | //LCOV_EXCL_STOP 34 | 35 | VerilogConstructor::~VerilogConstructor() { 36 | delete scanner_; 37 | delete parser_; 38 | } 39 | 40 | void VerilogConstructor::parse(const std::filesystem::path& path) { 41 | if (not std::filesystem::exists(path)) { 42 | std::string reason(path.string() + " does not exist"); 43 | throw VerilogException(reason); 44 | } 45 | currentPath_ = path; 46 | std::ifstream inFile(path); 47 | //LCOV_EXCL_START 48 | if (not inFile.good()) { 49 | std::string reason(path.string() + " is not a readable file"); 50 | throw VerilogException(reason); 51 | } 52 | //LCOV_EXCL_STOP 53 | internalParse(inFile); 54 | } 55 | 56 | void VerilogConstructor::parse(const VerilogConstructor::Paths& paths) { 57 | for (auto path: paths) { 58 | parse(path); 59 | } 60 | } 61 | 62 | void VerilogConstructor::internalParse(std::istream &stream) { 63 | delete(scanner_); 64 | scanner_ = new VerilogScanner(&stream); 65 | delete(parser_); 66 | parser_ = new VerilogParser(*scanner_, this); 67 | bool result = parser_->parse(); 68 | } 69 | 70 | void VerilogConstructor::internalStartModule(const naja::verilog::Identifier& id) { 71 | type_ = ModuleInterfaceType::Unknown; 72 | startModule(id); 73 | } 74 | 75 | void VerilogConstructor::internalEndModule() { 76 | endModule(); 77 | } 78 | 79 | void VerilogConstructor::internalModuleInterfaceSimplePort(const naja::verilog::Identifier& id) { 80 | if (type_ == ModuleInterfaceType::Unknown) { 81 | type_ = ModuleInterfaceType::Port; 82 | } 83 | if (type_ == ModuleInterfaceType::PortDeclaration) { 84 | moduleInterfaceCompletePort(Port(id, lastDirection_, lastRange_)); 85 | } else { 86 | moduleInterfaceSimplePort(id); 87 | } 88 | } 89 | 90 | void VerilogConstructor::internalModuleInterfaceCompletePort(const Port& port) { 91 | if (type_ == ModuleInterfaceType::Unknown) { 92 | type_ = ModuleInterfaceType::PortDeclaration; 93 | } 94 | if (type_ == ModuleInterfaceType::Port) { 95 | //Error 96 | } 97 | lastDirection_ = port.direction_; 98 | lastRange_ = port.range_; 99 | moduleInterfaceCompletePort(port); 100 | } 101 | 102 | void VerilogConstructor::internalModuleImplementationPort(const Port& port) { 103 | moduleImplementationPort(port); 104 | } 105 | 106 | }} // namespace verilog // namespace naja -------------------------------------------------------------------------------- /src/VerilogConstructor.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #ifndef __VERILOG_CONSTRUCTOR_H_ 6 | #define __VERILOG_CONSTRUCTOR_H_ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "VerilogTypes.h" 13 | 14 | namespace naja { namespace verilog { 15 | 16 | class VerilogScanner; 17 | class VerilogParser; 18 | 19 | class VerilogConstructor { 20 | friend class VerilogParser; 21 | public: 22 | VerilogConstructor() = default; 23 | ~VerilogConstructor(); 24 | using Paths = std::vector; 25 | void parse(const Paths& paths); 26 | void parse(const std::filesystem::path& path); 27 | 28 | //LCOV_EXCL_START 29 | std::string getCurrentPath() const { return currentPath_; } 30 | struct Location { 31 | std::filesystem::path currentPath_ {}; 32 | unsigned line_ {0}; 33 | unsigned column_ {0}; 34 | 35 | Location() = delete; 36 | Location(const Location&) = default; 37 | Location( 38 | const std::filesystem::path& currentPath, 39 | unsigned line, 40 | unsigned column): 41 | currentPath_(currentPath), 42 | line_(line), 43 | column_(column) 44 | {} 45 | }; 46 | Location getCurrentLocation() const; 47 | //LCOV_EXCL_STOP 48 | void setCurrentLocation(unsigned line, unsigned column) { 49 | line_= line; column_ = column; 50 | } 51 | 52 | //LCOV_EXCL_START 53 | virtual void startModule(const Identifier& id) {} 54 | //Simple Port declaration (only name), no range, no direction in module interface 55 | virtual void moduleInterfaceSimplePort(const Identifier& port) {} 56 | //Complete Port declaration in module interface 57 | virtual void moduleInterfaceCompletePort(const Port& port) {} 58 | virtual void moduleImplementationPort(const Port& port) {} 59 | virtual void addNet(const Net& net) {} 60 | virtual void addAssign(const RangeIdentifiers& identifiers, const Expression& expression) {} 61 | virtual void startInstantiation(const Identifier& model) {} 62 | virtual void addInstance(const Identifier& instance) {} 63 | virtual void addInstanceConnection(const Identifier& port, const Expression& expression) {} 64 | virtual void addOrderedInstanceConnection(size_t portIndex, const Expression& expression) {} 65 | virtual void endInstantiation() {} 66 | virtual void addParameterAssignment(const Identifier& parameter, const Expression& expression) {} 67 | virtual void addDefParameterAssignment( 68 | const Identifiers& hierarchicalParameter, 69 | const ConstantExpression& expression) {} 70 | virtual void addAttribute( 71 | const Identifier& attributeName, 72 | const ConstantExpression& expression) {} 73 | virtual void endModule() {} 74 | //LCOV_EXCL_STOP 75 | private: 76 | class ModuleInterfaceType { 77 | public: 78 | enum ModuleInterfaceTypeEnum { 79 | Unknown, PortDeclaration, Port 80 | }; 81 | ModuleInterfaceType(const ModuleInterfaceTypeEnum& typeEnum); 82 | ModuleInterfaceType(const ModuleInterfaceType& type) = default; 83 | operator const ModuleInterfaceTypeEnum&() const {return typeEnum_;} 84 | std::string getString() const; 85 | private: 86 | ModuleInterfaceTypeEnum typeEnum_; 87 | }; 88 | void internalParse(std::istream& stream); 89 | void internalStartModule(const Identifier& id); 90 | void internalEndModule(); 91 | void internalModuleInterfaceSimplePort(const Identifier& id); 92 | void internalModuleInterfaceCompletePort(const Port& port); 93 | void internalModuleImplementationPort(const Port& port); 94 | 95 | ModuleInterfaceType type_ {ModuleInterfaceType::Unknown}; 96 | Port::Direction lastDirection_ {Port::Direction::Unknown}; 97 | Range lastRange_ {}; 98 | 99 | VerilogScanner* scanner_ {nullptr}; 100 | VerilogParser* parser_ {nullptr}; 101 | std::filesystem::path currentPath_ {}; 102 | unsigned line_ {0}; 103 | unsigned column_ {0}; 104 | }; 105 | 106 | }} // namespace verilog // namespace naja 107 | 108 | #endif /* __VERILOG_CONSTRUCTOR_H_ */ 109 | -------------------------------------------------------------------------------- /src/VerilogException.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #ifndef __VERILOG_EXCEPTION_H_ 6 | #define __VERILOG_EXCEPTION_H_ 7 | 8 | namespace naja { namespace verilog { 9 | 10 | struct VerilogException: public std::exception { 11 | public: 12 | VerilogException() = delete; 13 | VerilogException(const VerilogException&) = default; 14 | 15 | VerilogException(const std::string& reason): 16 | std::exception(), 17 | reason_(reason) 18 | {} 19 | 20 | std::string getReason() const { 21 | return reason_; 22 | } 23 | 24 | //LCOV_EXCL_START 25 | const char* what() const noexcept override { 26 | return reason_.c_str(); 27 | } 28 | //LCOV_EXCL_STOP 29 | 30 | private: 31 | const std::string reason_; 32 | }; 33 | 34 | }} // namespace verilog // namespace naja 35 | 36 | #endif // __VERILOG_EXCEPTION_H_ 37 | -------------------------------------------------------------------------------- /src/VerilogParser.yy: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | %skeleton "lalr1.cc" 6 | %require "3.0" 7 | %define parse.trace 8 | %defines 9 | %define api.namespace {naja::verilog} 10 | %language "c++" 11 | %define api.parser.class {VerilogParser} 12 | 13 | %define parse.error verbose 14 | 15 | %code requires { 16 | 17 | #include "VerilogTypes.h" 18 | namespace naja { namespace verilog { 19 | class VerilogScanner; 20 | class VerilogConstructor; 21 | }} 22 | 23 | namespace { 24 | using Instances = std::vector; 25 | } 26 | 27 | // The following definitions is missing when %locations isn't used 28 | # ifndef YY_NULLPTR 29 | # if defined __cplusplus && 201103L <= __cplusplus 30 | # define YY_NULLPTR nullptr 31 | # else 32 | # define YY_NULLPTR 0 33 | # endif 34 | # endif 35 | 36 | } 37 | 38 | %parse-param { VerilogScanner& scanner } 39 | %parse-param { VerilogConstructor* constructor } 40 | 41 | %code{ 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #include "VerilogException.h" 49 | 50 | /* include for all driver functions */ 51 | #include "VerilogConstructor.h" 52 | #include "VerilogScanner.h" 53 | 54 | 55 | #undef yylex 56 | #define yylex scanner.yylex 57 | 58 | size_t portIndex = 0; 59 | 60 | static naja::verilog::Number generateNumber( 61 | bool hasSize, 62 | const std::string& size, 63 | const std::string& base, 64 | const std::string& digits, 65 | int beginLine, 66 | int beginColumn, 67 | int endLine, 68 | int endColumn) { 69 | if (base.size() == 2) { 70 | //LCOV_EXCL_START 71 | if (not (base[0] == 's' || base[0] == 'S')) { 72 | //Following should not happen as long as lexer is correct 73 | //should this be replaced by an assertion ? 74 | std::ostringstream reason; 75 | reason << "Parser error: "; 76 | if (hasSize) { 77 | reason << "\'" << size << base << digits; 78 | } else { 79 | reason << "\'" << base << digits; 80 | } 81 | reason << " is not a valid number: wrong signed character.\n" 82 | << " begin at line " << beginLine << " col " << beginColumn << '\n' 83 | << " end at line " << endLine << " col " << endColumn << "\n"; 84 | throw naja::verilog::VerilogException(reason.str()); 85 | } 86 | //LCOV_EXCL_STOP 87 | if (hasSize) { 88 | return naja::verilog::Number(size, true, base[1], digits); 89 | } else { 90 | return naja::verilog::Number(true, base[1], digits); 91 | } 92 | } else if (base.size() == 1) { 93 | if (hasSize) { 94 | return naja::verilog::Number(size, false, base[0], digits); 95 | } else { 96 | return naja::verilog::Number(false, base[0], digits); 97 | } 98 | } else { 99 | //LCOV_EXCL_START 100 | //Same as previously: should not be accessible, as this is filtered by lexer. 101 | std::ostringstream reason; 102 | reason << "Parser error: "; 103 | if (hasSize) { 104 | reason << "\'" << size << base << digits; 105 | } else { 106 | reason << "\'" << base << digits; 107 | } 108 | reason << " is not a valid number\n" 109 | << " begin at line " << beginLine << " col " << beginColumn << '\n' 110 | << " end at line " << endLine << " col " << endColumn << "\n"; 111 | throw naja::verilog::VerilogException(reason.str()); 112 | //LCOV_EXCL_STOP 113 | } 114 | } 115 | 116 | } 117 | 118 | %define api.value.type variant 119 | %define parse.assert 120 | 121 | %token MODULE_KW 122 | %token ENDMODULE_KW 123 | %token INOUT_KW 124 | %token INPUT_KW 125 | %token OUTPUT_KW 126 | %token SUPPLY0_KW 127 | %token SUPPLY1_KW 128 | %token WIRE_KW 129 | %token ASSIGN_KW 130 | %token DEFPARAM_KW 131 | %token END 0 "end of file" 132 | 133 | %token IDENTIFIER_TK 134 | %token ESCAPED_IDENTIFIER_TK 135 | %token STRING_TK 136 | %token CONSTVAL_TK BASE_TK BASED_CONSTVAL_TK 137 | %token SIGN_TK 138 | 139 | %type identifier; 140 | //no support for XMRs for the moment 141 | %type hierarchical_net_identifier; 142 | %type module_identifier; 143 | %type name_of_module_instance; 144 | %type parameter_identifier; 145 | 146 | %type port_declaration 147 | %type internal_ports_declaration 148 | %type port_type_io 149 | %type net_type; 150 | %type range; 151 | %type range.opt 152 | %type constant_range_expression.opt; 153 | %type net_identifier; 154 | %type list_of_identifiers; 155 | %type hierarchical_identifier; 156 | %type hierarchical_parameter_identifier; 157 | %type net_lvalue; 158 | %type list_of_net_lvalues; 159 | %type module_instance; 160 | %type port_identifier; 161 | 162 | %type number; 163 | %type constant_primary; 164 | %type constant_expression; 165 | %type constant_mintypmax_expression; 166 | %type unary_operator; 167 | %type primary; 168 | %type expression; 169 | %type expression.opt; 170 | %type mintypmax_expression; 171 | %type mintypmax_expression.opt; 172 | %type concatenation; 173 | %type list_of_expressions; 174 | %type attr_spec_value; 175 | %type attr_spec; 176 | 177 | %locations 178 | %start source_text 179 | 180 | %% 181 | 182 | source_text: list_of_descriptions 183 | 184 | list_of_descriptions: description | list_of_descriptions description; 185 | 186 | description: module_declaration; 187 | 188 | identifier 189 | : IDENTIFIER_TK { $$ = naja::verilog::Identifier($1); } 190 | | ESCAPED_IDENTIFIER_TK { 191 | std::string escaped = $1.substr(1, $1.size()-2); 192 | $$ = naja::verilog::Identifier(escaped, true); 193 | } 194 | 195 | primary 196 | : number { 197 | $$.valid_ = true; $$.value_ = $1; } 198 | //no support for XMRs for the moment: should be hierarchical_identifier below 199 | | identifier constant_range_expression.opt { 200 | $$.valid_ = true; $$.value_ = naja::verilog::RangeIdentifier($1, $2); } 201 | | STRING_TK { $$.valid_ = true; $$.value_ = $1.substr(1, $1.size()-2); } 202 | | concatenation { $$.valid_ = true; $$.value_ = naja::verilog::Concatenation($1); } 203 | ; 204 | 205 | constant_primary 206 | : number { 207 | $$.valid_ = true; $$.value_ = $1; } 208 | | STRING_TK { $$.valid_ = true; $$.value_ = $1.substr(1, $1.size()-2); } 209 | ; 210 | 211 | unary_operator: SIGN_TK; 212 | 213 | constant_expression: constant_primary { 214 | $$ = $1; 215 | } 216 | | unary_operator constant_primary { 217 | auto expression = $2; 218 | if (expression.value_.index() == naja::verilog::ConstantExpression::NUMBER) { 219 | auto number = std::get(expression.value_); 220 | if ($1 == "-") { number.sign_ = false; } 221 | $$.valid_ = true; 222 | $$.value_ = number; 223 | } else { 224 | throw VerilogException("Only constant number expression are supported"); //LCOV_EXCL_LINE 225 | } 226 | } 227 | 228 | range: '[' constant_expression ':' constant_expression ']' { 229 | if ($2.value_.index() == naja::verilog::ConstantExpression::NUMBER and 230 | $4.value_.index() == naja::verilog::ConstantExpression::NUMBER) { 231 | auto number1 = std::get($2.value_); 232 | auto number2 = std::get($4.value_); 233 | $$ = Range(number1.getInt(), number2.getInt()); 234 | } else { 235 | throw VerilogException("Only constant number expression are supported"); //LCOV_EXCL_LINE 236 | } 237 | } 238 | 239 | range.opt: %empty { $$.valid_ = false; } | range { $$ = $1; } 240 | 241 | port_declaration: list_of_attribute_instance.opt port_type_io range.opt identifier { 242 | $$ = Port($4, $2, $3); 243 | } 244 | 245 | internal_ports_declaration: list_of_attribute_instance.opt port_type_io range.opt list_of_identifiers { 246 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 247 | for (auto portIdentifier: $4) { 248 | constructor->internalModuleImplementationPort(Port(portIdentifier, $2, $3)); 249 | } 250 | } 251 | 252 | port_type_io 253 | : INOUT_KW { $$ = naja::verilog::Port::Direction::InOut; } 254 | | INPUT_KW { $$ = naja::verilog::Port::Direction::Input; } 255 | | OUTPUT_KW { $$ = naja::verilog::Port::Direction::Output; } 256 | ; 257 | 258 | non_port_module_item: module_or_generate_item; 259 | 260 | hierarchical_parameter_identifier: hierarchical_identifier; 261 | 262 | constant_mintypmax_expression: constant_expression; 263 | 264 | defparam_assignment: hierarchical_parameter_identifier '=' constant_mintypmax_expression { 265 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 266 | constructor->addDefParameterAssignment($1, $3); 267 | } 268 | 269 | list_of_defparam_assignments: defparam_assignment| list_of_defparam_assignments defparam_assignment; 270 | 271 | parameter_override: DEFPARAM_KW list_of_defparam_assignments ';' 272 | 273 | hierarchical_net_identifier: identifier; 274 | 275 | net_lvalue: hierarchical_net_identifier constant_range_expression.opt { 276 | $$ = { naja::verilog::RangeIdentifier($1, $2) }; 277 | } 278 | | '{' list_of_net_lvalues '}' { 279 | $$ = $2; 280 | } 281 | 282 | //Only one level of list is supported 283 | list_of_net_lvalues: hierarchical_net_identifier constant_range_expression.opt { 284 | $$ = { naja::verilog::RangeIdentifier($1, $2) }; 285 | } 286 | | list_of_net_lvalues ',' hierarchical_net_identifier constant_range_expression.opt { 287 | $1.push_back(naja::verilog::RangeIdentifier($3, $4)); 288 | $$ = $1; 289 | } 290 | 291 | net_assignment: net_lvalue '=' expression { 292 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 293 | constructor->addAssign($1, $3); 294 | } 295 | 296 | list_of_net_assignments: net_assignment | list_of_net_assignments ',' net_assignment; 297 | 298 | continuous_assign: ASSIGN_KW list_of_net_assignments ';' 299 | 300 | module_or_generate_item: 301 | list_of_attribute_instance.opt module_or_generate_item_declaration 302 | | list_of_attribute_instance.opt module_instantiation 303 | | list_of_attribute_instance.opt parameter_override 304 | | list_of_attribute_instance.opt continuous_assign 305 | ; 306 | 307 | module_or_generate_item_declaration: net_declaration; 308 | 309 | net_declaration: net_type range.opt list_of_identifiers ';' { 310 | for (auto netIdentifier: $3) { 311 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 312 | constructor->addNet(Net(netIdentifier, $2, $1)); 313 | } 314 | } 315 | 316 | list_of_identifiers 317 | : net_identifier { 318 | $$ = { $1 }; 319 | } 320 | | list_of_identifiers ',' net_identifier { 321 | $1.push_back($3); 322 | $$ = $1; 323 | } 324 | 325 | net_identifier: identifier { $$ = naja::verilog::Identifier($1); } 326 | 327 | net_type 328 | : SUPPLY0_KW { $$ = naja::verilog::Net::Type::Supply0; } 329 | | SUPPLY1_KW { $$ = naja::verilog::Net::Type::Supply1; } 330 | | WIRE_KW { $$ = naja::verilog::Net::Type::Wire; } 331 | ; 332 | 333 | list_of_module_instances 334 | : module_instance 335 | | list_of_module_instances ',' module_instance 336 | ; 337 | 338 | number 339 | : BASE_TK BASED_CONSTVAL_TK { 340 | $$ = generateNumber(false, "", $1, $2, @$.begin.line, @$.end.line, @$.begin.column, @$.end.column); 341 | } 342 | | CONSTVAL_TK BASE_TK BASED_CONSTVAL_TK { 343 | $$ = generateNumber(true, $1, $2, $3, @$.begin.line, @$.end.line, @$.begin.column, @$.end.column); 344 | } 345 | | CONSTVAL_TK { 346 | $$ = Number($1); 347 | } 348 | 349 | //hierarchical_identifier ::= 350 | //{ identifier [ [ constant_expression ] ] . } identifier 351 | hierarchical_identifier 352 | : identifier { 353 | $$ = { $1 }; 354 | } 355 | | hierarchical_identifier '.' identifier { 356 | $1.push_back($3); 357 | $$ = $1; 358 | } 359 | 360 | //only numeric values (one bit) [4] or [4:5] are supported 361 | constant_range_expression.opt: %empty { $$.valid_ = false; } 362 | | '[' constant_expression ']' { 363 | if ($2.value_.index() == naja::verilog::ConstantExpression::NUMBER) { 364 | auto number = std::get($2.value_); 365 | $$ = Range(number.getInt()); 366 | } else { 367 | throw VerilogException("Only constant number expression are supported"); //LCOV_EXCL_LINE 368 | } 369 | } 370 | | range { 371 | $$ = $1; 372 | } 373 | 374 | list_of_expressions: 375 | expression { 376 | $$ = { $1 }; 377 | } 378 | | list_of_expressions ',' expression { 379 | $1.push_back($3); 380 | $$ = $1; 381 | } 382 | 383 | concatenation: '{' list_of_expressions '}' { $$ = $2; } 384 | 385 | expression: primary { $$ = $1; } 386 | 387 | expression.opt: %empty { $$.valid_ = false; } | expression { $$ = $1; } 388 | 389 | ordered_port_connection: expression { 390 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 391 | constructor->addOrderedInstanceConnection(portIndex++, $1); 392 | } 393 | 394 | list_of_ordered_port_connections 395 | : ordered_port_connection 396 | | list_of_ordered_port_connections ',' ordered_port_connection 397 | ; 398 | 399 | port_identifier: identifier; 400 | 401 | named_port_connection: '.' port_identifier '(' expression.opt ')' { 402 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 403 | constructor->addInstanceConnection($2, $4); 404 | } 405 | 406 | list_of_named_port_connections: named_port_connection | list_of_named_port_connections ',' named_port_connection; 407 | 408 | list_of_port_connections 409 | : { portIndex = 0; } list_of_ordered_port_connections 410 | | list_of_named_port_connections 411 | ; 412 | 413 | list_of_port_connections.opt: %empty | list_of_port_connections; 414 | 415 | name_of_module_instance: identifier 416 | 417 | module_instance: name_of_module_instance { 418 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 419 | constructor->addInstance(std::move($1)); 420 | } '(' list_of_port_connections.opt ')' 421 | 422 | parameter_identifier: identifier; 423 | 424 | mintypmax_expression: expression; 425 | 426 | mintypmax_expression.opt: %empty { $$.valid_ = false; } | mintypmax_expression { $$ = $1; } 427 | 428 | named_parameter_assignment: '.' parameter_identifier '(' mintypmax_expression.opt ')' { 429 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 430 | constructor->addParameterAssignment($2, $4); 431 | } 432 | 433 | list_of_named_parameter_assignments 434 | : named_parameter_assignment 435 | | list_of_named_parameter_assignments ',' named_parameter_assignment 436 | ; 437 | 438 | list_of_parameter_assignments: /* list_of_ordered_parameter_assignment | */ list_of_named_parameter_assignments; 439 | 440 | parameter_value_assignment: %empty | '#' '(' list_of_parameter_assignments ')' 441 | 442 | //(From A.4.1) 443 | module_instantiation: module_identifier { 444 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 445 | constructor->startInstantiation(std::move($1)); 446 | } parameter_value_assignment list_of_module_instances ';' { 447 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 448 | constructor->endInstantiation(); 449 | } 450 | 451 | module_identifier: identifier 452 | 453 | port: identifier { 454 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 455 | constructor->internalModuleInterfaceSimplePort($1); 456 | } 457 | 458 | module_item: internal_ports_declaration ';' | non_port_module_item; 459 | 460 | list_of_module_items: module_item | list_of_module_items module_item; 461 | 462 | list_of_module_items.opt: %empty | list_of_module_items; 463 | 464 | /* A.1.2 */ 465 | module_arg 466 | : port_declaration { 467 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 468 | constructor->internalModuleInterfaceCompletePort($1); 469 | } 470 | | port; 471 | 472 | list_of_module_args: module_arg | list_of_module_args ',' module_arg; 473 | 474 | list_of_module_args.opt: %empty | '(' ')' | '(' list_of_module_args ')'; 475 | 476 | module_declaration: list_of_attribute_instance.opt { 477 | } MODULE_KW module_identifier { 478 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 479 | constructor->internalStartModule(std::move($4)); 480 | } list_of_module_args.opt ';' list_of_module_items.opt ENDMODULE_KW { 481 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 482 | constructor->internalEndModule(); 483 | } 484 | 485 | /* 3.8 */ 486 | attr_spec_value: %empty { 487 | $$.valid_ = false; 488 | } 489 | | '=' constant_expression { 490 | $$ = $2; 491 | } 492 | 493 | attr_spec: identifier attr_spec_value { 494 | constructor->setCurrentLocation(@$.begin.line, @$.begin.column); 495 | constructor->addAttribute($1, $2); 496 | } 497 | 498 | list_of_attr_spec: attr_spec | list_of_attr_spec ',' attr_spec; 499 | 500 | //A.9.1 501 | attribute_instance: '(' '*' list_of_attr_spec '*' ')'; 502 | 503 | list_of_attribute_instance: attribute_instance | list_of_attribute_instance attribute_instance; 504 | 505 | list_of_attribute_instance.opt: %empty | list_of_attribute_instance; 506 | 507 | %% 508 | 509 | void naja::verilog::VerilogParser::error( 510 | const location_type& l, 511 | const std::string& err_message ) { 512 | std::ostringstream reason; 513 | reason << "Parser error: " << err_message << '\n' 514 | << " begin at line " << l.begin.line << " col " << l.begin.column << '\n' 515 | << " end at line " << l.end.line << " col " << l.end.column << "\n"; 516 | throw VerilogException(reason.str()); 517 | } -------------------------------------------------------------------------------- /src/VerilogScanner.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #ifndef __VERILOG_SCANNER_H_ 6 | #define __VERILOG_SCANNER_H_ 7 | 8 | #if ! defined(yyFlexLexerOnce) 9 | #include 10 | #endif 11 | 12 | #include "VerilogParser.hpp" 13 | #include "location.hh" 14 | 15 | namespace naja { namespace verilog { 16 | 17 | class VerilogScanner: public yyFlexLexer { 18 | public: 19 | VerilogScanner(std::istream *in): yyFlexLexer(in) {}; 20 | virtual ~VerilogScanner() {}; 21 | 22 | //get rid of override virtual function warning 23 | using FlexLexer::yylex; 24 | 25 | int yylex( 26 | naja::verilog::VerilogParser::semantic_type* const lval, 27 | naja::verilog::VerilogParser::location_type* location); 28 | // YY_DECL defined in VerilogScanner.ll 29 | // Method body created by flex in mc_lexer.yy.cc 30 | 31 | private: 32 | /* yyval ptr */ 33 | naja::verilog::VerilogParser::semantic_type* yylval = nullptr; 34 | }; 35 | 36 | }} // namespace verilog //namespace naja 37 | 38 | #endif /* __VERILOG_SCANNER_H_ */ -------------------------------------------------------------------------------- /src/VerilogScanner.ll: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2023 The Naja verilog authors 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | %{ 8 | /* C++ string header, for string ops below */ 9 | #include 10 | #include 11 | 12 | #include "VerilogException.h" 13 | 14 | /* Implementation of yyFlexScanner */ 15 | #include "VerilogScanner.h" 16 | #undef YY_DECL 17 | #define YY_DECL \ 18 | int naja::verilog::VerilogScanner::yylex( \ 19 | naja::verilog::VerilogParser::semantic_type* const lval, \ 20 | naja::verilog::VerilogParser::location_type*loc) 21 | 22 | /* typedef to make the returns for the tokens shorter */ 23 | using token = naja::verilog::VerilogParser::token; 24 | 25 | /* define yyterminate as this instead of NULL */ 26 | #define yyterminate() return( token::END ) 27 | 28 | /* msvc2010 requires that we exclude this header file. */ 29 | #define YY_NO_UNISTD_H 30 | 31 | /* update location on matching */ 32 | #define YY_USER_ACTION loc->step(); loc->columns(yyleng); 33 | 34 | %} 35 | 36 | %option debug 37 | /* %option nodefault */ 38 | %option yyclass="naja::verilog::VerilogScanner" 39 | %option noyywrap 40 | %option nounput 41 | %option never-interactive 42 | %option c++ 43 | 44 | %x in_comment 45 | %x based_const 46 | 47 | /* Predefined rules */ 48 | NEWLINE "\n"|"\r\n" 49 | SPACE " "|"\t"|"\f" 50 | COMMENT_BEGIN "/*" 51 | COMMENT_END "*/" 52 | COMMENT_LINE "//".*\n 53 | 54 | IDENTIFIER [_a-zA-Z][$_a-zA-Z0-9]* 55 | UNSIGNED_NUMBER [0-9][0-9_]* 56 | STRING \"[^\"]*\" 57 | 58 | 59 | /* 60 | Check the escape rule inside character class 61 | https://www.regular-expressions.info/charclass.html 62 | */ 63 | ESCAPED_IDENTIFIER \\[\\^!"#$%&',()*+\-.a-zA-Z0-9/{|}~[\]_:;<=>?@]+[\n\t\f ] 64 | 65 | %% 66 | %{ /** Code executed at the beginning of yylex **/ 67 | yylval = lval; 68 | %} 69 | 70 | <*>{SPACE} { /* ignore any space */ } 71 | {NEWLINE} { 72 | // Update line number 73 | loc->lines(); 74 | } 75 | 76 | {COMMENT_LINE} { loc->lines(); } 77 | 78 | {COMMENT_BEGIN} { BEGIN(in_comment); } 79 | <> { 80 | BEGIN(INITIAL); 81 | std::ostringstream reason; 82 | reason << "Unclosed comment at line " 83 | << loc->end.line << " col " << loc->end.column; 84 | throw VerilogException(reason.str()); 85 | } 86 | 87 | {NEWLINE} { loc->lines(); } 88 | . { /* ignore characters in comment */ } 89 | {COMMENT_END} { BEGIN(INITIAL); } 90 | 91 | "."|","|";"|"("|")"|"*"|"#"|"["|"]"|":"|"{"|"}"|"=" { 92 | return yytext[0]; 93 | } 94 | 95 | "+"|"-" { yylval->build( yytext ); return token::SIGN_TK; } 96 | 97 | module { return token::MODULE_KW; } 98 | endmodule { return token::ENDMODULE_KW; } 99 | input { return token::INPUT_KW; } 100 | output { return token::OUTPUT_KW; } 101 | inout { return token::INOUT_KW; } 102 | wire { return token::WIRE_KW; } 103 | supply0 { return token::SUPPLY0_KW; } 104 | supply1 { return token::SUPPLY1_KW; } 105 | assign { return token::ASSIGN_KW; } 106 | defparam { return token::DEFPARAM_KW; } 107 | 108 | {IDENTIFIER} { yylval->build( yytext ); return token::IDENTIFIER_TK; } 109 | {ESCAPED_IDENTIFIER} { 110 | //if the character ending the escape identifier is '\n' 111 | //we need to update the line number 112 | if (yytext[strlen(yytext)-1] == '\n') { 113 | loc->lines(); 114 | } 115 | yylval->build( yytext ); 116 | return token::ESCAPED_IDENTIFIER_TK; 117 | } 118 | {STRING} { yylval->build( yytext ); return token::STRING_TK; } 119 | 120 | {UNSIGNED_NUMBER} { 121 | yylval->build(yytext); 122 | return token::CONSTVAL_TK; 123 | } 124 | 125 | \'[sS]?[bodhBODH] { 126 | BEGIN(based_const); 127 | //we don't need the "'" first character and we are sure that yytext is 's?b|o|... 128 | yylval->build(yytext+1); 129 | return token::BASE_TK; 130 | } 131 | 132 | [0-9a-fA-FzxZX?][0-9a-fA-FzxZX?_]* { 133 | BEGIN(INITIAL); 134 | yylval->build(yytext); 135 | return token::BASED_CONSTVAL_TK; 136 | } 137 | 138 | /* Last rule catches everything */ 139 | /* LCOV_EXCL_START */ 140 | . { 141 | std::ostringstream reason; 142 | reason << "Failed to match: " << yytext << " at line " 143 | << loc->end.line << " col " << loc->end.column; 144 | throw VerilogException(reason.str()); 145 | } 146 | /* LCOV_EXCL_STOP */ 147 | 148 | %% -------------------------------------------------------------------------------- /src/VerilogTypes.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "VerilogTypes.h" 6 | #include "VerilogException.h" 7 | 8 | #include 9 | 10 | namespace naja { namespace verilog { 11 | 12 | std::string Identifier::getString() const { 13 | return name_; 14 | } 15 | 16 | //LCOV_EXCL_START 17 | std::string Identifier::getDescription() const { 18 | if (escaped_) { 19 | return "Identifier: [\\" + name_ + " ] (escaped)"; 20 | } else { 21 | return "Identifier: [" + name_ + "]"; 22 | } 23 | } 24 | //LCOV_EXCL_STOP 25 | 26 | //LCOV_EXCL_START 27 | std::string Range::getString() const { 28 | std::ostringstream stream; 29 | if (not valid_) { 30 | stream << "[not valid]"; 31 | return stream.str(); 32 | } 33 | if (singleValue_) { 34 | stream << "[" << msb_ << "]"; 35 | } else { 36 | stream << "[" << msb_ << ":" << lsb_ << "]"; 37 | } 38 | return stream.str(); 39 | } 40 | //LCOV_EXCL_STOP 41 | 42 | Port::Direction::Direction(const DirectionEnum& dirEnum): 43 | dirEnum_(dirEnum) 44 | {} 45 | 46 | //LCOV_EXCL_START 47 | std::string Port::Direction::getString() const { 48 | switch (dirEnum_) { 49 | case Direction::Input: return "Input"; 50 | case Direction::Output: return "Output"; 51 | case Direction::InOut: return "InOut"; 52 | case Direction::Unknown: return "Unknown"; 53 | } 54 | return "Error"; 55 | } 56 | //LCOV_EXCL_STOP 57 | 58 | //LCOV_EXCL_START 59 | std::string Port::getString() const { 60 | std::ostringstream stream; 61 | stream << "Port: " << identifier_.getString(); 62 | if (range_.valid_) { 63 | stream << range_.getString(); 64 | } 65 | stream << " " << direction_.getString(); 66 | return stream.str(); 67 | } 68 | //LCOV_EXCL_STOP 69 | 70 | Net::Type::Type(const TypeEnum& typeEnum): 71 | typeEnum_(typeEnum) 72 | {} 73 | 74 | //LCOV_EXCL_START 75 | std::string Net::Type::getString() const { 76 | switch (typeEnum_) { 77 | case Type::Supply0: return "Supply0"; 78 | case Type::Supply1: return "Supply1"; 79 | case Type::Wire: return "Wire"; 80 | case Type::Unknown: return "Unknown"; 81 | } 82 | return "Error"; 83 | } 84 | //LCOV_EXCL_STOP 85 | 86 | //LCOV_EXCL_START 87 | std::string Net::getString() const { 88 | std::ostringstream stream; 89 | stream << "Net: " << identifier_.getString(); 90 | if (range_.valid_) { 91 | stream << range_.getString(); 92 | } 93 | stream << " " << type_.getString(); 94 | return stream.str(); 95 | } 96 | //LCOV_EXCL_STOP 97 | 98 | //LCOV_EXCL_START 99 | std::string RangeIdentifier::getString() const { 100 | std::ostringstream stream; 101 | stream << identifier_.getString(); 102 | if (range_.valid_) { 103 | stream << range_.getString(); 104 | } 105 | return stream.str(); 106 | } 107 | //LCOV_EXCL_STOP 108 | 109 | //LCOV_EXCL_START 110 | std::string RangeIdentifier::getDescription() const { 111 | return "RangeIdentifier: " + getString(); 112 | } 113 | //LCOV_EXCL_STOP 114 | 115 | //LCOV_EXCL_START 116 | std::string BasedNumber::getBaseString(Base base) { 117 | switch (base) { 118 | case BINARY: 119 | return "BINARY"; 120 | case OCTAL: 121 | return "OCTAL"; 122 | case HEX: 123 | return "HEX"; 124 | case DECIMAL: 125 | return "DECIMAL"; 126 | } 127 | return "UNKNOWN"; 128 | } 129 | //LCOV_EXCL_STOP 130 | 131 | //LCOV_EXCL_START 132 | std::string BasedNumber::getString() const { 133 | std::ostringstream stream; 134 | if (hasSize_) { 135 | stream << size_; 136 | } 137 | stream << "'"; 138 | if (signed_) { 139 | stream << 's'; 140 | } 141 | switch (base_) { 142 | case BINARY: 143 | stream << "b"; 144 | break; 145 | case OCTAL: 146 | stream << "o"; 147 | break; 148 | case HEX: 149 | stream << "h"; 150 | break; 151 | case DECIMAL: 152 | stream << "d"; 153 | break; 154 | } 155 | stream << digits_; 156 | return stream.str(); 157 | } 158 | //LCOV_EXCL_STOP 159 | 160 | //LCOV_EXCL_START 161 | std::string BasedNumber::getDescription() const { 162 | return "BasedNumber: " + getString(); 163 | } 164 | //LCOV_EXCL_STOP 165 | 166 | int Number::getInt() const { 167 | switch (value_.index()) { 168 | case Type::UNSIGNED: { 169 | int value = std::get(value_); 170 | return sign_?value:-value; 171 | } 172 | default: { 173 | throw VerilogException("Unsupported number"); 174 | } 175 | } 176 | return 0; 177 | } 178 | 179 | //LCOV_EXCL_START 180 | std::string Number::getString() const { 181 | switch (value_.index()) { 182 | case Type::BASED: 183 | return std::get(value_).getString(); 184 | case Type::UNSIGNED: 185 | return std::to_string(std::get(value_)); 186 | } 187 | return std::string(); 188 | } 189 | //LCOV_EXCL_STOP 190 | 191 | //LCOV_EXCL_START 192 | std::string Number::getDescription() const { 193 | std::ostringstream stream; 194 | switch (value_.index()) { 195 | case Type::BASED: 196 | stream << std::get(value_).getDescription(); 197 | break; 198 | case Type::UNSIGNED: 199 | stream << "unsigned: " << std::get(value_); 200 | break; 201 | } 202 | return stream.str(); 203 | } 204 | //LCOV_EXCL_STOP 205 | 206 | Concatenation::Concatenation(const Expressions& expressions) 207 | :expressions_(expressions) 208 | {} 209 | 210 | //LCOV_EXCL_START 211 | std::string Concatenation::getString() const { 212 | std::ostringstream stream; 213 | stream << "{ "; 214 | bool first = true; 215 | for (auto expression: expressions_) { 216 | if (not first) { 217 | stream << ", "; 218 | } 219 | stream << expression.getString(); 220 | first = false; 221 | } 222 | stream << " }"; 223 | return stream.str(); 224 | } 225 | //LCOV_EXCL_STOP 226 | 227 | //LCOV_EXCL_START 228 | std::string Concatenation::getDescription() const { 229 | return "Concatenation: " + getString(); 230 | } 231 | //LCOV_EXCL_STOP 232 | 233 | //LCOV_EXCL_START 234 | std::string Expression::getString() const { 235 | std::ostringstream stream; 236 | switch (value_.index()) { 237 | case Type::RANGEIDENTIFIER: 238 | return std::get(value_).getString(); 239 | case Type::NUMBER: 240 | return std::get(value_).getString(); 241 | case Type::STRING: 242 | return std::get(value_); 243 | case Type::CONCATENATION: 244 | return std::get(value_).getString(); 245 | } 246 | return std::string(); 247 | } 248 | //LCOV_EXCL_STOP 249 | 250 | //LCOV_EXCL_START 251 | std::string Expression::getDescription() const { 252 | std::ostringstream stream; 253 | stream << "Expression: (valid: " << valid_ << " supported: " << supported_ << ") "; 254 | switch (value_.index()) { 255 | case Type::RANGEIDENTIFIER: 256 | stream << std::get(value_).getDescription(); 257 | break; 258 | case Type::NUMBER: 259 | stream << std::get(value_).getDescription(); 260 | break; 261 | case Type::CONCATENATION: 262 | stream << std::get(value_).getDescription(); 263 | break; 264 | } 265 | return stream.str(); 266 | } 267 | //LCOV_EXCL_STOP 268 | 269 | //LCOV_EXCL_START 270 | std::string ConstantExpression::getString() const { 271 | std::ostringstream stream; 272 | switch (value_.index()) { 273 | case Type::NUMBER: 274 | return std::get(value_).getString(); 275 | case Type::STRING: 276 | return std::get(value_); 277 | } 278 | return std::string(); 279 | } 280 | //LCOV_EXCL_STOP 281 | 282 | //LCOV_EXCL_START 283 | std::string ConstantExpression::getDescription() const { 284 | std::ostringstream stream; 285 | stream << "Expression: (valid: " << valid_ << ") "; 286 | switch (value_.index()) { 287 | case Type::NUMBER: 288 | stream << std::get(value_).getDescription(); 289 | break; 290 | case Type::STRING: 291 | stream << std::get(value_); 292 | break; 293 | } 294 | return stream.str(); 295 | } 296 | //LCOV_EXCL_STOP 297 | 298 | }} // namespace verilog // namespace naja -------------------------------------------------------------------------------- /src/VerilogTypes.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #ifndef __VERILOG_TYPES_H_ 6 | #define __VERILOG_TYPES_H_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace naja { namespace verilog { 14 | 15 | struct Range { 16 | Range() = default; 17 | Range(const Range&) = default; 18 | Range(int msb, int lsb): 19 | valid_(true), singleValue_(false), msb_(msb), lsb_(lsb) {} 20 | Range(int value): 21 | valid_(true), singleValue_(true), msb_(value) {} 22 | bool operator==(const Range& other) const { 23 | return valid_ == other.valid_ 24 | && singleValue_ == other.singleValue_ 25 | && msb_ == other.msb_ 26 | && lsb_ == other.lsb_; 27 | } 28 | 29 | std::string getString() const; 30 | 31 | //Range has been parsed 32 | bool valid_ {false}; 33 | bool singleValue_ {false}; 34 | int msb_ {0}; 35 | int lsb_ {0}; 36 | }; 37 | 38 | struct Identifier { 39 | Identifier() = default; 40 | Identifier(const Identifier&) = default; 41 | Identifier(const std::string& name, bool escaped=false): name_(name), escaped_(escaped) {} 42 | bool operator==(const Identifier& other) const { 43 | return name_ == other.name_ && escaped_ == other.escaped_; 44 | } 45 | std::string getString() const; 46 | std::string getDescription() const; 47 | 48 | std::string name_; 49 | bool escaped_ {false}; 50 | }; 51 | 52 | using Identifiers = std::vector; 53 | 54 | struct Port { 55 | class Direction { 56 | public: 57 | enum DirectionEnum { 58 | Input, Output, InOut, Unknown 59 | }; 60 | Direction() = default; 61 | Direction(const DirectionEnum& dirEnum); 62 | Direction(const Direction&) = default; 63 | Direction(Direction&&) = default; 64 | Direction& operator=(const Direction&) = default; 65 | 66 | operator const DirectionEnum&() const {return dirEnum_;} 67 | std::string getString() const; 68 | private: 69 | DirectionEnum dirEnum_ { Unknown }; 70 | }; 71 | 72 | Port() = default; 73 | Port(const Port&) = default; 74 | Port(const Identifier& identifier, Direction direction): 75 | identifier_(identifier), 76 | direction_(direction) 77 | {} 78 | 79 | Port(const Identifier& identifier, Direction direction, const Range& range): 80 | identifier_(identifier), 81 | range_(range), 82 | direction_(direction) 83 | {} 84 | 85 | bool isBus() const { return range_.valid_; } 86 | 87 | Identifier identifier_ {}; 88 | Range range_ {}; 89 | Direction direction_ {}; 90 | 91 | std::string getString() const; 92 | }; 93 | 94 | using Ports = std::vector; 95 | 96 | struct Net { 97 | class Type { 98 | public: 99 | enum TypeEnum { 100 | Wire, Supply0, Supply1, Unknown 101 | }; 102 | Type() = default; 103 | Type(const TypeEnum& dirEnum); 104 | Type(const Type&) = default; 105 | Type(Type&&) = default; 106 | Type& operator=(const Type&) = default; 107 | 108 | operator const TypeEnum&() const {return typeEnum_;} 109 | std::string getString() const; 110 | private: 111 | TypeEnum typeEnum_ { Unknown }; 112 | }; 113 | 114 | Net() = default; 115 | Net(const Net&) = default; 116 | 117 | Net(const Identifier& identifier, const Range& range, Type type): 118 | identifier_(identifier), 119 | range_(range), 120 | type_(type) 121 | {} 122 | 123 | bool isBus() const { return range_.valid_; } 124 | 125 | Identifier identifier_ {}; 126 | Range range_ {}; 127 | Type type_ {}; 128 | 129 | std::string getString() const; 130 | }; 131 | 132 | struct RangeIdentifier { 133 | RangeIdentifier() = default; 134 | RangeIdentifier(const RangeIdentifier&) = default; 135 | RangeIdentifier(const Identifier& identifier): identifier_(identifier) {} 136 | RangeIdentifier(const Identifier& identifier, const Range& range): identifier_(identifier), range_(range) {} 137 | std::string getString() const; 138 | std::string getDescription() const; 139 | 140 | Identifier identifier_; 141 | Range range_; 142 | }; 143 | 144 | using RangeIdentifiers = std::vector; 145 | 146 | struct BasedNumber { 147 | BasedNumber() = default; 148 | BasedNumber(bool isSigned, char base, const std::string& digits) { 149 | hasSize_ = false; 150 | signed_ = isSigned; 151 | switch (base) { 152 | case 'b': case 'B': 153 | base_ = BINARY; 154 | break; 155 | case 'o': case 'O': 156 | base_ = OCTAL; 157 | break; 158 | case 'h': case 'H': 159 | base_ = HEX; 160 | break; 161 | case 'd': case 'D': 162 | base_ = DECIMAL; 163 | break; 164 | } 165 | digits_ = digits; 166 | } 167 | BasedNumber(const std::string& size, bool isSigned, char base, const std::string& digits): 168 | BasedNumber(isSigned, base, digits) { 169 | hasSize_ = true; 170 | size_ = static_cast(std::stoul(size)); 171 | } 172 | enum Base { BINARY, OCTAL, HEX, DECIMAL }; 173 | 174 | static std::string getBaseString(Base base); 175 | std::string getString() const; 176 | std::string getDescription() const; 177 | 178 | bool hasSize_ {false}; 179 | size_t size_ {0}; 180 | bool signed_ {false}; 181 | Base base_ {}; 182 | std::string digits_ {}; 183 | }; 184 | 185 | struct Number { 186 | Number() = default; 187 | Number(const Number&) = default; 188 | Number(const std::string& value) { 189 | value_ = static_cast(std::stoul(value)); 190 | } 191 | Number(const std::string& size, bool isSigned, char base, const std::string& value) { 192 | value_ = BasedNumber(size, isSigned, base, value); 193 | } 194 | Number(bool isSigned, char base, const std::string& value) { 195 | value_ = BasedNumber(isSigned, base, value); 196 | } 197 | std::string getString() const; 198 | std::string getDescription() const; 199 | 200 | int getInt() const; 201 | enum Type { BASED, UNSIGNED }; 202 | using Value = std::variant; 203 | 204 | bool sign_ {true}; //true positive, false negative 205 | Value value_ {}; 206 | }; 207 | 208 | struct Expression; 209 | 210 | struct Concatenation { 211 | using Expressions = std::vector; 212 | Concatenation() = default; 213 | Concatenation(const Concatenation&) = default; 214 | Concatenation(const Expressions& expressions); 215 | std::string getString() const; 216 | std::string getDescription() const; 217 | 218 | Expressions expressions_ {}; 219 | }; 220 | 221 | struct Expression { 222 | using Expressions = std::vector; 223 | Expression() = default; 224 | Expression(const Expression&) = default; 225 | std::string getString() const; 226 | std::string getDescription() const; 227 | 228 | enum Type { RANGEIDENTIFIER=0, NUMBER=1, STRING=2, CONCATENATION=3 }; 229 | using Value = std::variant; 230 | 231 | bool valid_ { false }; 232 | //If valid_ is true and supported_ is false, then this expression construction 233 | //is not currently supported. 234 | bool supported_ { true }; 235 | Value value_ {}; 236 | }; 237 | 238 | struct ConstantExpression { 239 | ConstantExpression() = default; 240 | ConstantExpression(const ConstantExpression&) = default; 241 | 242 | enum Type { NUMBER=0, STRING=1 }; 243 | using Value = std::variant; 244 | 245 | Type getType() const { return Type(value_.index()); } 246 | std::string getString() const; 247 | std::string getDescription() const; 248 | 249 | bool valid_ { false }; 250 | Value value_ {}; 251 | }; 252 | 253 | struct Attribute { 254 | Attribute() = default; 255 | Attribute(const Attribute&) = default; 256 | Attribute(const naja::verilog::Identifier& name, const ConstantExpression& expression): 257 | name_(name), 258 | expression_(expression) 259 | {} 260 | std::string getString() const; 261 | std::string getDescription() const; 262 | 263 | naja::verilog::Identifier name_ {}; 264 | ConstantExpression expression_ {}; 265 | }; 266 | 267 | }} // namespace verilog // namespace naja 268 | 269 | #endif /* __VERILOG_TYPES_H_ */ -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | include(GoogleTest) 6 | 7 | set(tests 8 | VerilogConstructorTest.cpp 9 | NajaVerilogTest012.cpp 10 | NajaVerilogTest3.cpp 11 | NajaVerilogTest4.cpp 12 | NajaVerilogTest5.cpp 13 | NajaVerilogTest6.cpp 14 | NajaVerilogTest7.cpp 15 | NajaVerilogTest8.cpp 16 | NajaVerilogTest9.cpp 17 | NajaVerilogTest10.cpp 18 | NajaVerilogTest11.cpp 19 | NajaVerilogTest12.cpp 20 | NajaVerilogTest13.cpp 21 | NajaVerilogTest14.cpp 22 | NajaVerilogTest15.cpp 23 | NajaVerilogTestMultipleFiles.cpp 24 | NajaVerilogTestErrors.cpp 25 | ) 26 | 27 | add_executable(naja_verilog_tests ${tests}) 28 | target_compile_definitions(naja_verilog_tests PRIVATE 29 | NAJA_VERILOG_BENCHMARKS="${CMAKE_CURRENT_SOURCE_DIR}") 30 | 31 | target_link_libraries(naja_verilog_tests naja_verilog gmock gtest_main) 32 | 33 | GTEST_DISCOVER_TESTS(naja_verilog_tests) -------------------------------------------------------------------------------- /test/NajaVerilogTest012.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest012, test0) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test0Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test0.v")); 26 | constructor.parse(test0Path); 27 | ASSERT_EQ(6, constructor.modules_.size()); 28 | auto test0 = constructor.modules_[0]; 29 | EXPECT_EQ("test0", test0->identifier_.name_); 30 | EXPECT_FALSE(test0->identifier_.escaped_); 31 | EXPECT_TRUE(test0->ports_.empty()); 32 | auto test1 = constructor.modules_[1]; 33 | EXPECT_EQ("test1", test1->identifier_.name_); 34 | EXPECT_FALSE(test1->identifier_.escaped_); 35 | EXPECT_TRUE(test1->ports_.empty()); 36 | auto test2 = constructor.modules_[2]; 37 | EXPECT_EQ("test2", test2->identifier_.name_); 38 | EXPECT_FALSE(test2->identifier_.escaped_); 39 | EXPECT_EQ(5, test2->ports_.size()); 40 | EXPECT_EQ("i0", test2->ports_[0].identifier_.name_); 41 | EXPECT_EQ(Port::Direction::Input, test2->ports_[0].direction_); 42 | EXPECT_EQ("i1", test2->ports_[1].identifier_.name_); 43 | EXPECT_EQ(Port::Direction::Input, test2->ports_[1].direction_); 44 | EXPECT_EQ("o0", test2->ports_[2].identifier_.name_); 45 | EXPECT_EQ(Port::Direction::Output, test2->ports_[2].direction_); 46 | EXPECT_EQ("o1", test2->ports_[3].identifier_.name_); 47 | EXPECT_EQ(Port::Direction::Output, test2->ports_[3].direction_); 48 | EXPECT_EQ("io", test2->ports_[4].identifier_.name_); 49 | EXPECT_EQ(Port::Direction::InOut, test2->ports_[4].direction_); 50 | for (auto port: test2->ports_) { 51 | EXPECT_FALSE(port.range_.valid_); 52 | } 53 | 54 | auto test3 = constructor.modules_[3]; 55 | EXPECT_EQ("test3", test3->identifier_.name_); 56 | EXPECT_FALSE(test3->identifier_.escaped_); 57 | EXPECT_EQ(5, test3->ports_.size()); 58 | EXPECT_EQ("i0", test3->ports_[0].identifier_.name_); 59 | EXPECT_EQ(Port::Direction::Input, test3->ports_[0].direction_); 60 | EXPECT_EQ("i1", test3->ports_[1].identifier_.name_); 61 | EXPECT_EQ(Port::Direction::Input, test3->ports_[1].direction_); 62 | EXPECT_EQ("o0", test3->ports_[2].identifier_.name_); 63 | EXPECT_EQ(Port::Direction::Output, test3->ports_[2].direction_); 64 | EXPECT_EQ("o1", test3->ports_[3].identifier_.name_); 65 | EXPECT_EQ(Port::Direction::Output, test3->ports_[3].direction_); 66 | EXPECT_EQ("io", test3->ports_[4].identifier_.name_); 67 | EXPECT_EQ(Port::Direction::InOut, test3->ports_[4].direction_); 68 | for (auto port: test3->ports_) { 69 | EXPECT_FALSE(port.range_.valid_); 70 | } 71 | 72 | auto test4 = constructor.modules_[4]; 73 | EXPECT_EQ("test4", test4->identifier_.name_); 74 | EXPECT_EQ(5, test4->ports_.size()); 75 | EXPECT_EQ("i0", test4->ports_[0].identifier_.name_); 76 | EXPECT_EQ(Port::Direction::Input, test4->ports_[0].direction_); 77 | EXPECT_EQ("i1", test4->ports_[1].identifier_.name_); 78 | EXPECT_EQ(Port::Direction::Input, test4->ports_[1].direction_); 79 | EXPECT_EQ("o0", test4->ports_[2].identifier_.name_); 80 | EXPECT_EQ(Port::Direction::Output, test4->ports_[2].direction_); 81 | EXPECT_EQ("o1", test4->ports_[3].identifier_.name_); 82 | EXPECT_EQ(Port::Direction::Output, test4->ports_[3].direction_); 83 | EXPECT_EQ("io", test4->ports_[4].identifier_.name_); 84 | EXPECT_EQ(Port::Direction::InOut, test4->ports_[4].direction_); 85 | for (auto port: test4->ports_) { 86 | EXPECT_FALSE(port.range_.valid_); 87 | } 88 | 89 | auto test5 = constructor.modules_[5]; 90 | EXPECT_EQ("test5", test5->identifier_.name_); 91 | EXPECT_FALSE(test5->identifier_.escaped_); 92 | EXPECT_EQ("i0", test5->ports_[0].identifier_.name_); 93 | EXPECT_EQ(Port::Direction::Input, test5->ports_[0].direction_); 94 | EXPECT_TRUE(test5->ports_[0].range_.valid_); 95 | EXPECT_EQ(test5->ports_[0].range_.msb_, 3); 96 | EXPECT_EQ(test5->ports_[0].range_.lsb_, 0); 97 | EXPECT_EQ("i1", test5->ports_[1].identifier_.name_); 98 | EXPECT_TRUE(test5->ports_[1].range_.valid_); 99 | EXPECT_EQ(test5->ports_[1].range_.msb_, 3); 100 | EXPECT_EQ(test5->ports_[1].range_.lsb_, 0); 101 | EXPECT_EQ(Port::Direction::Input, test5->ports_[1].direction_); 102 | EXPECT_EQ("o0", test5->ports_[2].identifier_.name_); 103 | EXPECT_TRUE(test5->ports_[2].range_.valid_); 104 | EXPECT_EQ(test5->ports_[2].range_.msb_, 0); 105 | EXPECT_EQ(test5->ports_[2].range_.lsb_, 3); 106 | EXPECT_EQ(Port::Direction::Output, test5->ports_[2].direction_); 107 | EXPECT_EQ("o1", test5->ports_[3].identifier_.name_); 108 | EXPECT_TRUE(test5->ports_[3].range_.valid_); 109 | EXPECT_EQ(test5->ports_[3].range_.msb_, 0); 110 | EXPECT_EQ(test5->ports_[3].range_.lsb_, 3); 111 | EXPECT_EQ(Port::Direction::Output, test5->ports_[3].direction_); 112 | EXPECT_EQ("io", test5->ports_[4].identifier_.name_); 113 | EXPECT_FALSE(test5->ports_[4].identifier_.escaped_); 114 | EXPECT_FALSE(test5->ports_[4].range_.valid_); 115 | EXPECT_EQ(Port::Direction::InOut, test5->ports_[4].direction_); 116 | } 117 | 118 | TEST(NajaVerilogTest012, test1) { 119 | VerilogConstructorTest constructor; 120 | std::filesystem::path test1Path( 121 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 122 | / std::filesystem::path("benchmarks") 123 | / std::filesystem::path("test1.v")); 124 | constructor.parse(test1Path); 125 | ASSERT_EQ(1, constructor.modules_.size()); 126 | auto module = constructor.modules_[0]; 127 | EXPECT_EQ("test", module->identifier_.name_); 128 | } 129 | 130 | TEST(NajaVerilogTest012, test2) { 131 | VerilogConstructorTest constructor; 132 | std::filesystem::path test1Path( 133 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 134 | / std::filesystem::path("benchmarks") 135 | / std::filesystem::path("test2.v")); 136 | constructor.parse(test1Path); 137 | ASSERT_EQ(1, constructor.modules_.size()); 138 | auto module = constructor.modules_[0]; 139 | EXPECT_EQ("test", module->identifier_.name_); 140 | } 141 | -------------------------------------------------------------------------------- /test/NajaVerilogTest10.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2024 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest10, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test10Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test10.v")); 26 | 27 | constructor.setFirstPass(true); 28 | constructor.parse(test10Path); 29 | ASSERT_EQ(1, constructor.modules_.size()); 30 | auto test = constructor.modules_[0]; 31 | EXPECT_TRUE(test->ports_.empty()); 32 | EXPECT_TRUE(test->nets_.empty()); 33 | EXPECT_TRUE(test->assigns_.empty()); 34 | EXPECT_TRUE(test->instances_.empty()); 35 | constructor.setFirstPass(false); 36 | constructor.parse(test10Path); 37 | 38 | ASSERT_EQ(1, constructor.modules_.size()); 39 | EXPECT_TRUE(test->ports_.empty()); 40 | EXPECT_TRUE(test->nets_.empty()); 41 | EXPECT_TRUE(test->assigns_.empty()); 42 | EXPECT_EQ(1, test->instances_.size()); 43 | auto instance = test->instances_[0]; 44 | EXPECT_EQ("ins", instance.identifier_.name_); 45 | EXPECT_EQ("MOD", instance.model_.name_); 46 | EXPECT_EQ(3, instance.parameterAssignments_.size()); 47 | using Parameters = std::vector>; 48 | Parameters parameters; 49 | for (const auto& [parameter, value]: instance.parameterAssignments_) { 50 | parameters.push_back({parameter, value}); 51 | } 52 | EXPECT_EQ("elem10", parameters[0].first); 53 | EXPECT_EQ("'d0", parameters[0].second); 54 | EXPECT_EQ("elem11", parameters[1].first); 55 | EXPECT_EQ("10'sd0", parameters[1].second); 56 | EXPECT_EQ("elem12", parameters[2].first); 57 | EXPECT_EQ("'sd0", parameters[2].second); 58 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest11.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2024 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest11, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test11Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test11.v")); 26 | 27 | constructor.setFirstPass(true); 28 | constructor.parse(test11Path); 29 | ASSERT_EQ(1, constructor.modules_.size()); 30 | auto test = constructor.modules_[0]; 31 | EXPECT_TRUE(test->ports_.empty()); 32 | EXPECT_TRUE(test->nets_.empty()); 33 | EXPECT_TRUE(test->assigns_.empty()); 34 | EXPECT_TRUE(test->instances_.empty()); 35 | constructor.setFirstPass(false); 36 | constructor.parse(test11Path); 37 | 38 | ASSERT_EQ(1, constructor.modules_.size()); 39 | EXPECT_TRUE(test->ports_.empty()); 40 | EXPECT_TRUE(test->nets_.empty()); 41 | EXPECT_TRUE(test->assigns_.empty()); 42 | EXPECT_EQ(1, test->instances_.size()); 43 | auto instance = test->instances_[0]; 44 | EXPECT_EQ("ins", instance.identifier_.name_); 45 | EXPECT_EQ("MOD", instance.model_.name_); 46 | EXPECT_EQ(2, instance.parameterAssignments_.size()); 47 | using Parameters = std::vector>; 48 | Parameters parameters; 49 | for (const auto& [parameter, value]: instance.parameterAssignments_) { 50 | parameters.push_back({parameter, value}); 51 | } 52 | EXPECT_EQ("elem10", parameters[0].first); 53 | EXPECT_EQ("'o0", parameters[0].second); 54 | EXPECT_EQ("elem11", parameters[1].first); 55 | EXPECT_EQ("8'o84", parameters[1].second); 56 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest12.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2024 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest12, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test12Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test12.v")); 26 | 27 | constructor.setFirstPass(true); 28 | constructor.parse(test12Path); 29 | ASSERT_EQ(1, constructor.modules_.size()); 30 | auto test = constructor.modules_[0]; 31 | EXPECT_TRUE(test->ports_.empty()); 32 | EXPECT_TRUE(test->nets_.empty()); 33 | EXPECT_TRUE(test->assigns_.empty()); 34 | EXPECT_TRUE(test->instances_.empty()); 35 | 36 | constructor.setFirstPass(false); 37 | constructor.parse(test12Path); 38 | ASSERT_EQ(1, constructor.modules_.size()); 39 | EXPECT_TRUE(test->ports_.empty()); 40 | EXPECT_TRUE(test->assigns_.empty()); 41 | ASSERT_EQ(2, test->nets_.size()); 42 | ASSERT_EQ(3, test->instances_.size()); 43 | 44 | auto ins1 = test->instances_[0]; 45 | EXPECT_EQ("ins1", ins1.identifier_.name_); 46 | EXPECT_FALSE(ins1.identifier_.escaped_); 47 | EXPECT_EQ("CFG1", ins1.model_.name_); 48 | EXPECT_TRUE(ins1.parameterAssignments_.empty()); 49 | 50 | auto mem = test->instances_[1]; 51 | EXPECT_EQ("mem_regfile_mem_regfile_0_0", mem.identifier_.name_); 52 | EXPECT_FALSE(mem.identifier_.escaped_); 53 | EXPECT_EQ("RAM64x18", mem.model_.name_); 54 | EXPECT_TRUE(mem.parameterAssignments_.empty()); 55 | 56 | auto ins2 = test->instances_[2]; 57 | EXPECT_EQ("$$ins2@@", ins2.identifier_.name_); 58 | EXPECT_FALSE(ins2.identifier_.escaped_); 59 | EXPECT_EQ("CFG1", ins2.model_.name_); 60 | EXPECT_TRUE(ins2.parameterAssignments_.empty()); 61 | 62 | EXPECT_EQ(3, test->defParameterAssignments_.size()); 63 | auto def0Path = test->defParameterAssignments_[0].first; 64 | auto def0Value = test->defParameterAssignments_[0].second; 65 | EXPECT_EQ(2, def0Path.size()); 66 | EXPECT_EQ("ins1", def0Path[0].name_); 67 | EXPECT_FALSE(def0Path[0].escaped_); 68 | EXPECT_EQ("INIT", def0Path[1].name_); 69 | EXPECT_FALSE(def0Path[1].escaped_); 70 | EXPECT_EQ("2'h1", def0Value.getString()); 71 | EXPECT_EQ(ConstantExpression::Type::NUMBER ,def0Value.value_.index()); 72 | 73 | auto def1Path = test->defParameterAssignments_[1].first; 74 | auto def1Value = test->defParameterAssignments_[1].second; 75 | EXPECT_EQ(2, def1Path.size()); 76 | EXPECT_EQ("mem_regfile_mem_regfile_0_0", def1Path[0].name_); 77 | EXPECT_FALSE(def1Path[0].escaped_); 78 | EXPECT_EQ("RAMINDEX", def1Path[1].name_); 79 | EXPECT_FALSE(def1Path[1].escaped_); 80 | EXPECT_EQ(ConstantExpression::Type::STRING ,def1Value.value_.index()); 81 | EXPECT_EQ("mem_regfile[7:0]%32%8%SPEED%0%0%MICRO_RAM", def1Value.getString()); 82 | 83 | auto def2Path = test->defParameterAssignments_[2].first; 84 | auto def2Value = test->defParameterAssignments_[2].second; 85 | EXPECT_EQ(2, def2Path.size()); 86 | EXPECT_EQ("$$ins2@@", def2Path[0].name_); 87 | EXPECT_TRUE(def2Path[0].escaped_); 88 | EXPECT_EQ("INIT", def2Path[1].name_); 89 | EXPECT_FALSE(def2Path[1].escaped_); 90 | EXPECT_EQ(ConstantExpression::Type::NUMBER ,def2Value.value_.index()); 91 | EXPECT_EQ("2'h2", def2Value.getString()); 92 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest13.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2024 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest13, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test13Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test13.v")); 26 | 27 | constructor.setFirstPass(true); 28 | constructor.parse(test13Path); 29 | ASSERT_EQ(1, constructor.modules_.size()); 30 | auto test = constructor.modules_[0]; 31 | ASSERT_EQ(27, test->ports_.size()); 32 | EXPECT_TRUE(test->nets_.empty()); 33 | EXPECT_TRUE(test->assigns_.empty()); 34 | EXPECT_TRUE(test->instances_.empty()); 35 | 36 | constructor.setFirstPass(false); 37 | constructor.parse(test13Path); 38 | ASSERT_EQ(1, constructor.modules_.size()); 39 | ASSERT_EQ(27, test->ports_.size()); 40 | ASSERT_EQ(67, test->nets_.size()); 41 | EXPECT_TRUE(test->assigns_.empty()); 42 | EXPECT_EQ(69, test->instances_.size()); 43 | #if 0 44 | EXPECT_EQ("ins", instance.identifier_.name_); 45 | EXPECT_EQ("MOD", instance.model_.name_); 46 | EXPECT_EQ(2, instance.parameterAssignments_.size()); 47 | using Parameters = std::vector>; 48 | Parameters parameters; 49 | for (const auto& [parameter, value]: instance.parameterAssignments_) { 50 | parameters.push_back({parameter, value}); 51 | } 52 | EXPECT_EQ("elem10", parameters[0].first); 53 | EXPECT_EQ("'o0", parameters[0].second); 54 | EXPECT_EQ("elem11", parameters[1].first); 55 | EXPECT_EQ("8'o84", parameters[1].second); 56 | #endif 57 | } 58 | -------------------------------------------------------------------------------- /test/NajaVerilogTest14.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2024 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest14, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test14Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test14.v")); 26 | constructor.parse(test14Path); 27 | ASSERT_EQ(1, constructor.modules_.size()); 28 | auto adder = constructor.modules_[0]; 29 | EXPECT_EQ("adder", adder->identifier_.getString()); 30 | //EXPECT_EQ(2, adder->currentMo connections_.size()); 31 | 32 | constructor.setFirstPass(false); 33 | constructor.parse(test14Path); 34 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest15.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2024 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest15, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test15Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test15.v")); 26 | constructor.parse(test15Path); 27 | ASSERT_EQ(1, constructor.modules_.size()); 28 | auto test = constructor.modules_[0]; 29 | EXPECT_EQ("test", test->identifier_.getString()); 30 | 31 | constructor.setFirstPass(false); 32 | constructor.parse(test15Path); 33 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest3.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest3, test0) { 21 | std::filesystem::path test3Path( 22 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 23 | / std::filesystem::path("benchmarks") 24 | / std::filesystem::path("test3.v")); 25 | VerilogConstructorTest constructor; 26 | { 27 | constructor.parse(test3Path); 28 | 29 | ASSERT_EQ(3, constructor.modules_.size()); 30 | auto mod0 = constructor.modules_[0]; 31 | EXPECT_EQ("mod0", mod0->identifier_.name_); 32 | ASSERT_EQ(2, mod0->ports_.size()); 33 | EXPECT_EQ("i0", mod0->ports_[0].identifier_.name_); 34 | EXPECT_EQ("o0", mod0->ports_[1].identifier_.name_); 35 | EXPECT_EQ(naja::verilog::Port::Direction::Input, mod0->ports_[0].direction_); 36 | EXPECT_EQ(naja::verilog::Port::Direction::Output, mod0->ports_[1].direction_); 37 | EXPECT_TRUE(mod0->nets_.empty()); 38 | EXPECT_TRUE(mod0->instances_.empty()); 39 | 40 | auto mod1 = constructor.modules_[1]; 41 | EXPECT_EQ("mod1", mod1->identifier_.name_); 42 | ASSERT_EQ(2, mod1->ports_.size()); 43 | EXPECT_EQ("i0", mod1->ports_[0].identifier_.name_); 44 | EXPECT_EQ("o0", mod1->ports_[1].identifier_.name_); 45 | EXPECT_EQ(naja::verilog::Port::Direction::Input, mod1->ports_[0].direction_); 46 | EXPECT_EQ(naja::verilog::Port::Direction::Output, mod1->ports_[1].direction_); 47 | EXPECT_TRUE(mod1->nets_.empty()); 48 | EXPECT_TRUE(mod1->instances_.empty()); 49 | 50 | auto test = constructor.modules_[2]; 51 | EXPECT_EQ("test", test->identifier_.name_); 52 | EXPECT_FALSE(test->identifier_.escaped_); 53 | ASSERT_EQ(3, test->ports_.size()); 54 | EXPECT_EQ("i", test->ports_[0].identifier_.name_); 55 | EXPECT_EQ("o", test->ports_[1].identifier_.name_); 56 | EXPECT_EQ("io", test->ports_[2].identifier_.name_); 57 | EXPECT_EQ(naja::verilog::Port::Direction::Input, test->ports_[0].direction_); 58 | EXPECT_EQ(naja::verilog::Port::Direction::Output, test->ports_[1].direction_); 59 | EXPECT_EQ(naja::verilog::Port::Direction::InOut, test->ports_[2].direction_); 60 | EXPECT_TRUE(test->nets_.empty()); 61 | EXPECT_TRUE(test->instances_.empty()); 62 | } 63 | { 64 | constructor.setFirstPass(false); 65 | constructor.parse(test3Path); 66 | 67 | EXPECT_EQ(3, constructor.modules_.size()); 68 | auto mod0 = constructor.modules_[0]; 69 | EXPECT_EQ("mod0", mod0->identifier_.name_); 70 | EXPECT_EQ(2, mod0->ports_.size()); 71 | EXPECT_TRUE(mod0->nets_.empty()); 72 | EXPECT_TRUE(mod0->instances_.empty()); 73 | 74 | auto mod1 = constructor.modules_[1]; 75 | EXPECT_EQ("mod1", mod1->identifier_.name_); 76 | EXPECT_EQ(2, mod1->ports_.size()); 77 | EXPECT_TRUE(mod1->nets_.empty()); 78 | EXPECT_TRUE(mod1->instances_.empty()); 79 | 80 | auto test = constructor.modules_[2]; 81 | EXPECT_EQ("test", test->identifier_.name_); 82 | EXPECT_EQ(3, test->ports_.size()); 83 | ASSERT_EQ(8, test->nets_.size()); 84 | EXPECT_EQ("net0", test->nets_[0].identifier_.name_); 85 | EXPECT_EQ("net1", test->nets_[1].identifier_.name_); 86 | EXPECT_EQ("net2", test->nets_[2].identifier_.name_); 87 | EXPECT_EQ("net3", test->nets_[3].identifier_.name_); 88 | EXPECT_EQ("net4", test->nets_[4].identifier_.name_); 89 | EXPECT_EQ("net5", test->nets_[5].identifier_.name_); 90 | EXPECT_EQ("constant0", test->nets_[6].identifier_.name_); 91 | EXPECT_EQ("constant1", test->nets_[7].identifier_.name_); 92 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[0].type_); 93 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[1].type_); 94 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[2].type_); 95 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[3].type_); 96 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[4].type_); 97 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[5].type_); 98 | EXPECT_EQ(naja::verilog::Net::Type::Supply0, test->nets_[6].type_); 99 | EXPECT_EQ(naja::verilog::Net::Type::Supply1, test->nets_[7].type_); 100 | EXPECT_FALSE(test->nets_[0].range_.valid_); 101 | EXPECT_FALSE(test->nets_[1].range_.valid_); 102 | EXPECT_FALSE(test->nets_[2].range_.valid_); 103 | EXPECT_FALSE(test->nets_[3].range_.valid_); 104 | EXPECT_TRUE(test->nets_[4].range_.valid_); 105 | EXPECT_TRUE(test->nets_[5].range_.valid_); 106 | EXPECT_FALSE(test->nets_[6].range_.valid_); 107 | EXPECT_FALSE(test->nets_[7].range_.valid_); 108 | EXPECT_EQ(31, test->nets_[4].range_.msb_); 109 | EXPECT_EQ(0, test->nets_[4].range_.lsb_); 110 | EXPECT_EQ(-2, test->nets_[5].range_.msb_); 111 | EXPECT_EQ(1, test->nets_[5].range_.lsb_); 112 | 113 | ASSERT_EQ(6, test->instances_.size()); 114 | EXPECT_EQ("mod0", test->instances_[0].model_.name_); 115 | EXPECT_EQ("inst0", test->instances_[0].identifier_.name_); 116 | EXPECT_EQ("mod0", test->instances_[1].model_.name_); 117 | EXPECT_EQ("inst1", test->instances_[1].identifier_.name_); 118 | EXPECT_EQ("mod1", test->instances_[2].model_.name_); 119 | EXPECT_EQ("inst2", test->instances_[2].identifier_.name_); 120 | EXPECT_EQ("mod1", test->instances_[3].model_.name_); 121 | EXPECT_EQ("inst3", test->instances_[3].identifier_.name_); 122 | EXPECT_EQ("mod1", test->instances_[4].model_.name_); 123 | EXPECT_EQ("inst4", test->instances_[4].identifier_.name_); 124 | EXPECT_EQ("mod1", test->instances_[5].model_.name_); 125 | EXPECT_EQ("inst5", test->instances_[5].identifier_.name_); 126 | 127 | auto inst0 = test->instances_[0]; 128 | ASSERT_EQ(2, inst0.connections_.size()); 129 | EXPECT_EQ("i0", inst0.connections_[0].port_.name_); 130 | EXPECT_TRUE(inst0.connections_[0].expression_.valid_); 131 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 132 | inst0.connections_[0].expression_.value_.index()); 133 | auto identifier = 134 | std::get(inst0.connections_[0].expression_.value_); 135 | EXPECT_FALSE(identifier.range_.valid_); 136 | EXPECT_EQ("net0", identifier.identifier_.name_); 137 | EXPECT_FALSE(identifier.identifier_.escaped_); 138 | EXPECT_EQ("o0", inst0.connections_[1].port_.name_); 139 | EXPECT_FALSE(inst0.connections_[1].expression_.valid_); 140 | 141 | auto inst1 = test->instances_[1]; 142 | ASSERT_EQ(2, inst1.connections_.size()); 143 | EXPECT_EQ("i0", inst1.connections_[0].port_.name_); 144 | EXPECT_TRUE(inst1.connections_[0].expression_.valid_); 145 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 146 | inst1.connections_[0].expression_.value_.index()); 147 | identifier = 148 | std::get(inst1.connections_[0].expression_.value_); 149 | EXPECT_TRUE(identifier.range_.valid_); 150 | EXPECT_EQ("net4", identifier.identifier_.name_); 151 | EXPECT_TRUE(identifier.range_.singleValue_); 152 | EXPECT_EQ(21, identifier.range_.msb_); 153 | 154 | EXPECT_EQ("o0", inst1.connections_[1].port_.name_); 155 | EXPECT_TRUE(inst1.connections_[1].expression_.valid_); 156 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 157 | inst1.connections_[1].expression_.value_.index()); 158 | identifier = 159 | std::get(inst1.connections_[1].expression_.value_); 160 | EXPECT_TRUE(identifier.range_.valid_); 161 | EXPECT_EQ("net4", identifier.identifier_.name_); 162 | EXPECT_TRUE(identifier.range_.singleValue_); 163 | EXPECT_EQ(5, identifier.range_.msb_); 164 | 165 | auto inst2 = test->instances_[2]; 166 | ASSERT_EQ(2, inst2.connections_.size()); 167 | EXPECT_EQ("i0", inst2.connections_[0].port_.name_); 168 | EXPECT_TRUE(inst2.connections_[0].expression_.valid_); 169 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 170 | inst2.connections_[0].expression_.value_.index()); 171 | identifier = 172 | std::get(inst2.connections_[0].expression_.value_); 173 | EXPECT_TRUE(identifier.range_.valid_); 174 | EXPECT_EQ("net4", identifier.identifier_.name_); 175 | EXPECT_FALSE(identifier.range_.singleValue_); 176 | EXPECT_EQ(3, identifier.range_.msb_); 177 | EXPECT_EQ(6, identifier.range_.lsb_); 178 | 179 | EXPECT_EQ("o0", inst2.connections_[1].port_.name_); 180 | EXPECT_TRUE(inst2.connections_[1].expression_.valid_); 181 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 182 | inst2.connections_[1].expression_.value_.index()); 183 | identifier = 184 | std::get(inst2.connections_[1].expression_.value_); 185 | EXPECT_FALSE(identifier.range_.valid_); 186 | EXPECT_EQ("net5", identifier.identifier_.name_); 187 | 188 | auto inst3 = test->instances_[3]; 189 | ASSERT_EQ(2, inst3.connections_.size()); 190 | EXPECT_EQ("i0", inst3.connections_[0].port_.name_); 191 | EXPECT_TRUE(inst3.connections_[0].expression_.valid_); 192 | ASSERT_EQ(naja::verilog::Expression::Type::CONCATENATION, 193 | inst3.connections_[0].expression_.value_.index()); 194 | auto concatenation = 195 | std::get(inst3.connections_[0].expression_.value_); 196 | ASSERT_EQ(4, concatenation.expressions_.size()); 197 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 198 | concatenation.expressions_[0].value_.index()); 199 | identifier = 200 | std::get(concatenation.expressions_[0].value_); 201 | EXPECT_FALSE(identifier.range_.valid_); 202 | EXPECT_EQ("net0", identifier.identifier_.name_); 203 | 204 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 205 | concatenation.expressions_[1].value_.index()); 206 | identifier = 207 | std::get(concatenation.expressions_[1].value_); 208 | EXPECT_FALSE(identifier.range_.valid_); 209 | EXPECT_EQ("net1", identifier.identifier_.name_); 210 | 211 | 212 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 213 | concatenation.expressions_[2].value_.index()); 214 | identifier = 215 | std::get(concatenation.expressions_[2].value_); 216 | EXPECT_FALSE(identifier.range_.valid_); 217 | EXPECT_EQ("net2", identifier.identifier_.name_); 218 | EXPECT_FALSE(identifier.identifier_.escaped_); 219 | 220 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 221 | concatenation.expressions_[3].value_.index()); 222 | identifier = 223 | std::get(concatenation.expressions_[3].value_); 224 | EXPECT_TRUE(identifier.range_.valid_); 225 | EXPECT_EQ("net5", identifier.identifier_.name_); 226 | EXPECT_TRUE(identifier.range_.singleValue_); 227 | EXPECT_EQ(-2, identifier.range_.msb_); 228 | 229 | auto inst4 = test->instances_[4]; 230 | ASSERT_EQ(2, inst4.orderedConnections_.size()); 231 | EXPECT_EQ(0, inst4.orderedConnections_[0].portIndex_); 232 | ASSERT_TRUE(inst4.orderedConnections_[0].expression_.valid_); 233 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 234 | inst4.orderedConnections_[0].expression_.value_.index()); 235 | identifier = 236 | std::get(inst4.orderedConnections_[0].expression_.value_); 237 | EXPECT_TRUE(identifier.range_.valid_); 238 | EXPECT_EQ("net4", identifier.identifier_.name_); 239 | EXPECT_FALSE(identifier.range_.singleValue_); 240 | EXPECT_EQ(7, identifier.range_.msb_); 241 | EXPECT_EQ(10, identifier.range_.lsb_); 242 | 243 | EXPECT_EQ(1, inst4.orderedConnections_[1].portIndex_); 244 | ASSERT_TRUE(inst4.orderedConnections_[1].expression_.valid_); 245 | EXPECT_EQ(naja::verilog::Expression::Type::CONCATENATION, 246 | inst4.orderedConnections_[1].expression_.value_.index()); 247 | concatenation = 248 | std::get(inst4.orderedConnections_[1].expression_.value_); 249 | ASSERT_EQ(4, concatenation.expressions_.size()); 250 | 251 | auto inst5 = test->instances_[5]; 252 | ASSERT_EQ(1, inst5.orderedConnections_.size()); 253 | EXPECT_EQ(0, inst5.orderedConnections_[0].portIndex_); 254 | ASSERT_TRUE(inst5.orderedConnections_[0].expression_.valid_); 255 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 256 | inst5.orderedConnections_[0].expression_.value_.index()); 257 | identifier = 258 | std::get(inst5.orderedConnections_[0].expression_.value_); 259 | EXPECT_TRUE(identifier.range_.valid_); 260 | EXPECT_EQ("net4", identifier.identifier_.name_); 261 | EXPECT_FALSE(identifier.range_.singleValue_); 262 | EXPECT_EQ(7, identifier.range_.msb_); 263 | EXPECT_EQ(10, identifier.range_.lsb_); 264 | } 265 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest4.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest4, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test4Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test4.v")); 26 | constructor.parse(test4Path); 27 | ASSERT_EQ(2, constructor.modules_.size()); 28 | 29 | auto test = constructor.modules_[1]; 30 | EXPECT_EQ("test", test->identifier_.name_); 31 | ASSERT_EQ(3, test->ports_.size()); 32 | EXPECT_EQ("i", test->ports_[0].identifier_.name_); 33 | EXPECT_EQ("o", test->ports_[1].identifier_.name_); 34 | EXPECT_EQ("io", test->ports_[2].identifier_.name_); 35 | 36 | EXPECT_EQ(naja::verilog::Port::Direction::Input, test->ports_[0].direction_); 37 | EXPECT_EQ(naja::verilog::Port::Direction::Output, test->ports_[1].direction_); 38 | EXPECT_EQ(naja::verilog::Port::Direction::InOut, test->ports_[2].direction_); 39 | 40 | EXPECT_TRUE(test->nets_.empty()); 41 | 42 | constructor.setFirstPass(false); 43 | constructor.parse(test4Path); 44 | ASSERT_EQ(5, test->nets_.size()); 45 | EXPECT_EQ("_i0_", test->nets_[0].identifier_.name_); 46 | EXPECT_EQ("_i1_", test->nets_[1].identifier_.name_); 47 | EXPECT_EQ("i", test->nets_[2].identifier_.name_); 48 | EXPECT_EQ("o", test->nets_[3].identifier_.name_); 49 | EXPECT_EQ("io", test->nets_[4].identifier_.name_); 50 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[0].type_); 51 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[1].type_); 52 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[2].type_); 53 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[3].type_); 54 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[4].type_); 55 | EXPECT_FALSE(test->nets_[0].range_.valid_); 56 | EXPECT_FALSE(test->nets_[1].range_.valid_); 57 | EXPECT_FALSE(test->nets_[2].range_.valid_); 58 | EXPECT_TRUE(test->nets_[3].range_.valid_); 59 | EXPECT_EQ(3, test->nets_[3].range_.msb_); 60 | EXPECT_EQ(0, test->nets_[3].range_.lsb_); 61 | EXPECT_FALSE(test->nets_[4].range_.valid_); 62 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest5.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest5, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test5Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test5.v")); 26 | constructor.parse(test5Path); 27 | ASSERT_EQ(1, constructor.modules_.size()); 28 | auto test = constructor.modules_[0]; 29 | EXPECT_EQ("test", test->identifier_.name_); 30 | 31 | ASSERT_EQ(1, test->ports_.size()); 32 | EXPECT_EQ("asqrt[33]", test->ports_[0].identifier_.name_); 33 | EXPECT_TRUE(test->ports_[0].identifier_.escaped_); 34 | EXPECT_EQ(naja::verilog::Port::Direction::Output, test->ports_[0].direction_); 35 | 36 | EXPECT_TRUE(test->nets_.empty()); 37 | EXPECT_TRUE(test->instances_.empty()); 38 | 39 | constructor.setFirstPass(false); 40 | constructor.parse(test5Path); 41 | ASSERT_EQ(3, test->nets_.size()); 42 | EXPECT_EQ("asqrt[33]", test->nets_[0].identifier_.name_); 43 | EXPECT_TRUE(test->nets_[0].identifier_.escaped_); 44 | EXPECT_EQ("_0746_", test->nets_[1].identifier_.name_); 45 | EXPECT_EQ("_0747_", test->nets_[2].identifier_.name_); 46 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[0].type_); 47 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[1].type_); 48 | EXPECT_EQ(naja::verilog::Net::Type::Wire, test->nets_[2].type_); 49 | EXPECT_FALSE(test->nets_[0].range_.valid_); 50 | EXPECT_FALSE(test->nets_[1].range_.valid_); 51 | EXPECT_FALSE(test->nets_[2].range_.valid_); 52 | 53 | EXPECT_EQ(1, test->instances_.size()); 54 | const VerilogConstructorTest::Instance& instance = test->instances_[0]; 55 | EXPECT_EQ("_4370_", instance.identifier_.name_); 56 | EXPECT_EQ("LUT4", instance.model_.name_); 57 | EXPECT_EQ(1, instance.parameterAssignments_.size()); 58 | EXPECT_EQ("INIT", instance.parameterAssignments_.begin()->first); 59 | EXPECT_EQ("8'h2b", instance.parameterAssignments_.begin()->second); 60 | EXPECT_EQ(5, instance.connections_.size()); 61 | EXPECT_EQ("I0", instance.connections_[0].port_.name_); 62 | EXPECT_EQ("I1", instance.connections_[1].port_.name_); 63 | EXPECT_EQ("I2", instance.connections_[2].port_.name_); 64 | EXPECT_EQ("I3", instance.connections_[3].port_.name_); 65 | EXPECT_EQ("Q", instance.connections_[4].port_.name_); 66 | EXPECT_TRUE(instance.connections_[0].expression_.supported_); 67 | EXPECT_TRUE(instance.connections_[1].expression_.supported_); 68 | EXPECT_TRUE(instance.connections_[2].expression_.supported_); 69 | EXPECT_TRUE(instance.connections_[3].expression_.supported_); 70 | EXPECT_TRUE(instance.connections_[4].expression_.supported_); 71 | EXPECT_TRUE(instance.connections_[0].expression_.valid_); 72 | EXPECT_TRUE(instance.connections_[1].expression_.valid_); 73 | EXPECT_TRUE(instance.connections_[2].expression_.valid_); 74 | EXPECT_TRUE(instance.connections_[3].expression_.valid_); 75 | EXPECT_FALSE(instance.connections_[4].expression_.valid_); 76 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 77 | instance.connections_[0].expression_.value_.index()); 78 | auto identifier = 79 | std::get(instance.connections_[0].expression_.value_); 80 | EXPECT_FALSE(identifier.range_.valid_); 81 | EXPECT_EQ("_0746_", identifier.identifier_.name_); 82 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 83 | instance.connections_[1].expression_.value_.index()); 84 | identifier = 85 | std::get(instance.connections_[1].expression_.value_); 86 | EXPECT_FALSE(identifier.range_.valid_); 87 | EXPECT_EQ("_0747_", identifier.identifier_.name_); 88 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, 89 | instance.connections_[2].expression_.value_.index()); 90 | identifier = 91 | std::get(instance.connections_[2].expression_.value_); 92 | EXPECT_FALSE(identifier.range_.valid_); 93 | EXPECT_EQ("asqrt[33]", identifier.identifier_.name_); 94 | EXPECT_TRUE(identifier.identifier_.escaped_); 95 | EXPECT_EQ(naja::verilog::Expression::Type::NUMBER, 96 | instance.connections_[3].expression_.value_.index()); 97 | auto number = 98 | std::get(instance.connections_[3].expression_.value_); 99 | EXPECT_EQ(naja::verilog::Number::Type::BASED, number.value_.index()); 100 | auto basedNumber = 101 | std::get(number.value_); 102 | EXPECT_EQ(naja::verilog::BasedNumber::Base::HEX, basedNumber.base_); 103 | EXPECT_EQ(1, basedNumber.size_); 104 | EXPECT_EQ("0", basedNumber.digits_); 105 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest6.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest6, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test6Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test6.v")); 26 | constructor.parse(test6Path); 27 | ASSERT_EQ(1, constructor.modules_.size()); 28 | auto test = constructor.modules_[0]; 29 | EXPECT_EQ("test", test->identifier_.name_); 30 | EXPECT_EQ(1, constructor.modules_.size()); 31 | { 32 | auto mod = constructor.modules_[0]; 33 | EXPECT_TRUE(mod->assigns_.empty()); 34 | } 35 | 36 | constructor.setFirstPass(false); 37 | constructor.parse(test6Path); 38 | EXPECT_EQ(1, constructor.modules_.size()); 39 | auto mod = constructor.modules_[0]; 40 | EXPECT_FALSE(mod->assigns_.empty()); 41 | EXPECT_EQ(4, mod->assigns_.size()); 42 | 43 | { 44 | auto assign = mod->assigns_[0]; 45 | EXPECT_EQ(1, assign.identifiers_.size()); 46 | auto identifier = assign.identifiers_[0]; 47 | EXPECT_EQ("n0", identifier.identifier_.name_); 48 | EXPECT_FALSE(identifier.range_.valid_); 49 | auto expression = assign.expression_; 50 | EXPECT_TRUE(expression.valid_); 51 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, expression.value_.index()); 52 | auto leftId = std::get(expression.value_); 53 | EXPECT_EQ("n1", leftId.identifier_.name_); 54 | EXPECT_FALSE(leftId.range_.valid_); 55 | } 56 | 57 | { 58 | auto assign = mod->assigns_[1]; 59 | EXPECT_EQ(1, assign.identifiers_.size()); 60 | auto identifier = assign.identifiers_[0]; 61 | EXPECT_EQ("n1", identifier.identifier_.name_); 62 | EXPECT_FALSE(identifier.range_.valid_); 63 | auto expression = assign.expression_; 64 | EXPECT_TRUE(expression.valid_); 65 | EXPECT_EQ(naja::verilog::Expression::Type::NUMBER, expression.value_.index()); 66 | auto leftId = std::get(expression.value_); 67 | EXPECT_TRUE(leftId.sign_); 68 | EXPECT_EQ(naja::verilog::Number::BASED, leftId.value_.index()); 69 | auto leftBaseNumber = std::get(leftId.value_); 70 | EXPECT_FALSE(leftBaseNumber.signed_); 71 | EXPECT_EQ(naja::verilog::BasedNumber::BINARY, leftBaseNumber.base_); 72 | EXPECT_EQ(1, leftBaseNumber.size_); 73 | EXPECT_EQ("0", leftBaseNumber.digits_); 74 | } 75 | 76 | { 77 | auto assign = mod->assigns_[2]; 78 | EXPECT_EQ(2, assign.identifiers_.size()); 79 | auto id0 = assign.identifiers_[0]; 80 | EXPECT_EQ("n2", id0.identifier_.name_); 81 | EXPECT_TRUE(id0.range_.valid_); 82 | EXPECT_EQ(3, id0.range_.msb_); 83 | EXPECT_EQ(2, id0.range_.lsb_); 84 | auto id1 = assign.identifiers_[1]; 85 | EXPECT_EQ("n2", id1.identifier_.name_); 86 | EXPECT_TRUE(id1.range_.valid_); 87 | EXPECT_EQ(1, id1.range_.msb_); 88 | EXPECT_EQ(0, id1.range_.lsb_); 89 | auto expression = assign.expression_; 90 | EXPECT_TRUE(expression.valid_); 91 | EXPECT_EQ(naja::verilog::Expression::Type::CONCATENATION, expression.value_.index()); 92 | auto concatenation = std::get(expression.value_); 93 | EXPECT_EQ(3, concatenation.expressions_.size()); 94 | EXPECT_TRUE(concatenation.expressions_[2].valid_); 95 | auto constant = concatenation.expressions_[2]; 96 | EXPECT_EQ(naja::verilog::Expression::NUMBER, constant.value_.index()); 97 | auto constantValue = std::get(constant.value_); 98 | EXPECT_TRUE(constantValue.sign_); 99 | EXPECT_EQ(naja::verilog::Number::BASED, constantValue.value_.index()); 100 | auto constantNumber = std::get(constantValue.value_); 101 | EXPECT_FALSE(constantNumber.signed_); 102 | EXPECT_EQ(naja::verilog::BasedNumber::HEX, constantNumber.base_); 103 | EXPECT_EQ(2, constantNumber.size_); 104 | EXPECT_EQ("2", constantNumber.digits_); 105 | } 106 | 107 | { 108 | auto assign = mod->assigns_[3]; 109 | EXPECT_EQ(1, assign.identifiers_.size()); 110 | auto identifier = assign.identifiers_[0]; 111 | EXPECT_EQ("n3", identifier.identifier_.name_); 112 | EXPECT_FALSE(identifier.range_.valid_); 113 | auto expression = assign.expression_; 114 | EXPECT_TRUE(expression.valid_); 115 | EXPECT_EQ(naja::verilog::Expression::Type::NUMBER, expression.value_.index()); 116 | auto leftId = std::get(expression.value_); 117 | EXPECT_TRUE(leftId.sign_); 118 | EXPECT_EQ(naja::verilog::Number::BASED, leftId.value_.index()); 119 | auto leftBaseNumber = std::get(leftId.value_); 120 | EXPECT_TRUE(leftBaseNumber.signed_); 121 | EXPECT_EQ(naja::verilog::BasedNumber::HEX, leftBaseNumber.base_); 122 | EXPECT_EQ(4, leftBaseNumber.size_); 123 | EXPECT_EQ("F", leftBaseNumber.digits_); 124 | } 125 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest7.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest7, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test7Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test7.v")); 26 | constructor.parse(test7Path); 27 | ASSERT_EQ(1, constructor.modules_.size()); 28 | auto test = constructor.modules_[0]; 29 | EXPECT_EQ("test", test->identifier_.name_); 30 | 31 | constructor.setFirstPass(false); 32 | constructor.parse(test7Path); 33 | 34 | ASSERT_EQ(1, constructor.modules_[0]->instances_.size()); 35 | auto instance = constructor.modules_[0]->instances_[0]; 36 | EXPECT_EQ("ins", instance.identifier_.name_); 37 | EXPECT_EQ("mod", instance.model_.name_); 38 | ASSERT_EQ(3, instance.parameterAssignments_.size()); 39 | auto paramIt = instance.parameterAssignments_.find("PARAM0"); 40 | ASSERT_TRUE(paramIt != instance.parameterAssignments_.end()); 41 | EXPECT_TRUE(paramIt->second.empty()); 42 | paramIt = instance.parameterAssignments_.find("PARAM1"); 43 | ASSERT_TRUE(paramIt != instance.parameterAssignments_.end()); 44 | EXPECT_EQ("A", paramIt->second); 45 | paramIt = instance.parameterAssignments_.find("PARAM2"); 46 | ASSERT_TRUE(paramIt != instance.parameterAssignments_.end()); 47 | EXPECT_EQ("VALUE", paramIt->second); 48 | } -------------------------------------------------------------------------------- /test/NajaVerilogTest8.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2024 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest8, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test8Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test8.v")); 26 | 27 | constructor.setFirstPass(true); 28 | constructor.parse(test8Path); 29 | ASSERT_EQ(1, constructor.modules_.size()); 30 | auto test = constructor.modules_[0]; 31 | EXPECT_EQ(naja::verilog::Identifier("mod%", true), test->identifier_); 32 | EXPECT_TRUE(constructor.modules_[0]->instances_.empty()); 33 | EXPECT_TRUE(constructor.modules_[0]->nets_.empty()); 34 | EXPECT_TRUE(constructor.modules_[0]->assigns_.empty()); 35 | ASSERT_EQ(1, constructor.modules_[0]->ports_.size()); 36 | EXPECT_EQ(naja::verilog::Identifier("asqrt", true), constructor.modules_[0]->ports_[0].identifier_); 37 | EXPECT_EQ(naja::verilog::Port::Direction::Output, constructor.modules_[0]->ports_[0].direction_); 38 | EXPECT_TRUE(constructor.modules_[0]->ports_[0].isBus()); 39 | EXPECT_EQ(naja::verilog::Range(40, 0), constructor.modules_[0]->ports_[0].range_); 40 | 41 | constructor.setFirstPass(false); 42 | constructor.parse(test8Path); 43 | ASSERT_EQ(1, constructor.modules_.size()); 44 | ASSERT_EQ(1, constructor.modules_[0]->instances_.size()); 45 | auto instance = constructor.modules_[0]->instances_[0]; 46 | EXPECT_EQ("ins@2", instance.identifier_.name_); 47 | EXPECT_EQ("$$MOD", instance.model_.name_); 48 | EXPECT_TRUE(instance.orderedConnections_.empty()); 49 | ASSERT_EQ(5, instance.connections_.size()); 50 | EXPECT_EQ(naja::verilog::Identifier("I0", false), instance.connections_[0].port_); 51 | EXPECT_EQ(naja::verilog::Identifier("I1", false), instance.connections_[1].port_); 52 | EXPECT_EQ(naja::verilog::Identifier("I2", false), instance.connections_[2].port_); 53 | EXPECT_EQ(naja::verilog::Identifier("I3", false), instance.connections_[3].port_); 54 | EXPECT_EQ(naja::verilog::Identifier("Q", false), instance.connections_[4].port_); 55 | EXPECT_EQ(naja::verilog::Expression::Type::RANGEIDENTIFIER, instance.connections_[0].expression_.value_.index()); 56 | auto identifier = 57 | std::get(instance.connections_[0].expression_.value_); 58 | EXPECT_EQ(naja::verilog::Identifier("busa+index", true), identifier.identifier_); 59 | EXPECT_FALSE(identifier.range_.valid_); 60 | identifier = 61 | std::get(instance.connections_[1].expression_.value_); 62 | EXPECT_EQ(naja::verilog::Identifier("-clock", true), identifier.identifier_); 63 | EXPECT_FALSE(identifier.range_.valid_); 64 | identifier = 65 | std::get(instance.connections_[2].expression_.value_); 66 | EXPECT_EQ(naja::verilog::Identifier("asqrt[33]", true), identifier.identifier_); 67 | EXPECT_FALSE(identifier.range_.valid_); 68 | identifier = 69 | std::get(instance.connections_[3].expression_.value_); 70 | EXPECT_EQ(naja::verilog::Identifier("asqrt", true), identifier.identifier_); 71 | EXPECT_TRUE(identifier.range_.valid_); 72 | EXPECT_EQ(naja::verilog::Range(33), identifier.range_); 73 | identifier = 74 | std::get(instance.connections_[4].expression_.value_); 75 | EXPECT_EQ(naja::verilog::Identifier("{a,b}", true), identifier.identifier_); 76 | EXPECT_FALSE(identifier.range_.valid_); 77 | } 78 | -------------------------------------------------------------------------------- /test/NajaVerilogTest9.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2024 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTest9, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path test9Path( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("test9.v")); 26 | 27 | constructor.setFirstPass(true); 28 | constructor.parse(test9Path); 29 | ASSERT_EQ(1, constructor.modules_.size()); 30 | EXPECT_TRUE(constructor.modules_[0]->nets_.empty()); 31 | EXPECT_TRUE(constructor.modules_[0]->assigns_.empty()); 32 | EXPECT_TRUE(constructor.modules_[0]->instances_.empty()); 33 | auto test = constructor.modules_[0]; 34 | const auto& ports = constructor.modules_[0]->ports_; 35 | ASSERT_EQ(7, constructor.modules_[0]->ports_.size()); 36 | EXPECT_EQ(naja::verilog::Identifier("i1", false), ports[0].identifier_); 37 | EXPECT_EQ(naja::verilog::Identifier("i2%", true), ports[1].identifier_); 38 | EXPECT_EQ(naja::verilog::Identifier("i3", false), ports[2].identifier_); 39 | EXPECT_EQ(naja::verilog::Identifier("o1", false), ports[3].identifier_); 40 | EXPECT_EQ(naja::verilog::Identifier("o2", false), ports[4].identifier_); 41 | EXPECT_EQ(naja::verilog::Identifier("io1", false), ports[5].identifier_); 42 | EXPECT_EQ(naja::verilog::Identifier("io2", false), ports[6].identifier_); 43 | 44 | EXPECT_EQ(naja::verilog::Port::Direction::Input, ports[0].direction_); 45 | EXPECT_EQ(naja::verilog::Port::Direction::Input, ports[1].direction_); 46 | EXPECT_EQ(naja::verilog::Port::Direction::Input, ports[2].direction_); 47 | EXPECT_EQ(naja::verilog::Port::Direction::Output, ports[3].direction_); 48 | EXPECT_EQ(naja::verilog::Port::Direction::Output, ports[4].direction_); 49 | EXPECT_EQ(naja::verilog::Port::Direction::InOut, ports[5].direction_); 50 | EXPECT_EQ(naja::verilog::Port::Direction::InOut, ports[6].direction_); 51 | 52 | EXPECT_FALSE(ports[0].range_.valid_); 53 | EXPECT_FALSE(ports[1].range_.valid_); 54 | EXPECT_FALSE(ports[2].range_.valid_); 55 | EXPECT_TRUE(ports[3].range_.valid_); 56 | EXPECT_EQ(3, ports[3].range_.msb_); 57 | EXPECT_EQ(0, ports[3].range_.lsb_); 58 | EXPECT_TRUE(ports[4].range_.valid_); 59 | EXPECT_EQ(3, ports[4].range_.msb_); 60 | EXPECT_EQ(0, ports[4].range_.lsb_); 61 | EXPECT_FALSE(ports[5].range_.valid_); 62 | EXPECT_FALSE(ports[6].range_.valid_); 63 | 64 | constructor.setFirstPass(false); 65 | constructor.parse(test9Path); 66 | ASSERT_EQ(1, constructor.modules_.size()); 67 | EXPECT_TRUE(constructor.modules_[0]->assigns_.empty()); 68 | EXPECT_TRUE(constructor.modules_[0]->instances_.empty()); 69 | EXPECT_EQ(8, constructor.modules_[0]->nets_.size()); 70 | const auto& nets = constructor.modules_[0]->nets_; 71 | EXPECT_EQ(naja::verilog::Identifier("macu_n_280", false), nets[0].identifier_); 72 | EXPECT_EQ(naja::verilog::Identifier("macu_n_281", false), nets[1].identifier_); 73 | EXPECT_EQ(naja::verilog::Identifier("macu_n_282", false), nets[2].identifier_); 74 | EXPECT_EQ(naja::verilog::Identifier("macu_result[0]_203", true), nets[3].identifier_); 75 | EXPECT_EQ(naja::verilog::Identifier("macu_result[1]_204", true), nets[4].identifier_); 76 | EXPECT_EQ(naja::verilog::Identifier("macu_result[2]_205", true), nets[5].identifier_); 77 | EXPECT_EQ(naja::verilog::Identifier("macu_result[3]_206", true), nets[6].identifier_); 78 | EXPECT_EQ(naja::verilog::Identifier("macu_result[4]_207", true), nets[7].identifier_); 79 | } -------------------------------------------------------------------------------- /test/NajaVerilogTestErrors.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | #include "VerilogException.h" 12 | 13 | using namespace naja::verilog; 14 | 15 | #include "VerilogConstructorTest.h" 16 | 17 | #ifndef NAJA_VERILOG_BENCHMARKS 18 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 19 | #endif 20 | 21 | TEST(NajaVerilogTestErrors, testErrorPath) { 22 | VerilogConstructorTest constructor; 23 | std::filesystem::path errorPath("does_not_exist.v"); 24 | EXPECT_THROW(constructor.parse(errorPath), VerilogException); 25 | } 26 | 27 | TEST(NajaVerilogTestErrors, test0) { 28 | std::filesystem::path error0Path( 29 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 30 | / std::filesystem::path("benchmarks") 31 | / std::filesystem::path("errors") 32 | / std::filesystem::path("error0.v")); 33 | VerilogConstructorTest constructor; 34 | EXPECT_THROW(constructor.parse(error0Path), VerilogException); 35 | } 36 | 37 | TEST(NajaVerilogTestErrors, test1) { 38 | std::filesystem::path error1Path( 39 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 40 | / std::filesystem::path("benchmarks") 41 | / std::filesystem::path("errors") 42 | / std::filesystem::path("error1.v")); 43 | VerilogConstructorTest constructor; 44 | EXPECT_THROW(constructor.parse(error1Path), VerilogException); 45 | } 46 | 47 | TEST(NajaVerilogTestErrors, test2) { 48 | std::filesystem::path error2Path( 49 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 50 | / std::filesystem::path("benchmarks") 51 | / std::filesystem::path("errors") 52 | / std::filesystem::path("error2.v")); 53 | VerilogConstructorTest constructor; 54 | EXPECT_THROW(constructor.parse(error2Path), VerilogException); 55 | } 56 | 57 | TEST(NajaVerilogTestErrors, testVerilogTypeErrors) { 58 | auto number = Number("2", false, 'b', "00"); 59 | EXPECT_THROW(number.getInt(), VerilogException); 60 | } -------------------------------------------------------------------------------- /test/NajaVerilogTestMultipleFiles.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "gtest/gtest.h" 6 | 7 | #include 8 | #include 9 | 10 | #include "VerilogConstructor.h" 11 | 12 | using namespace naja::verilog; 13 | 14 | #include "VerilogConstructorTest.h" 15 | 16 | #ifndef NAJA_VERILOG_BENCHMARKS 17 | #define NAJA_VERILOG_BENCHMARKS "Undefined" 18 | #endif 19 | 20 | TEST(NajaVerilogTestMultipleFiles, test) { 21 | VerilogConstructorTest constructor; 22 | std::filesystem::path multipleFilesPath( 23 | std::filesystem::path(NAJA_VERILOG_BENCHMARKS) 24 | / std::filesystem::path("benchmarks") 25 | / std::filesystem::path("multifiles")); 26 | VerilogConstructor::Paths paths; 27 | paths.push_back(multipleFilesPath / std::filesystem::path("mod0.v")); 28 | paths.push_back(multipleFilesPath / std::filesystem::path("mod1.v")); 29 | paths.push_back(multipleFilesPath / std::filesystem::path("top.v")); 30 | constructor.parse(paths); 31 | ASSERT_EQ(3, constructor.modules_.size()); 32 | EXPECT_EQ("mod0", constructor.modules_[0]->identifier_.name_); 33 | EXPECT_EQ("mod1", constructor.modules_[1]->identifier_.name_); 34 | EXPECT_EQ("top", constructor.modules_[2]->identifier_.name_); 35 | ASSERT_EQ(2, constructor.modules_[0]->ports_.size()); 36 | ASSERT_EQ(2, constructor.modules_[1]->ports_.size()); 37 | ASSERT_EQ(2, constructor.modules_[2]->ports_.size()); 38 | 39 | constructor.setFirstPass(false); 40 | constructor.parse(paths); 41 | 42 | EXPECT_TRUE(constructor.modules_[0]->instances_.empty()); 43 | EXPECT_TRUE(constructor.modules_[1]->instances_.empty()); 44 | ASSERT_EQ(2, constructor.modules_[2]->instances_.size()); 45 | auto ins0 = constructor.modules_[2]->instances_[0]; 46 | EXPECT_EQ("ins0", ins0.identifier_.name_); 47 | EXPECT_EQ("mod0", ins0.model_.name_); 48 | auto ins1 = constructor.modules_[2]->instances_[1]; 49 | EXPECT_EQ("ins1", ins1.identifier_.name_); 50 | EXPECT_EQ("mod1", ins1.model_.name_); 51 | } -------------------------------------------------------------------------------- /test/VerilogConstructorTest.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "VerilogConstructorTest.h" 6 | 7 | #include 8 | #include 9 | 10 | VerilogConstructorTest::~VerilogConstructorTest() { 11 | for (auto module: modules_) { 12 | delete module; 13 | } 14 | } 15 | 16 | void VerilogConstructorTest::addModule(Module* module) { 17 | assert(modulesMap_.find(module->identifier_.name_) == modulesMap_.end()); 18 | modulesMap_[module->identifier_.name_] = module; 19 | modules_.push_back(module); 20 | } 21 | 22 | void VerilogConstructorTest::startModule(const naja::verilog::Identifier& identifier) { 23 | if (inFirstPass()) { 24 | currentModule_ = new Module(identifier); 25 | addModule(currentModule_); 26 | //currentModuleAttributes_.clear(); 27 | std::cerr << "Construct Module: " << identifier.getString() << std::endl; 28 | } else { 29 | if (auto it = modulesMap_.find(identifier.name_); it != modulesMap_.end()) { 30 | currentModule_ = it->second; 31 | } else { 32 | std::cerr << "Cannot find Module: " << identifier.getString() << std::endl; 33 | exit(5); 34 | } 35 | } 36 | } 37 | 38 | void VerilogConstructorTest::moduleInterfaceSimplePort(const naja::verilog::Identifier& port) { 39 | if (inFirstPass()) { 40 | std::cerr << "Construct Simple: " << port.getString() << std::endl; 41 | } 42 | } 43 | 44 | void VerilogConstructorTest::moduleInterfaceCompletePort(const naja::verilog::Port& port) { 45 | if (inFirstPass()) { 46 | std::cerr << "Interface Complete: " << port.getString() << std::endl; 47 | currentModule_->ports_.push_back(std::move(port)); 48 | } 49 | } 50 | 51 | void VerilogConstructorTest::moduleImplementationPort(const naja::verilog::Port& port) { 52 | if (inFirstPass()) { 53 | std::cerr << "Implementation Complete: " << port.getString() << std::endl; 54 | currentModule_->ports_.push_back(std::move(port)); 55 | } 56 | } 57 | 58 | void VerilogConstructorTest::addNet(const naja::verilog::Net& net) { 59 | if (not inFirstPass()) { 60 | std::cerr << "Add net: " << net.getString() << std::endl; 61 | //net.addAttributes(nextObjectAttributes_); 62 | currentModule_->nets_.push_back(std::move(net)); 63 | } 64 | nextObjectAttributes_.clear(); 65 | } 66 | 67 | void VerilogConstructorTest::startInstantiation(const naja::verilog::Identifier& model) { 68 | if (not inFirstPass()) { 69 | std::cerr << "startInstantiation: " << model.getString() << std::endl; 70 | currentModelName_ = model.name_; 71 | } 72 | } 73 | 74 | void VerilogConstructorTest::endInstantiation() { 75 | if (not nextObjectAttributes_.empty()) { 76 | //error 77 | } 78 | if (not inFirstPass()) { 79 | std::cerr << "Finish Instantiation of: " << currentModelName_ << std::endl; 80 | Instance& instance = currentModule_->instances_.back(); 81 | instance.parameterAssignments_.swap(currentModule_->currentInstanceParameterAssignments_); 82 | currentModelName_ = std::string(); 83 | } 84 | } 85 | 86 | void VerilogConstructorTest::addInstance(const naja::verilog::Identifier& instanceID) { 87 | if (not inFirstPass()) { 88 | std::cerr << "Add instance: " << instanceID.getString() << std::endl; 89 | auto instance = Instance(currentModelName_, instanceID.getString()); 90 | instance.addAttributes(nextObjectAttributes_); 91 | currentModule_->instances_.push_back(instance); 92 | } 93 | nextObjectAttributes_.clear(); 94 | } 95 | 96 | void VerilogConstructorTest::addInstanceConnection( 97 | const naja::verilog::Identifier& port, 98 | const naja::verilog::Expression& expression) { 99 | if (not inFirstPass()) { 100 | std::cerr << "Add instance connection: " 101 | << port.getString() << " " << expression.getString() << std::endl; 102 | Instance& instance = currentModule_->instances_.back(); 103 | instance.connections_.push_back(InstanceConnection(port.name_, expression)); 104 | } 105 | } 106 | 107 | void VerilogConstructorTest::addOrderedInstanceConnection( 108 | size_t portIndex, 109 | const naja::verilog::Expression& expression) { 110 | if (not inFirstPass()) { 111 | std::cerr << "Add ordered instance connection: " 112 | << portIndex << " " << expression.getString() << std::endl; 113 | Instance& instance = currentModule_->instances_.back(); 114 | instance.orderedConnections_.push_back(OrderedInstanceConnection(portIndex, expression)); 115 | } 116 | } 117 | 118 | void VerilogConstructorTest::addParameterAssignment( 119 | const naja::verilog::Identifier& parameter, 120 | const naja::verilog::Expression& expression) { 121 | if (not inFirstPass()) { 122 | std::cerr << "Add parameter assignment: " 123 | << parameter.getString() << " " << expression.getString() << std::endl; 124 | currentModule_->currentInstanceParameterAssignments_[parameter.getString()] = expression.getString(); 125 | } 126 | } 127 | 128 | void VerilogConstructorTest::addAssign( 129 | const naja::verilog::RangeIdentifiers& identifiers, 130 | const naja::verilog::Expression& expression) { 131 | if (not inFirstPass()) { 132 | currentModule_->assigns_.push_back(Assign(identifiers, expression)); 133 | } 134 | } 135 | 136 | void VerilogConstructorTest::addDefParameterAssignment( 137 | const naja::verilog::Identifiers& hierarchicalParameter, 138 | const naja::verilog::ConstantExpression& expression) { 139 | if (not inFirstPass()) { 140 | currentModule_->defParameterAssignments_.push_back( 141 | VerilogConstructorTest::Module::DefParameterAssignment(hierarchicalParameter, expression)); 142 | } 143 | } 144 | 145 | void VerilogConstructorTest::addAttribute( 146 | const naja::verilog::Identifier& attributeName, 147 | const naja::verilog::ConstantExpression& expression) { 148 | nextObjectAttributes_.push_back(naja::verilog::Attribute(attributeName, expression)); 149 | } -------------------------------------------------------------------------------- /test/VerilogConstructorTest.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | // 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #ifndef __VERILOG_CONSTRUCTOR_TEST_H_ 6 | #define __VERILOG_CONSTRUCTOR_TEST_H_ 7 | 8 | #include "VerilogConstructor.h" 9 | 10 | #include 11 | #include 12 | 13 | class VerilogConstructorTest: public naja::verilog::VerilogConstructor { 14 | public: 15 | ~VerilogConstructorTest(); 16 | bool inFirstPass() const { return firstPass_; } 17 | void setFirstPass(bool mode) { firstPass_ = mode; } 18 | void startModule(const naja::verilog::Identifier& id) override; 19 | void moduleInterfaceSimplePort(const naja::verilog::Identifier& id) override; 20 | void moduleImplementationPort(const naja::verilog::Port& port) override; 21 | void moduleInterfaceCompletePort(const naja::verilog::Port& port) override; 22 | void startInstantiation(const naja::verilog::Identifier& model) override; 23 | void addInstance(const naja::verilog::Identifier& name) override; 24 | void addInstanceConnection( 25 | const naja::verilog::Identifier& port, 26 | const naja::verilog::Expression& expression) override; 27 | void addOrderedInstanceConnection( 28 | size_t portIndex, 29 | const naja::verilog::Expression& expression) override; 30 | void addParameterAssignment( 31 | const naja::verilog::Identifier& parameter, 32 | const naja::verilog::Expression& expression) override; 33 | void endInstantiation() override; 34 | void addNet(const naja::verilog::Net& net) override; 35 | void addAssign( 36 | const naja::verilog::RangeIdentifiers& identifiers, 37 | const naja::verilog::Expression& expression) override; 38 | virtual void addDefParameterAssignment( 39 | const naja::verilog::Identifiers& hierarchicalParameter, 40 | const naja::verilog::ConstantExpression& expression) override; 41 | void addAttribute( 42 | const naja::verilog::Identifier& attributeName, 43 | const naja::verilog::ConstantExpression& expression) override; 44 | struct OrderedInstanceConnection { 45 | OrderedInstanceConnection() = default; 46 | OrderedInstanceConnection(const OrderedInstanceConnection&) = default; 47 | OrderedInstanceConnection( 48 | const size_t portIndex, 49 | const naja::verilog::Expression& expression): 50 | portIndex_(portIndex), 51 | expression_(expression) 52 | {} 53 | 54 | std::string getString() const { 55 | std::ostringstream stream; 56 | stream << "OrderedInstanceConnection - port: " 57 | << portIndex_ << " : " << expression_.getString(); 58 | return stream.str(); 59 | } 60 | 61 | size_t portIndex_ {0}; 62 | naja::verilog::Expression expression_ {}; 63 | }; 64 | 65 | using Attributes = std::list; 66 | 67 | struct ObjectWithAttributes { 68 | ObjectWithAttributes() = default; 69 | void addAttributes(const Attributes& attributes) { 70 | attributes_.insert(attributes_.end(), attributes.begin(), attributes.end()); 71 | } 72 | 73 | Attributes attributes_ {}; 74 | }; 75 | 76 | struct InstanceConnection { 77 | InstanceConnection() = default; 78 | InstanceConnection(const InstanceConnection&) = default; 79 | InstanceConnection( 80 | const naja::verilog::Identifier& port, 81 | const naja::verilog::Expression& expression): 82 | port_(port), 83 | expression_(expression) 84 | {} 85 | 86 | std::string getString() const { 87 | std::ostringstream stream; 88 | stream << "InstanceConnection - port: " 89 | << port_.getString() << " : " << expression_.getString(); 90 | return stream.str(); 91 | } 92 | 93 | naja::verilog::Identifier port_ {}; 94 | naja::verilog::Expression expression_ {}; 95 | }; 96 | 97 | struct Instance: public ObjectWithAttributes { 98 | using Connections = std::vector; 99 | using OrderedConnections = std::vector; 100 | using ParameterAssignments = std::map; 101 | Instance() = default; 102 | Instance(const Instance&) = default; 103 | Instance(const naja::verilog::Identifier& model, const naja::verilog::Identifier& id): 104 | model_(model), identifier_(id) 105 | {} 106 | 107 | std::string getString() const { 108 | std::ostringstream stream; 109 | stream << "Instance: (" << model_.getString() << ") " 110 | << identifier_.getString(); 111 | return stream.str(); 112 | } 113 | 114 | naja::verilog::Identifier model_ {}; 115 | naja::verilog::Identifier identifier_ {}; 116 | ParameterAssignments parameterAssignments_ {}; 117 | Connections connections_ {}; 118 | OrderedConnections orderedConnections_ {}; 119 | }; 120 | 121 | struct Assign { 122 | Assign( 123 | const naja::verilog::RangeIdentifiers& identifiers, 124 | const naja::verilog::Expression& expression): 125 | identifiers_(identifiers), 126 | expression_(expression) 127 | {} 128 | naja::verilog::RangeIdentifiers identifiers_ {}; 129 | naja::verilog::Expression expression_ {}; 130 | }; 131 | 132 | struct Module { 133 | using Ports = std::vector; 134 | using Nets = std::vector; 135 | using Instances = std::vector; 136 | using Assigns = std::vector; 137 | using DefParameterAssignment = std::pair; 138 | using DefParameterAssignments = std::vector; 139 | naja::verilog::Identifier identifier_ {}; 140 | Ports ports_ {}; 141 | Nets nets_ {}; 142 | Assigns assigns_ {}; 143 | Instances instances_ {}; 144 | Instance::ParameterAssignments currentInstanceParameterAssignments_ {}; 145 | DefParameterAssignments defParameterAssignments_ {}; 146 | 147 | Module(const naja::verilog::Identifier& identifier): 148 | identifier_(identifier) 149 | {} 150 | }; 151 | 152 | using Modules = std::vector; 153 | using ModulesMap = std::map; 154 | void addModule(Module* module); 155 | 156 | bool firstPass_ {true}; 157 | Modules modules_ {}; 158 | ModulesMap modulesMap_ {}; 159 | Module* currentModule_ {nullptr}; 160 | Attributes nextObjectAttributes_ {}; 161 | std::string currentModelName_ {}; 162 | }; 163 | 164 | #endif /* __VERILOG_CONSTRUCTOR_TEST_H_ */ 165 | -------------------------------------------------------------------------------- /test/benchmarks/errors/error0.v: -------------------------------------------------------------------------------- 1 | /* 2 | Unterminated comment 3 | */ 4 | 5 | module test(); 6 | endmodule 7 | 8 | /* 9 | This is not terminated -------------------------------------------------------------------------------- /test/benchmarks/errors/error1.v: -------------------------------------------------------------------------------- 1 | /* 2 | Unterminated pragma 3 | */ 4 | 5 | (* src = "/home/source/test.v" 6 | module test(); 7 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/errors/error2.v: -------------------------------------------------------------------------------- 1 | /* 2 | Syntax error 3 | */ 4 | 5 | module test(); 6 | //Missing ";" 7 | model ins 8 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/multifiles/mod0.v: -------------------------------------------------------------------------------- 1 | module mod0(input i, output o); 2 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/multifiles/mod1.v: -------------------------------------------------------------------------------- 1 | module mod1(input a, output b); 2 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/multifiles/top.v: -------------------------------------------------------------------------------- 1 | module top(input in, output out); 2 | wire n; 3 | mod0 ins0(in, n); 4 | mod1 ins1(n, out); 5 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test0.v: -------------------------------------------------------------------------------- 1 | module test0; 2 | endmodule 3 | 4 | module test1(); 5 | endmodule 6 | 7 | module test2(input i0, input i1, output o0, output o1, inout io); 8 | endmodule 9 | 10 | module test3(input i0, i1, output o0, o1, inout io); 11 | endmodule 12 | 13 | module test4(i0, i1, o0, o1, io); 14 | input i0; 15 | input i1; 16 | output o0; 17 | output o1; 18 | inout io; 19 | endmodule 20 | 21 | module test5(input [3:0] i0, i1, output [0:3] o0, o1, inout io); 22 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test1.v: -------------------------------------------------------------------------------- 1 | module test(); 2 | endmodule 3 | -------------------------------------------------------------------------------- /test/benchmarks/test10.v: -------------------------------------------------------------------------------- 1 | module test10(); 2 | 3 | MOD 4 | // test:# 5 | // /home/foo/bar/elem.v:10 6 | // param0(1'b0) 7 | // param1('d0) 8 | // param2(1'b0) 9 | #( 10 | .elem10('d0), 11 | .elem11(10'sd0), 12 | .elem12('sd0) 13 | ) 14 | ins ( 15 | .INPUT1(1'b1) 16 | ,.INPUT2(1'b0) 17 | ,.INPUT3(1'b0) 18 | ,.INPUT4(1'b0) 19 | ); 20 | 21 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test11.v: -------------------------------------------------------------------------------- 1 | module test11(); 2 | //test octal 3 | 4 | MOD 5 | #( 6 | .elem10('o0), 7 | .elem11(8'o84) 8 | ) 9 | ins(); 10 | 11 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test12.v: -------------------------------------------------------------------------------- 1 | // defparam test 2 | // 3 | 4 | module test12 (); 5 | wire f_we; 6 | wire f_we_i; 7 | 8 | CFG1 ins1 ( 9 | .A(f_we), 10 | .Y(f_we_i) 11 | ); 12 | defparam ins1.INIT=2'h1; 13 | 14 | RAM64x18 mem_regfile_mem_regfile_0_0 (); 15 | defparam mem_regfile_mem_regfile_0_0.RAMINDEX="mem_regfile[7:0]%32%8%SPEED%0%0%MICRO_RAM"; 16 | 17 | CFG1 \$$ins2@@ ( 18 | .A(f_we_i), 19 | .Y(f_we) 20 | ); 21 | defparam \$$ins2@@ .INIT=2'h2; 22 | 23 | 24 | endmodule /* test12 */ -------------------------------------------------------------------------------- /test/benchmarks/test13.v: -------------------------------------------------------------------------------- 1 | // defparam with escape ids 2 | // 3 | 4 | module ins_decode ( 5 | k, 6 | inst, 7 | inst_fast_7, 8 | inst_fast_8, 9 | inst_fast_0, 10 | inst_fast_1, 11 | aluop, 12 | alub_sel, 13 | alua_sel, 14 | pc_sel28_3, 15 | pc_sel29_2, 16 | N_23, 17 | N_92, 18 | aluz, 19 | N_168, 20 | N_24, 21 | bdpol, 22 | status_c_we, 23 | status_z_we, 24 | tris_we, 25 | w_we, 26 | pc_sel28_3_i, 27 | clock_c, 28 | resetn_c, 29 | skip_1z, 30 | f_we_i, 31 | f_we 32 | ) 33 | ; 34 | input [4:0] k ; 35 | input [11:5] inst ; 36 | input inst_fast_7 ; 37 | input inst_fast_8 ; 38 | input inst_fast_0 ; 39 | input inst_fast_1 ; 40 | output [3:0] aluop ; 41 | output [1:0] alub_sel ; 42 | output [1:0] alua_sel ; 43 | input pc_sel28_3 ; 44 | input pc_sel29_2 ; 45 | output N_23 ; 46 | output N_92 ; 47 | input aluz ; 48 | output N_168 ; 49 | output N_24 ; 50 | output bdpol ; 51 | output status_c_we ; 52 | output status_z_we ; 53 | output tris_we ; 54 | output w_we ; 55 | input pc_sel28_3_i ; 56 | input clock_c ; 57 | input resetn_c ; 58 | output skip_1z ; 59 | output f_we_i ; 60 | output f_we ; 61 | wire inst_fast_7 ; 62 | wire inst_fast_8 ; 63 | wire inst_fast_0 ; 64 | wire inst_fast_1 ; 65 | wire pc_sel28_3 ; 66 | wire pc_sel29_2 ; 67 | wire N_23 ; 68 | wire N_92 ; 69 | wire aluz ; 70 | wire N_168 ; 71 | wire N_24 ; 72 | wire bdpol ; 73 | wire status_c_we ; 74 | wire status_z_we ; 75 | wire tris_we ; 76 | wire w_we ; 77 | wire pc_sel28_3_i ; 78 | wire clock_c ; 79 | wire resetn_c ; 80 | wire skip_1z ; 81 | wire f_we_i ; 82 | wire f_we ; 83 | wire [12:3] decodes_in; 84 | wire [7:7] decodes_in_0_0_1_0_Z; 85 | wire [7:7] decodes_in_0_0_4_Z; 86 | wire [7:7] decodes_in_0_0_a3_0_3; 87 | wire [8:8] decodes_in_0_a2_i_0_Z; 88 | wire [5:2] decodes_in_i_0_0_Z; 89 | wire [5:5] decodes_in_i_0_a3_0; 90 | wire [3:3] decodes_in_0_a2_0_a3_3_Z; 91 | wire [2:2] decodes_in_i_0_1_Z; 92 | wire [7:7] decodes_in_0_0_2_Z; 93 | wire [11:11] decodes_in_0_0_0_Z; 94 | wire [2:2] decodes_in_i_0_2_Z; 95 | wire VCC ; 96 | wire skip_in ; 97 | wire GND ; 98 | wire N_22_i ; 99 | wire N_8_i ; 100 | wire N_11_i ; 101 | wire N_23_i ; 102 | wire N_21_i ; 103 | wire N_19_i ; 104 | wire N_16_i ; 105 | wire N_20_i ; 106 | wire decodes_in94 ; 107 | wire N_61 ; 108 | wire N_67 ; 109 | wire N_261 ; 110 | wire N_38 ; 111 | wire N_35_i ; 112 | wire N_25 ; 113 | wire N_34 ; 114 | wire N_49 ; 115 | wire N_73 ; 116 | wire N_65 ; 117 | wire N_262 ; 118 | wire N_75 ; 119 | wire N_84 ; 120 | wire N_26 ; 121 | wire N_40_i ; 122 | wire N_60 ; 123 | wire N_27 ; 124 | wire N_33 ; 125 | wire skip_in_0_0_Z ; 126 | wire N_31 ; 127 | wire N_74 ; 128 | CFG1 \decodes_RNIL3NV2[4] ( 129 | .A(f_we), 130 | .Y(f_we_i) 131 | ); 132 | defparam \decodes_RNIL3NV2[4] .INIT=2'h1; 133 | // @7:58 134 | SLE skip ( 135 | .Q(skip_1z), 136 | .ADn(VCC), 137 | .ALn(resetn_c), 138 | .CLK(clock_c), 139 | .D(skip_in), 140 | .EN(VCC), 141 | .LAT(GND), 142 | .SD(GND), 143 | .SLn(VCC) 144 | ); 145 | // @7:58 146 | SLE \decodes[13] ( 147 | .Q(alua_sel[1]), 148 | .ADn(VCC), 149 | .ALn(resetn_c), 150 | .CLK(clock_c), 151 | .D(pc_sel28_3_i), 152 | .EN(VCC), 153 | .LAT(GND), 154 | .SD(GND), 155 | .SLn(VCC) 156 | ); 157 | // @7:58 158 | SLE \decodes[12] ( 159 | .Q(alua_sel[0]), 160 | .ADn(VCC), 161 | .ALn(resetn_c), 162 | .CLK(clock_c), 163 | .D(decodes_in[12]), 164 | .EN(VCC), 165 | .LAT(GND), 166 | .SD(GND), 167 | .SLn(VCC) 168 | ); 169 | // @7:58 170 | SLE \decodes[11] ( 171 | .Q(alub_sel[1]), 172 | .ADn(VCC), 173 | .ALn(resetn_c), 174 | .CLK(clock_c), 175 | .D(decodes_in[11]), 176 | .EN(VCC), 177 | .LAT(GND), 178 | .SD(GND), 179 | .SLn(VCC) 180 | ); 181 | // @7:58 182 | SLE \decodes[10] ( 183 | .Q(alub_sel[0]), 184 | .ADn(VCC), 185 | .ALn(resetn_c), 186 | .CLK(clock_c), 187 | .D(N_22_i), 188 | .EN(VCC), 189 | .LAT(GND), 190 | .SD(GND), 191 | .SLn(VCC) 192 | ); 193 | // @7:58 194 | SLE \decodes[9] ( 195 | .Q(aluop[3]), 196 | .ADn(VCC), 197 | .ALn(resetn_c), 198 | .CLK(clock_c), 199 | .D(N_8_i), 200 | .EN(VCC), 201 | .LAT(GND), 202 | .SD(GND), 203 | .SLn(VCC) 204 | ); 205 | // @7:58 206 | SLE \decodes[8] ( 207 | .Q(aluop[2]), 208 | .ADn(VCC), 209 | .ALn(resetn_c), 210 | .CLK(clock_c), 211 | .D(N_11_i), 212 | .EN(VCC), 213 | .LAT(GND), 214 | .SD(GND), 215 | .SLn(VCC) 216 | ); 217 | // @7:58 218 | SLE \decodes[7] ( 219 | .Q(aluop[1]), 220 | .ADn(VCC), 221 | .ALn(resetn_c), 222 | .CLK(clock_c), 223 | .D(decodes_in[7]), 224 | .EN(VCC), 225 | .LAT(GND), 226 | .SD(GND), 227 | .SLn(VCC) 228 | ); 229 | // @7:58 230 | SLE \decodes[6] ( 231 | .Q(aluop[0]), 232 | .ADn(VCC), 233 | .ALn(resetn_c), 234 | .CLK(clock_c), 235 | .D(N_23_i), 236 | .EN(VCC), 237 | .LAT(GND), 238 | .SD(GND), 239 | .SLn(VCC) 240 | ); 241 | // @7:58 242 | SLE \decodes[5] ( 243 | .Q(w_we), 244 | .ADn(VCC), 245 | .ALn(resetn_c), 246 | .CLK(clock_c), 247 | .D(N_21_i), 248 | .EN(VCC), 249 | .LAT(GND), 250 | .SD(GND), 251 | .SLn(VCC) 252 | ); 253 | // @7:58 254 | SLE \decodes[4] ( 255 | .Q(f_we), 256 | .ADn(VCC), 257 | .ALn(resetn_c), 258 | .CLK(clock_c), 259 | .D(N_19_i), 260 | .EN(VCC), 261 | .LAT(GND), 262 | .SD(GND), 263 | .SLn(VCC) 264 | ); 265 | // @7:58 266 | SLE \decodes[3] ( 267 | .Q(tris_we), 268 | .ADn(VCC), 269 | .ALn(resetn_c), 270 | .CLK(clock_c), 271 | .D(decodes_in[3]), 272 | .EN(VCC), 273 | .LAT(GND), 274 | .SD(GND), 275 | .SLn(VCC) 276 | ); 277 | // @7:58 278 | SLE \decodes[2] ( 279 | .Q(status_z_we), 280 | .ADn(VCC), 281 | .ALn(resetn_c), 282 | .CLK(clock_c), 283 | .D(N_16_i), 284 | .EN(VCC), 285 | .LAT(GND), 286 | .SD(GND), 287 | .SLn(VCC) 288 | ); 289 | // @7:58 290 | SLE \decodes[1] ( 291 | .Q(status_c_we), 292 | .ADn(VCC), 293 | .ALn(resetn_c), 294 | .CLK(clock_c), 295 | .D(N_20_i), 296 | .EN(VCC), 297 | .LAT(GND), 298 | .SD(GND), 299 | .SLn(VCC) 300 | ); 301 | // @7:58 302 | SLE \decodes[0] ( 303 | .Q(bdpol), 304 | .ADn(VCC), 305 | .ALn(resetn_c), 306 | .CLK(clock_c), 307 | .D(decodes_in94), 308 | .EN(VCC), 309 | .LAT(GND), 310 | .SD(GND), 311 | .SLn(VCC) 312 | ); 313 | // @7:114 314 | CFG4 \decodes_in_0_0[7] ( 315 | .A(N_61), 316 | .B(N_67), 317 | .C(decodes_in_0_0_1_0_Z[7]), 318 | .D(decodes_in_0_0_4_Z[7]), 319 | .Y(decodes_in[7]) 320 | ); 321 | defparam \decodes_in_0_0[7] .INIT=16'hFFFE; 322 | // @7:114 323 | CFG4 \decodes_in_0_0_1_0[7] ( 324 | .A(N_261), 325 | .B(decodes_in_0_0_a3_0_3[7]), 326 | .C(inst[8]), 327 | .D(N_24), 328 | .Y(decodes_in_0_0_1_0_Z[7]) 329 | ); 330 | defparam \decodes_in_0_0_1_0[7] .INIT=16'h5054; 331 | // @7:114 332 | CFG2 \decodes_in_0_0_a3_3_1[7] ( 333 | .A(inst[6]), 334 | .B(inst[7]), 335 | .Y(N_168) 336 | ); 337 | defparam \decodes_in_0_0_a3_3_1[7] .INIT=4'h4; 338 | // @7:114 339 | CFG2 \decodes_in_0_a2_i_o3[8] ( 340 | .A(inst[9]), 341 | .B(inst[10]), 342 | .Y(N_38) 343 | ); 344 | defparam \decodes_in_0_a2_i_o3[8] .INIT=4'hD; 345 | // @7:78 346 | CFG2 skip_in_0_x2 ( 347 | .A(inst[8]), 348 | .B(aluz), 349 | .Y(N_35_i) 350 | ); 351 | defparam skip_in_0_x2.INIT=4'h6; 352 | // @7:78 353 | CFG2 skip_in_0_a2 ( 354 | .A(inst_fast_7), 355 | .B(inst_fast_8), 356 | .Y(N_92) 357 | ); 358 | defparam skip_in_0_a2.INIT=4'h4; 359 | // @7:114 360 | CFG2 \decodes_in_0_a2_0_o2[3] ( 361 | .A(k[1]), 362 | .B(k[0]), 363 | .Y(N_23) 364 | ); 365 | defparam \decodes_in_0_a2_0_o2[3] .INIT=4'hE; 366 | // @7:114 367 | CFG2 \decodes_in_i_0_o2[5] ( 368 | .A(inst[8]), 369 | .B(inst[9]), 370 | .Y(N_25) 371 | ); 372 | defparam \decodes_in_i_0_o2[5] .INIT=4'hE; 373 | // @7:114 374 | CFG2 \decodes_in_0_0_o2[11] ( 375 | .A(inst[9]), 376 | .B(inst[6]), 377 | .Y(N_261) 378 | ); 379 | defparam \decodes_in_0_0_o2[11] .INIT=4'hE; 380 | // @7:114 381 | CFG2 \decodes_in_i_0_o2_0[4] ( 382 | .A(inst[10]), 383 | .B(inst[5]), 384 | .Y(N_34) 385 | ); 386 | defparam \decodes_in_i_0_o2_0[4] .INIT=4'hE; 387 | // @7:114 388 | CFG2 \decodes_in_0_a2_i_o3[9] ( 389 | .A(inst[8]), 390 | .B(inst[7]), 391 | .Y(N_49) 392 | ); 393 | defparam \decodes_in_0_a2_i_o3[9] .INIT=4'hB; 394 | // @7:114 395 | CFG2 \decodes_in_0_a2_0_o2_0[3] ( 396 | .A(inst_fast_0), 397 | .B(inst_fast_1), 398 | .Y(N_24) 399 | ); 400 | defparam \decodes_in_0_a2_0_o2_0[3] .INIT=4'hE; 401 | // @7:114 402 | CFG3 \decodes_in_0_a2_i_0[8] ( 403 | .A(inst[8]), 404 | .B(inst[11]), 405 | .C(inst[6]), 406 | .Y(decodes_in_0_a2_i_0_Z[8]) 407 | ); 408 | defparam \decodes_in_0_a2_i_0[8] .INIT=8'hCD; 409 | // @7:114 410 | CFG4 \decodes_in_i_0_a3[6] ( 411 | .A(inst[7]), 412 | .B(inst[6]), 413 | .C(inst[9]), 414 | .D(inst[8]), 415 | .Y(N_73) 416 | ); 417 | defparam \decodes_in_i_0_a3[6] .INIT=16'h0900; 418 | // @7:114 419 | CFG4 \decodes_in_0_0_a3_3[7] ( 420 | .A(inst[7]), 421 | .B(inst[10]), 422 | .C(inst[8]), 423 | .D(inst[6]), 424 | .Y(N_65) 425 | ); 426 | defparam \decodes_in_0_0_a3_3[7] .INIT=16'h0020; 427 | // @7:114 428 | CFG4 \decodes_in_0_0_a2[11] ( 429 | .A(inst[7]), 430 | .B(inst[10]), 431 | .C(inst[9]), 432 | .D(inst[6]), 433 | .Y(N_262) 434 | ); 435 | defparam \decodes_in_0_0_a2[11] .INIT=16'h2000; 436 | // @7:114 437 | CFG4 decodes_in94_0_a3 ( 438 | .A(inst[11]), 439 | .B(inst[10]), 440 | .C(inst[9]), 441 | .D(inst[8]), 442 | .Y(decodes_in94) 443 | ); 444 | defparam decodes_in94_0_a3.INIT=16'h0004; 445 | // @7:114 446 | CFG3 \decodes_in_i_0_a3_1[6] ( 447 | .A(inst[9]), 448 | .B(inst[10]), 449 | .C(inst[6]), 450 | .Y(N_75) 451 | ); 452 | defparam \decodes_in_i_0_a3_1[6] .INIT=8'h20; 453 | // @7:114 454 | CFG3 \decodes_in_0_a2_0_a2[3] ( 455 | .A(inst[8]), 456 | .B(inst[7]), 457 | .C(inst[9]), 458 | .Y(N_84) 459 | ); 460 | defparam \decodes_in_0_a2_0_a2[3] .INIT=8'h01; 461 | // @7:78 462 | CFG3 skip_in_0_o2 ( 463 | .A(k[4]), 464 | .B(k[3]), 465 | .C(k[2]), 466 | .Y(N_26) 467 | ); 468 | defparam skip_in_0_o2.INIT=8'hFE; 469 | // @7:114 470 | CFG3 \decodes_in_0_i_x2_0[1] ( 471 | .A(inst[8]), 472 | .B(inst[6]), 473 | .C(inst[9]), 474 | .Y(N_40_i) 475 | ); 476 | defparam \decodes_in_0_i_x2_0[1] .INIT=8'h56; 477 | // @7:114 478 | CFG4 \decodes_in_i_0_0[2] ( 479 | .A(inst[11]), 480 | .B(inst[10]), 481 | .C(inst[9]), 482 | .D(inst[8]), 483 | .Y(decodes_in_i_0_0_Z[2]) 484 | ); 485 | defparam \decodes_in_i_0_0[2] .INIT=16'h5444; 486 | // @7:114 487 | CFG4 \decodes_in_i_0_0[5] ( 488 | .A(inst[11]), 489 | .B(inst[10]), 490 | .C(N_34), 491 | .D(N_25), 492 | .Y(decodes_in_i_0_0_Z[5]) 493 | ); 494 | defparam \decodes_in_i_0_0[5] .INIT=16'h7250; 495 | // @7:114 496 | CFG4 \decodes_in_i_0_a3_0_0[5] ( 497 | .A(inst[9]), 498 | .B(inst[8]), 499 | .C(inst[11]), 500 | .D(inst[7]), 501 | .Y(decodes_in_i_0_a3_0[5]) 502 | ); 503 | defparam \decodes_in_i_0_a3_0_0[5] .INIT=16'h0001; 504 | // @7:114 505 | CFG4 \decodes_in_0_a2_0_a3_3[3] ( 506 | .A(k[2]), 507 | .B(N_23), 508 | .C(inst[11]), 509 | .D(inst[6]), 510 | .Y(decodes_in_0_a2_0_a3_3_Z[3]) 511 | ); 512 | defparam \decodes_in_0_a2_0_a3_3[3] .INIT=16'h0008; 513 | // @7:114 514 | CFG4 \decodes_in_0_0_a3_0_4[7] ( 515 | .A(k[2]), 516 | .B(N_23), 517 | .C(inst[10]), 518 | .D(inst[7]), 519 | .Y(decodes_in_0_0_a3_0_3[7]) 520 | ); 521 | defparam \decodes_in_0_0_a3_0_4[7] .INIT=16'h0008; 522 | // @7:78 523 | CFG4 skip_in_0_a3_1 ( 524 | .A(f_we), 525 | .B(k[0]), 526 | .C(k[1]), 527 | .D(N_26), 528 | .Y(N_60) 529 | ); 530 | defparam skip_in_0_a3_1.INIT=16'h0020; 531 | // @7:114 532 | CFG4 \decodes_in_0_0[12] ( 533 | .A(inst[11]), 534 | .B(inst[10]), 535 | .C(inst[9]), 536 | .D(N_49), 537 | .Y(decodes_in[12]) 538 | ); 539 | defparam \decodes_in_0_0[12] .INIT=16'h5455; 540 | // @7:114 541 | CFG4 \decodes_in_0_0_a3[7] ( 542 | .A(inst[8]), 543 | .B(N_38), 544 | .C(inst[7]), 545 | .D(inst[6]), 546 | .Y(N_61) 547 | ); 548 | defparam \decodes_in_0_0_a3[7] .INIT=16'h0201; 549 | // @7:114 550 | CFG4 \decodes_in_i_0_o2_1[5] ( 551 | .A(k[2]), 552 | .B(N_24), 553 | .C(k[0]), 554 | .D(k[1]), 555 | .Y(N_27) 556 | ); 557 | defparam \decodes_in_i_0_o2_1[5] .INIT=16'hFFFE; 558 | // @7:114 559 | CFG4 \decodes_in_0_0_o3[7] ( 560 | .A(inst[11]), 561 | .B(inst[10]), 562 | .C(inst[9]), 563 | .D(inst[8]), 564 | .Y(N_33) 565 | ); 566 | defparam \decodes_in_0_0_o3[7] .INIT=16'h2E2A; 567 | // @7:114 568 | CFG4 \decodes_in_i_0_1[2] ( 569 | .A(decodes_in_i_0_0_Z[2]), 570 | .B(pc_sel29_2), 571 | .C(inst[11]), 572 | .D(inst[9]), 573 | .Y(decodes_in_i_0_1_Z[2]) 574 | ); 575 | defparam \decodes_in_i_0_1[2] .INIT=16'hAEAA; 576 | // @7:114 577 | CFG4 \decodes_in_0_0_2[7] ( 578 | .A(inst[11]), 579 | .B(inst[8]), 580 | .C(N_65), 581 | .D(N_33), 582 | .Y(decodes_in_0_0_2_Z[7]) 583 | ); 584 | defparam \decodes_in_0_0_2[7] .INIT=16'hFFF8; 585 | // @7:78 586 | CFG4 skip_in_0_0 ( 587 | .A(inst[11]), 588 | .B(inst[10]), 589 | .C(inst[9]), 590 | .D(N_35_i), 591 | .Y(skip_in_0_0_Z) 592 | ); 593 | defparam skip_in_0_0.INIT=16'h6222; 594 | // @7:114 595 | CFG4 \decodes_in_0_0_0[11] ( 596 | .A(inst[10]), 597 | .B(N_261), 598 | .C(N_262), 599 | .D(N_49), 600 | .Y(decodes_in_0_0_0_Z[11]) 601 | ); 602 | defparam \decodes_in_0_0_0[11] .INIT=16'hF0F4; 603 | // @7:58 604 | CFG4 \decodes_RNO[9] ( 605 | .A(pc_sel28_3), 606 | .B(N_49), 607 | .C(inst[6]), 608 | .D(inst[9]), 609 | .Y(N_8_i) 610 | ); 611 | defparam \decodes_RNO[9] .INIT=16'h2022; 612 | // @7:58 613 | CFG3 \decodes_RNO[8] ( 614 | .A(N_38), 615 | .B(pc_sel29_2), 616 | .C(decodes_in_0_a2_i_0_Z[8]), 617 | .Y(N_11_i) 618 | ); 619 | defparam \decodes_RNO[8] .INIT=8'h01; 620 | // @7:58 621 | CFG4 \decodes_RNO[4] ( 622 | .A(inst[10]), 623 | .B(inst[9]), 624 | .C(inst[11]), 625 | .D(inst[5]), 626 | .Y(N_19_i) 627 | ); 628 | defparam \decodes_RNO[4] .INIT=16'h0702; 629 | // @7:58 630 | CFG4 \decodes_RNO[1] ( 631 | .A(pc_sel28_3), 632 | .B(N_40_i), 633 | .C(inst[7]), 634 | .D(inst[9]), 635 | .Y(N_20_i) 636 | ); 637 | defparam \decodes_RNO[1] .INIT=16'h0220; 638 | // @7:114 639 | CFG4 \decodes_in_i_0_2[2] ( 640 | .A(inst[10]), 641 | .B(inst[11]), 642 | .C(decodes_in_i_0_1_Z[2]), 643 | .D(N_25), 644 | .Y(decodes_in_i_0_2_Z[2]) 645 | ); 646 | defparam \decodes_in_i_0_2[2] .INIT=16'hF4FC; 647 | // @7:114 648 | CFG4 \decodes_in_0_0_4[7] ( 649 | .A(inst[5]), 650 | .B(inst[10]), 651 | .C(N_84), 652 | .D(decodes_in_0_0_2_Z[7]), 653 | .Y(decodes_in_0_0_4_Z[7]) 654 | ); 655 | defparam \decodes_in_0_0_4[7] .INIT=16'hFF20; 656 | // @7:78 657 | CFG4 skip_in_0 ( 658 | .A(skip_in_0_0_Z), 659 | .B(N_60), 660 | .C(aluz), 661 | .D(N_262), 662 | .Y(skip_in) 663 | ); 664 | defparam skip_in_0.INIT=16'hFEEE; 665 | // @7:114 666 | CFG4 \decodes_in_0_0_a3_5[7] ( 667 | .A(inst[10]), 668 | .B(inst[6]), 669 | .C(N_84), 670 | .D(N_27), 671 | .Y(N_67) 672 | ); 673 | defparam \decodes_in_0_0_a3_5[7] .INIT=16'h0040; 674 | // @7:114 675 | CFG4 \decodes_in_0_0[11] ( 676 | .A(inst[10]), 677 | .B(inst[11]), 678 | .C(decodes_in_0_0_0_Z[11]), 679 | .D(N_25), 680 | .Y(decodes_in[11]) 681 | ); 682 | defparam \decodes_in_0_0[11] .INIT=16'hF4FC; 683 | // @7:114 684 | CFG4 \decodes_in_0_a2_0_a3[3] ( 685 | .A(N_24), 686 | .B(N_34), 687 | .C(N_84), 688 | .D(decodes_in_0_a2_0_a3_3_Z[3]), 689 | .Y(decodes_in[3]) 690 | ); 691 | defparam \decodes_in_0_a2_0_a3[3] .INIT=16'h1000; 692 | // @7:114 693 | CFG4 \decodes_in_i_0_o2[2] ( 694 | .A(inst[6]), 695 | .B(inst[5]), 696 | .C(N_23), 697 | .D(N_26), 698 | .Y(N_31) 699 | ); 700 | defparam \decodes_in_i_0_o2[2] .INIT=16'h7775; 701 | // @7:58 702 | CFG4 \decodes_RNO[10] ( 703 | .A(pc_sel29_2), 704 | .B(N_25), 705 | .C(inst[11]), 706 | .D(inst[10]), 707 | .Y(N_22_i) 708 | ); 709 | defparam \decodes_RNO[10] .INIT=16'h0F0E; 710 | // @7:114 711 | CFG4 \decodes_in_i_0_a3_0[6] ( 712 | .A(inst[10]), 713 | .B(inst[7]), 714 | .C(inst[8]), 715 | .D(N_31), 716 | .Y(N_74) 717 | ); 718 | defparam \decodes_in_i_0_a3_0[6] .INIT=16'h0504; 719 | // @7:58 720 | CFG4 \decodes_RNO[5] ( 721 | .A(decodes_in_i_0_a3_0[5]), 722 | .B(inst[6]), 723 | .C(decodes_in_i_0_0_Z[5]), 724 | .D(N_27), 725 | .Y(N_21_i) 726 | ); 727 | defparam \decodes_RNO[5] .INIT=16'h050D; 728 | // @7:58 729 | CFG3 \decodes_RNO[2] ( 730 | .A(N_31), 731 | .B(decodes_in_i_0_2_Z[2]), 732 | .C(N_84), 733 | .Y(N_16_i) 734 | ); 735 | defparam \decodes_RNO[2] .INIT=8'h13; 736 | // @7:58 737 | CFG4 \decodes_RNO[6] ( 738 | .A(N_73), 739 | .B(N_75), 740 | .C(N_74), 741 | .D(N_33), 742 | .Y(N_23_i) 743 | ); 744 | defparam \decodes_RNO[6] .INIT=16'h0001; 745 | GND GND_Z ( 746 | .Y(GND) 747 | ); 748 | VCC VCC_Z ( 749 | .Y(VCC) 750 | ); 751 | endmodule /* ins_decode */ 752 | -------------------------------------------------------------------------------- /test/benchmarks/test14.v: -------------------------------------------------------------------------------- 1 | /* 2 | test attributes (pragmas) 3 | */ 4 | (* top = 1 *) 5 | (* src = "src/adder.v:1.1-8.10" *) 6 | module adder(a, b, s); 7 | (* src = "src/adder.v:2.14-2.15" *) 8 | input [7:0] a; 9 | (* src = "src/adder.v:2.14-2.15" *) 10 | input [7:0] a; 11 | wire [7:0] a; 12 | (* src = "src/adder.v:3.14-3.15" *) 13 | input [7:0] b; 14 | wire [7:0] b; 15 | (* src = "src/adder.v:4.10-4.11" *) 16 | output s; 17 | wire s; 18 | (* module_not_derived = 32'd1 *) 19 | (* src = "/opt/homebrew/bin/../share/yosys/xilinx/lut_map.v:43.26-44.30" *) 20 | LUT2 #( 21 | .INIT(4'h1) 22 | ) _07_ ( 23 | .I0(_04_[0]), 24 | .I1(_04_[1]), 25 | .O(_05_[4]) 26 | ); 27 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test15.v: -------------------------------------------------------------------------------- 1 | /* 2 | test more attributes (pragmas) 3 | */ 4 | (* test *) 5 | module test(); 6 | (* test, a *) 7 | wire [7:0] a; 8 | (* test, b *) 9 | wire [7:0] b; 10 | (* test, s *) 11 | wire s; 12 | (* test, adder_inst *) 13 | adder adder_inst ( 14 | .a(a), 15 | .b(b), 16 | .s(s) 17 | ); 18 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test2.v: -------------------------------------------------------------------------------- 1 | module test(input i); 2 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test3.v: -------------------------------------------------------------------------------- 1 | /* 2 | Various Verilog constructs to test different aspects 3 | 4 | */ 5 | 6 | module mod0(input i0, output o0); 7 | endmodule 8 | 9 | module mod1(input[3:0] i0, output[0:3] o0); 10 | endmodule 11 | 12 | module test(input i, output o, inout io); 13 | wire net0; 14 | wire net1, net2, net3; 15 | wire [31:0] net4; 16 | wire [-2:1] net5; 17 | supply0 constant0; 18 | supply1 constant1; 19 | 20 | mod0 inst0(.i0(net0), .o0(/*empty*/)); 21 | mod0 inst1(.i0(net4[21]), .o0(net4[5])); 22 | mod1 inst2(.i0(net4[3:6]), .o0(net5)); 23 | mod1 inst3(.i0({net0, net1, net2, net5[-2]}), .o0(net5)); 24 | mod1 inst4(net4[7:10], {net0, net1, net2, net3}); 25 | mod1 inst5(net4[7:10]); //only first port is connected 26 | 27 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test4.v: -------------------------------------------------------------------------------- 1 | module mod0(input i0, output o0); 2 | endmodule 3 | 4 | module test(i, o, io); 5 | wire _i0_; 6 | wire _i1_; 7 | input i; 8 | wire i; 9 | output [3:0] o; 10 | wire [3:0] o; 11 | inout io; 12 | wire io; 13 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test5.v: -------------------------------------------------------------------------------- 1 | module test(\asqrt[33] ); 2 | output \asqrt[33] ; 3 | wire \asqrt[33] ; 4 | 5 | wire _0746_; 6 | wire _0747_; 7 | 8 | (* option1 = 32'd1 *) 9 | (* src = "/path1/path2/test.v:7.24-7.93" *) 10 | LUT4 #( 11 | .INIT(8'h2b) 12 | ) _4370_ ( 13 | .I0(_0746_), 14 | .I1(_0747_), 15 | .I2(\asqrt[33] ), 16 | .I3(1'h0), 17 | .Q() 18 | ); 19 | 20 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test6.v: -------------------------------------------------------------------------------- 1 | /* 2 | Focus on assign test 3 | */ 4 | module test(\asqrt[33] ); 5 | wire n0, n1; 6 | wire [3:0] n2; 7 | wire [3:0] n3; 8 | 9 | assign n0 = n1; 10 | assign n1 = 1'b0; 11 | assign { n2[3:2], n2[1:0] } = { n0, n1, 2'h2 }; 12 | assign n3 = 4'shF; 13 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test7.v: -------------------------------------------------------------------------------- 1 | /* 2 | parameter assignments: string 3 | */ 4 | module test(); 5 | mod #( 6 | .PARAM0(""), 7 | .PARAM1("A"), 8 | .PARAM2("VALUE") 9 | ) ins(); 10 | endmodule -------------------------------------------------------------------------------- /test/benchmarks/test8.v: -------------------------------------------------------------------------------- 1 | //Testing escape identifiers 2 | 3 | module \mod% (); 4 | output[40:0] \asqrt ; 5 | wire \asqrt[33] ; 6 | 7 | //parameter \mypar^ = 32'd1; FIXME: need to support parameters 8 | 9 | \$$MOD #( 10 | .INIT(8'h2b) 11 | ) \ins@2 ( 12 | .I0(\busa+index ), 13 | .I1(\-clock ), 14 | .I2(\asqrt[33] ), 15 | .I3(\asqrt [33]), 16 | .Q(\{a,b} ) 17 | ); 18 | 19 | endmodule 20 | -------------------------------------------------------------------------------- /test/benchmarks/test9.v: -------------------------------------------------------------------------------- 1 | //multiple ports on the same line or multi-line 2 | 3 | module test(i1, \i2% , i3, o1, o2, io1, io2); 4 | input i1, \i2% , i3; 5 | output [3:0] o1, 6 | o2; 7 | inout io1, io2; 8 | 9 | wire macu_n_280, macu_n_281, macu_n_282, \macu_result[0]_203 , 10 | \macu_result[1]_204 , \macu_result[2]_205 , \macu_result[3]_206 11 | , \macu_result[4]_207 ; 12 | endmodule -------------------------------------------------------------------------------- /thirdparty/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2023 The Naja verilog authors 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | add_subdirectory(googletest) --------------------------------------------------------------------------------