diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4017fcaf5..e0cd7bc71 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -127,15 +127,10 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 - - name: checkout submodules - shell: bash - run: | - make checkout - - name: Build shell: bash run: | - make compile BUILD_TYPE=$BUILD_TYPE + make all BUILD_TYPE=$BUILD_TYPE # Check the cache size and see if it is over the limit - name: Check ccache size @@ -216,15 +211,10 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 - - name: checkout submodules - shell: bash - run: | - make checkout - - name: Build shell: bash run: | - make compile BUILD_TYPE=$BUILD_TYPE CMAKE_FLAGS="${{ matrix.config.cmake_flags }}" + make all BUILD_TYPE=$BUILD_TYPE CMAKE_FLAGS="${{ matrix.config.cmake_flags }}" ubuntu_support: needs: change_detect @@ -262,15 +252,10 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 - - name: checkout submodules - shell: bash - run: | - make checkout - - name: Build shell: bash run: | - make compile BUILD_TYPE=$BUILD_TYPE + make all BUILD_TYPE=$BUILD_TYPE debug_build: needs: change_detect @@ -315,15 +300,10 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 - - name: checkout submodules - shell: bash - run: | - make checkout - - name: Build shell: bash run: | - make compile BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} + make all BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} - name: Quick Test shell: bash @@ -371,15 +351,10 @@ jobs: - uses: hendrikmuhs/ccache-action@v1 - - name: checkout submodules - shell: bash - run: | - make checkout - - name: Build shell: bash run: | - make compile BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} CMAKE_FLAGS="-DOPENFPGA_ENABLE_STRICT_COMPILE=ON" + make all BUILD_TYPE=${{ matrix.config.build_type }} -j ${{ matrix.config.cores }} CMAKE_FLAGS="-DOPENFPGA_ENABLE_STRICT_COMPILE=ON" - name: Quick Test shell: bash diff --git a/.github/workflows/cell_lib_test.yml b/.github/workflows/cell_lib_test.yml index 619dc5251..7d5b08984 100644 --- a/.github/workflows/cell_lib_test.yml +++ b/.github/workflows/cell_lib_test.yml @@ -13,7 +13,7 @@ jobs: # Test the RTL compilation compatibility verilog: name: RTL compilation and tests - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Cancel previous uses: styfle/cancel-workflow-action@0.9.1 @@ -25,7 +25,7 @@ jobs: - name: Install Dependencies run: | - sudo bash .github/workflows/install_dependencies_run.sh + sudo bash .github/workflows/install_dependencies_run_ubuntu22p04.sh - name: Dump tool versions run: | diff --git a/.github/workflows/install_dependencies_run.sh b/.github/workflows/install_dependencies_run.sh index ee8be9676..3d086d45f 100644 --- a/.github/workflows/install_dependencies_run.sh +++ b/.github/workflows/install_dependencies_run.sh @@ -1,3 +1,5 @@ +# Update as required by some packages +apt-get update apt-get install --no-install-recommends -y \ libdatetime-perl libc6 libffi-dev libgcc1 libreadline8 libstdc++6 \ libtcl8.6 tcl python3.8 python3-pip zlib1g libbz2-1.0 \ diff --git a/.github/workflows/install_dependencies_run_ubuntu22p04.sh b/.github/workflows/install_dependencies_run_ubuntu22p04.sh index a9973d0c8..491f8020f 100644 --- a/.github/workflows/install_dependencies_run_ubuntu22p04.sh +++ b/.github/workflows/install_dependencies_run_ubuntu22p04.sh @@ -1,3 +1,5 @@ +# Update as required by some packages +apt-get update apt-get install --no-install-recommends -y \ libdatetime-perl libc6 libffi-dev libgcc1 libreadline8 libstdc++6 \ libtcl8.6 tcl python3-pip zlib1g libbz2-1.0 \ diff --git a/.readthedocs.yml b/.readthedocs.yml index 5ff1814f4..2b28d0df4 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -7,7 +7,9 @@ version: 2 # Specify docker image for building the doc build: - image: latest + os: ubuntu-22.04 + tools: + python: "3.7" # Build documentation in the docs/ directory with Sphinx sphinx: @@ -19,7 +21,5 @@ formats: all # Optionally set the version of Python and requirements required to build your docs python: - version: 3.7 - system_packages: true install: - requirements: docs/requirements.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index b21400b2f..100351184 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,9 +109,9 @@ endif() include(CheckCXXCompilerFlag) # -# We require c++14 support +# We require c++17 support # -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) #No compiler specific extensions diff --git a/Dockerfile b/Dockerfile index 0c7500540..b1901b95a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM ghcr.io/lnis-uofu/openfpga-master:8d555772 # Install node js USER root -RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - +RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - RUN curl -fsSL https://code-server.dev/install.sh | sh RUN apt-get install -y nodejs RUN apt-get install tree @@ -49,7 +49,7 @@ RUN python3 -m pip install --upgrade pip RUN python3 -m pip install --user --no-cache-dir notebook RUN python3 -m pip install --user --no-cache-dir jupyterlab RUN python3 -m pip install --user --no-cache-dir jupyterhub -RUN python3 -m pip install --user --no-cache-dir "jupyter-server<2.0.0" +RUN python3 -m pip install --user --no-cache-dir jupyter-server RUN python3 -m pip install --user --no-cache-dir jupyter-server-proxy RUN python3 -m pip install --user --no-cache-dir jupyter-vscode-proxy diff --git a/Makefile b/Makefile index db960eb5b..e3d23b82a 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ CMAKE_BUILD_TYPE := $(shell echo ${BUILD_TYPE} | sed 's/_\?pgo//' | sed 's/_\?st # e.g. make CMAKE_FLAGS="-DCMAKE_CXX_COMPILER=g++-9' override CMAKE_FLAGS := -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -G 'Unix Makefiles' ${CMAKE_FLAGS} -# -s : Suppresss makefile output (e.g. entering/leaving directories) +# -s : Suppress makefile output (e.g. entering/leaving directories) # --output-sync target : For parallel compilation ensure output for each target is synchronized (make version >= 4.0) MAKEFLAGS := -s @@ -66,7 +66,7 @@ prebuild: echo "cd ${BUILD_DIR} && ${CMAKE_COMMAND} ${CMAKE_FLAGS} ${SOURCE_DIR}" && \ cd ${BUILD_DIR} && ${CMAKE_COMMAND} ${CMAKE_FLAGS} ${SOURCE_DIR} -compile: prebuild +compile: | prebuild # Compile the code base. By default, all the targets will be compiled # Following options are available # .. option:: CMAKE_GOALS @@ -75,12 +75,13 @@ compile: prebuild echo "Building target(s): ${CMAKE_GOALS}" @+${MAKE} -C ${BUILD_DIR} ${CMAKE_GOALS} -list_cmake_targets: prebuild +list_cmake_targets: | prebuild # Show the targets available to be built, which can be specified through ``CMAKE_GOALS`` when compile cd ${BUILD_DIR} && make help && cd - -all: checkout compile +all: checkout # A shortcut command to run checkout and compile in serial + @+${MAKE} compile format-cpp: # Format all the C/C++ files under this project, excluding submodules diff --git a/VERSION.md b/VERSION.md index 24b435dac..7f274dc5f 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.2.971 +1.2.1505 diff --git a/docs/requirements.txt b/docs/requirements.txt index cd8e75de7..359b7099b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -6,10 +6,10 @@ #recommonmark #Handle references in bibtex format -sphinxcontrib-bibtex<2.0.0 +sphinxcontrib-bibtex # Package required to embed youtube video -sphinxcontrib-yt +sphinxcontrib-youtube # Package required to convert SVG for latex building sphinxcontrib-svg2pdfconverter diff --git a/docs/source/conf.py b/docs/source/conf.py index 821dcb4b2..e33146101 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,7 +26,7 @@ import sphinx_rtd_theme # For bibtex support import sphinxcontrib.bibtex # For embedded youtube -import sphinxcontrib.yt +import sphinxcontrib.youtube # For converting SVG to PNG using rsvg import sphinxcontrib.rsvgconverter @@ -57,7 +57,7 @@ extensions = [ 'sphinx.ext.graphviz', 'sphinxcontrib.bibtex', 'sphinx.ext.autosectionlabel', - 'sphinxcontrib.yt', + 'sphinxcontrib.youtube', 'sphinxcontrib.rsvgconverter', ] diff --git a/docs/source/dev_manual/cicd_setup.rst b/docs/source/dev_manual/cicd_setup.rst index 773e07efb..92609ccd3 100644 --- a/docs/source/dev_manual/cicd_setup.rst +++ b/docs/source/dev_manual/cicd_setup.rst @@ -44,7 +44,7 @@ in which case the docker image compiled for the latest master branch is used for ]; RunRegression [ - label = "Run functional regeression test" + label = "Run functional regression test" shape = box ]; @@ -69,7 +69,7 @@ in which case the docker image compiled for the latest master branch is used for .. option:: Build regression test - The OpenFPGA soure is compiled with the following set of compilers. + The OpenFPGA source is compiled with the following set of compilers. #. gcc-7 #. gcc-8 @@ -81,9 +81,9 @@ in which case the docker image compiled for the latest master branch is used for #. clang-8 #. clang-10 - The docker images for these build enviroment are available on `github packages `_. + The docker images for these build environment are available on `github packages `_. -.. option:: Functional regeression test +.. option:: Functional regression test OpenFPGA maintains a set of functional tests to validate the different functionality. The test are broadly catagories into ``basic_reg_test``, ``fpga_verilog_reg_test``, @@ -93,7 +93,7 @@ in which case the docker image compiled for the latest master branch is used for How to debug failed regression test ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In case the ``funtional regression test`` fails, +In case the ``functional regression test`` fails, the actions script will collect all ``.log`` files from the task directory and upload as a artifacts on github storage. These artifacts can be downloaded from the github website actions tab, for more reference follow `this `_ article. @@ -113,11 +113,11 @@ Release Docker Images CI after cloning repository ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If you clone the repository the CI setup will still function, except the based images are still pullled from "lnis-uofu" repsitory and the master branch +If you clone the repository the CI setup will still function, except the based images are still pulled from "lnis-uofu" repository and the master branch of cloned repo will not push final docker image to any repository . -**In case you want to host your own copies of OpenFPGA base images** and final release create a githib secret variable with name ``DOCKER_REPO`` and set it to ``true``. This will make ci script to download base images from your own repo pakcages, and upload final realse to the same. +**In case you want to host your own copies of OpenFPGA base images** and final release create a github secret variable with name ``DOCKER_REPO`` and set it to ``true``. This will make ci script to download base images from your own repo packages, and upload final release to the same. -**If you don not want to use docker images based regression test** and like to compile all the bianries for each CI run. You can set ``IGNORE_DOCKER_TEST`` secrete variable to ``true``. +**If you don not want to use docker images based regression test** and like to compile all the binaries for each CI run. You can set ``IGNORE_DOCKER_TEST`` secrete variable to ``true``. -.. note:: Once you add ``DOCKER_REPO`` variable, you need to genrerate base images. To do this trigger mannual workflow ``Build docker CI images`` +.. note:: Once you add ``DOCKER_REPO`` variable, you need to generate base images. To do this trigger manual workflow ``Build docker CI images`` diff --git a/docs/source/dev_manual/version_number.rst b/docs/source/dev_manual/version_number.rst index feabce41f..9e75fa9e8 100644 --- a/docs/source/dev_manual/version_number.rst +++ b/docs/source/dev_manual/version_number.rst @@ -42,6 +42,6 @@ Version updates are made in the following scenario - significant improvements on Quality-of-Results (QoR). - significant changes on user interface. - - a techical feature is developed and validated by the community, which can impact the complete design flow. + - a technical feature is developed and validated by the community, which can impact the complete design flow. diff --git a/docs/source/manual/arch_lang/addon_vpr_syntax.rst b/docs/source/manual/arch_lang/addon_vpr_syntax.rst index c1d0f593f..ef93be938 100644 --- a/docs/source/manual/arch_lang/addon_vpr_syntax.rst +++ b/docs/source/manual/arch_lang/addon_vpr_syntax.rst @@ -59,12 +59,12 @@ Layout .. option:: through_channel="" Allow routing channels to pass through multi-width and multi-height programable blocks. This is mainly used in heterogeneous FPGAs to increase routability, as illustrated in :numref:`fig_thru_channel`. - By default, it is ``off``. + By default, it is ``false``. .. _fig_thru_channel: .. figure:: ./figures/thru_channel.png - :scale: 80% + :width: 100% :alt: Impact of through channel Impact on routing architecture when through channel in multi-width and multi-height programmable blocks: (a) disabled; (b) enabled. @@ -73,12 +73,26 @@ Layout .. warning:: You cannot use ``spread`` pin location for the ``height > 1`` or ``width >1`` tiles when using the tileable routing resource graph!!! Otherwise, it will cause undriven pins in your device!!! +.. option:: shrink_boundary="" + + Remove all the routing wires in empty regions. This is mainly used in non-rectangle FPGAs to avoid redundant routing wires in blank area, as illustrated in :numref:`fig_shrink_boundary`. + By default, it is ``false``. -A quick example to show tileable routing is enabled and through channels are disabled: + .. _fig_shrink_boundary: + + .. figure:: ./figures/shrink_boundary.png + :width: 100% + :alt: Impact of shrink boundary + + Impact on routing architecture when shrink-boundary: (a) disabled; (b) enabled. + + .. warning:: Do NOT enable ``shrink_boundary`` if you are not using the tileable routing resource graph generator! + +A quick example to show tileable routing is enabled, other options, e.g., through channels are disabled: .. code-block:: xml - + Switch Block diff --git a/docs/source/manual/arch_lang/figures/shrink_boundary.png b/docs/source/manual/arch_lang/figures/shrink_boundary.png new file mode 100644 index 000000000..acbb4518f Binary files /dev/null and b/docs/source/manual/arch_lang/figures/shrink_boundary.png differ diff --git a/docs/source/manual/file_formats/fabric_bitstream.rst b/docs/source/manual/file_formats/fabric_bitstream.rst index 6cd8085de..eb094d53b 100644 --- a/docs/source/manual/file_formats/fabric_bitstream.rst +++ b/docs/source/manual/file_formats/fabric_bitstream.rst @@ -11,7 +11,7 @@ Plain text (.bit) This file format is designed to be directly loaded to an FPGA fabric. It does not include any comments but only bitstream. -The information depends on the type of configuration procotol. +The information depends on the type of configuration protocol. .. option:: vanilla @@ -232,7 +232,7 @@ A quick example: -Other information may depend on the type of configuration procotol. +Other information may depend on the type of configuration protocol. .. option:: memory_bank diff --git a/docs/source/manual/file_formats/fabric_key.rst b/docs/source/manual/file_formats/fabric_key.rst index b3088aa6b..e35c8d844 100644 --- a/docs/source/manual/file_formats/fabric_key.rst +++ b/docs/source/manual/file_formats/fabric_key.rst @@ -5,6 +5,19 @@ Fabric Key (.xml) A fabric key follows an XML format. As shown in the following XML code, the key file includes the organization of configurable blocks in the top-level FPGA fabric. +Configurable Module +^^^^^^^^^^^^^^^^^^^ + +Fabric key can be applied to various modules. Each module can be a top-level FPGA fabric, or a submodule of the FPGA fabric. + +.. option:: + + Under each module, a set of keys can be defined. Note that for the top-level FPGA fabric, not only keys but also regions and shift-register banks can be defined. For non-top-level module, only keys are allowed. + + - ``name`` indicates the unique name of a valid module in FPGA fabric. Note that ``fpga_top`` is the considered as the module name of the top-level FPGA fabric. + + .. note:: ``fpga_core`` is not applicable to fabric key. + Configurable Region ^^^^^^^^^^^^^^^^^^^ @@ -23,60 +36,62 @@ The following example shows how to define multiple configuration regions in the .. code-block:: xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -111,41 +126,43 @@ This key contains only ``alias`` which is easy to craft. .. code-block:: xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The following shows another example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA. @@ -154,41 +171,43 @@ This key contains only ``name`` and ``value`` which is fast to parse. .. code-block:: xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The following shows another example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA using memory bank. @@ -197,41 +216,43 @@ This key contains only ``name``, ``value``, ``row`` and ``column``. .. code-block:: xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BL Shift Register Banks diff --git a/docs/source/manual/file_formats/figures/fpga_core_wrapper.png b/docs/source/manual/file_formats/figures/fpga_core_wrapper.png new file mode 100644 index 000000000..7dbe35527 Binary files /dev/null and b/docs/source/manual/file_formats/figures/fpga_core_wrapper.png differ diff --git a/docs/source/manual/file_formats/figures/tile_style_top_left.png b/docs/source/manual/file_formats/figures/tile_style_top_left.png new file mode 100644 index 000000000..1e0f66575 Binary files /dev/null and b/docs/source/manual/file_formats/figures/tile_style_top_left.png differ diff --git a/docs/source/manual/file_formats/index.rst b/docs/source/manual/file_formats/index.rst index 45c91d0ce..6a30c2b8b 100644 --- a/docs/source/manual/file_formats/index.rst +++ b/docs/source/manual/file_formats/index.rst @@ -1,7 +1,7 @@ File Formats ------------ -OpenFPGA widely uses XML format for interchangable files +OpenFPGA widely uses XML format for interchangeable files .. _file_formats: @@ -35,3 +35,7 @@ OpenFPGA widely uses XML format for interchangable files pin_table_file clock_network + + io_naming_file + + tile_config_file diff --git a/docs/source/manual/file_formats/io_naming_file.rst b/docs/source/manual/file_formats/io_naming_file.rst new file mode 100644 index 000000000..6cf9a7bc5 --- /dev/null +++ b/docs/source/manual/file_formats/io_naming_file.rst @@ -0,0 +1,98 @@ +.. _file_formats_io_naming_file: + +Fabric I/O Naming (.xml) +------------------------ + +The XML-based description language is used to describe + +- I/O names for an FPGA fabric when creating a top-level wrapper +- I/O connections between the fabric and top-level wrappers + +Using the description language, users can customize the I/O names for each pin/port of an FPGA fabric, including dummy pins (not from an FPGA fabric but required for system integration). + +Under the root node ````, naming rules can be defined line-by-line through syntax ````. + +.. code-block:: xml + + + + + +.. note:: If you do not need to rename a port of an FPGA fabric, there is no need to define it explicitly in the naming rules. OpenFPGA can infer it. + +Please be aware of the following restrictions: + +.. note:: Please note that when naming rules should be applied to a port at its full size. For example, given a port of ``in[0:31]``, naming rules should cover all the 32 bits. + +.. note:: Please note that we currently only supports port splitting at the top-level wrapper. For example, there is a port ``a[0:9]`` from the FPGA fabric, it can be split to ``a0[0:4]`` and ``a1[0:4]`` at the top-level wrapper. + +.. warning:: Port grouping is **NOT** supported yet. For example, there are ports ``b[0:7]`` and ``c[0:7]`` from the FPGA fabric, it can **NOT** be grouped to a port ``bnc[0:15]`` at the top-level wrapper. + +Syntax +`````` + +Detailed syntax are presented as follows. + +.. option:: top_name="" + + Define the port name and width which will appear in the top-level wrapper. For example, + + .. code-block:: xml + + top_name="a[0:2]" + +.. option:: core_name="" + + Define the port name and width which exists in the current FPGA fabric. For example, + + .. note:: You can find the available ports in the current top-level module of FPGA netlists. See details in :ref:`fabric_netlists`. + + .. code-block:: xml + + core_name="gfpga_pad_GPIO_PAD[0:2]" + +.. option:: is_dummy="" + + Define if the port is a dummy one in the top-level wrapper, which does not connect to any pin/port of the current FPGA fabric. For example, + + .. note:: When a dummy port is defined. ``core_name`` is not required. + + .. code-block:: xml + + is_dummy="true" + +.. option:: direction="" + + Direction can be ``input`` | ``output`` | ``inout``. Only applicable to dummy ports. For example, + + .. code-block:: xml + + direction="input" + +Example +``````` + +:numref:`fig_fpga_core_wrapper` shows an example of a top-level wrapper with naming rules, which is built on top of an existing FPGA core fabric. +There is a dummy input port at the top-level wrapper. + +.. _fig_fpga_core_wrapper: + +.. figure:: figures/fpga_core_wrapper.png + :width: 100% + :alt: Illustration of a top-level wrapper on an existing FPGA core fabric + + Example of a top-level wrapper: how it interfaces between SoC and an existing FPGA core fabric + +The I/O naming in the :numref:`fig_fpga_core_wrapper` can be described in the following XML: + +.. code-block:: xml + + + + + + + + + +Note that since port ``reset[0:0]`` require no name changes, it is not required to be defined in the XML. diff --git a/docs/source/manual/file_formats/tile_config_file.rst b/docs/source/manual/file_formats/tile_config_file.rst new file mode 100644 index 000000000..c3dfcbbce --- /dev/null +++ b/docs/source/manual/file_formats/tile_config_file.rst @@ -0,0 +1,39 @@ +.. _file_formats_tile_config_file: + +Tile Organization (.xml) +------------------------ + +The XML-based description language is used to describe how each tile is composed. +For example, what programmable blocks, connection blocks and switch blocks should be included. + +Using the description language, users can customize the tiles of an FPGA fabric, as detailed as each component in each tile. + +Under the root node ````, the detailes of tile organization can be described. + +.. code-block:: xml + + + + +Syntax +`````` + +Detailed syntax are presented as follows. + +.. option:: style="" + + Specify the style of tile organization. Can be [``top_left`` | ``top_right`` | ``bottom_left`` | ``bottom_right`` | ``custom``] + + .. warning:: Currently, only ``top_left`` is supported! + + The ``top_left`` is a shortcut to define the organization for all the tiles. :numref:`fig_tile_style_top_left` shows an example of tiles in the top-left sytle, where the programmable block locates in the top-left corner of all the tiles, surrounded by two connection blocks and one switch blocks. + +.. _fig_tile_style_top_left: + +.. figure:: ./figures/tile_style_top_left.png + :width: 100% + :alt: An example of top-left style of tile + + An example of top-left style of a tile in FPGA fabric + + diff --git a/docs/source/manual/fpga_spice/command_line_usage.rst b/docs/source/manual/fpga_spice/command_line_usage.rst index e7c261ab3..2592d2bb5 100644 --- a/docs/source/manual/fpga_spice/command_line_usage.rst +++ b/docs/source/manual/fpga_spice/command_line_usage.rst @@ -23,16 +23,16 @@ FPGA-SPICE Supported Options:: --fpga_spice_testbench_load_extraction_off --fpga_spice_sim_mt_num -.. note:: FPGA-SPICE requires the input of activity estimation results (\*.act file) from ACE2. - Remember to use the option --activity_file to read the activity file. +.. note:: FPGA-SPICE requires the input of activity estimation results (\*.act file) from ACE2. + Remember to use the option --activity_file to read the activity file. -.. note:: To dump full-chip-level testbenches, the option –-fpga_spice_print_top_testbench should be enabled. - -.. note:: To dump grid-level testbenches, the options -- fpga_spice_print_grid_testbench, -- fpga_spice_print_cb_testbench and -- fpga_spice_print_sb_testbench should be enabled. - -.. note:: To dump component-level testbenches, the options –fpga_spice_print_lut_testbench, --fpga_spice_print_hardlogic_testbench, --fpga_spice_print_pb_mux_testbench, --fpga_spice_print_cb_mux_testbench and --fpga_spice_print_sb_mux_testbench should be enabled. +.. note:: To dump full-chip-level testbenches, the option –-fpga_spice_print_top_testbench should be enabled. -.. csv-table:: Commmand-line Options of FPGA-SPICE +.. note:: To dump grid-level testbenches, the options -- fpga_spice_print_grid_testbench, -- fpga_spice_print_cb_testbench and -- fpga_spice_print_sb_testbench should be enabled. + +.. note:: To dump component-level testbenches, the options –fpga_spice_print_lut_testbench, --fpga_spice_print_hardlogic_testbench, --fpga_spice_print_pb_mux_testbench, --fpga_spice_print_cb_mux_testbench and --fpga_spice_print_sb_mux_testbench should be enabled. + +.. csv-table:: Command-line Options of FPGA-SPICE :header: "Command Options", "Description" :widths: 15, 20 diff --git a/docs/source/manual/fpga_verilog/fabric_netlist.rst b/docs/source/manual/fpga_verilog/fabric_netlist.rst index f09575a84..17b64115e 100644 --- a/docs/source/manual/fpga_verilog/fabric_netlist.rst +++ b/docs/source/manual/fpga_verilog/fabric_netlist.rst @@ -5,9 +5,9 @@ Fabric Netlists In this part, we will introduce the hierarchy, dependency and functionality of each Verilog netlist, which are generated to model the FPGA fabric. -.. note:: These netlists are automatically generated by the OpenFPGA command ``write_fabric_verilog``. See :ref:`openfpga_verilog_commands` for its detailed usage. +.. note:: These netlists are automatically generated by the OpenFPGA command :ref:`cmd_write_fabric_verilog`. See :ref:`openfpga_verilog_commands` for its detailed usage. -All the generated Verilog netlists are located in the directory as you specify in the OpenFPGA command ``write_fabric_verilog``. +All the generated Verilog netlists are located in the directory as you specify in the OpenFPGA command :ref:`cmd_write_fabric_verilog`. Inside the directory, the Verilog netlists are organized as illustrated in :numref:`fig_fabric_netlist_hierarchy`. .. _fig_fabric_netlist_hierarchy: @@ -24,6 +24,8 @@ Inside the directory, the Verilog netlists are organized as illustrated in :numr An illustrative FPGA fabric modelled by the Verilog netlists +.. _fabric_netlists_top_level_netlists: + Top-level Netlists ~~~~~~~~~~~~~~~~~~ @@ -48,6 +50,21 @@ Top-level Netlists .. note:: We strongly recommend users to turn on this flag as it can help simulators to converge quickly. +.. _fabric_netlists_tiles: + +Tiles +~~~~~ + +This sub-directory contains all the tile-level modules. Only seen when the ``--group_tile`` option is enabled when calling command :ref:`cmd_build_fabric`. +Each tile groups a number of programmable blocks (:ref:`fabric_netlists_logic_blocks`) and routing blocks (:ref:`fabric_netlists_routing_blocks`), as depicted in :numref:`fig_generic_fabric`. +Tiles are instanciated under the top-level module (:ref:`fabric_netlists_top_level_netlists`). + +.. option:: tile____.v + + For each unique tile, a Verilog netlist will be generated. The ```` and ```` denote the coordinate of the tile in the FPGA fabric. + +.. _fabric_netlists_logic_blocks: + Logic Blocks ~~~~~~~~~~~~ This sub-directory contains all the Verilog modules modeling configurable logic blocks, heterogeneous blocks as well as I/O blocks. @@ -63,6 +80,8 @@ Take the example in :numref:`fig_generic_fabric`, the modules are CLBs, DSP bloc For each root ``pb_type`` defined in the ```` of VPR architecture description, a Verilog netlist will be generated to model its internal structure. +.. _fabric_netlists_routing_blocks: + Routing Blocks ~~~~~~~~~~~~~~ This sub-directory contains all the Verilog modules modeling Switch Blocks (SBs) and Connection Blocks (CBs). diff --git a/docs/source/manual/fpga_verilog/figures/fabric_netlist_hierarchy.png b/docs/source/manual/fpga_verilog/figures/fabric_netlist_hierarchy.png index 232eb940c..27811bfb7 100644 Binary files a/docs/source/manual/fpga_verilog/figures/fabric_netlist_hierarchy.png and b/docs/source/manual/fpga_verilog/figures/fabric_netlist_hierarchy.png differ diff --git a/docs/source/manual/fpga_verilog/figures/mock_fpga_wrapper.png b/docs/source/manual/fpga_verilog/figures/mock_fpga_wrapper.png new file mode 100644 index 000000000..68e8745a1 Binary files /dev/null and b/docs/source/manual/fpga_verilog/figures/mock_fpga_wrapper.png differ diff --git a/docs/source/manual/fpga_verilog/index.rst b/docs/source/manual/fpga_verilog/index.rst index f851e6ed9..d356ff42f 100644 --- a/docs/source/manual/fpga_verilog/index.rst +++ b/docs/source/manual/fpga_verilog/index.rst @@ -10,3 +10,5 @@ FPGA-Verilog fabric_netlist testbench + + mock_fpga_wrapper diff --git a/docs/source/manual/fpga_verilog/mock_fpga_wrapper.rst b/docs/source/manual/fpga_verilog/mock_fpga_wrapper.rst new file mode 100644 index 000000000..a2c9cbd2b --- /dev/null +++ b/docs/source/manual/fpga_verilog/mock_fpga_wrapper.rst @@ -0,0 +1,25 @@ +.. _fpga_verilog_mock_fpga_wrapper: + +Mock FPGA Wrapper +----------------- + +OpenFPGA can generates HDL netlists that model a complete eFPGA fabric (see details in :ref:`fabric_netlists`). +Through bitstream forcing, users can verify the eFPGAs that are mapped by various applications in the context of SoC (see details in :numref:`fig_preconfig_module`). +However, the complete eFPGA fabric is very costly in design verification runtime. +To reduce runtime, a mock eFPGA wrapper is required to bridge the application HDL and other components in the SoC. +As illustrated in :numref:`fig_mock_fpga_wrapper`, a 3-bit counter application is mapped to an FPGA, while a mock wrapper is interfacing the signals between the counter module and the SoC. +The mock wrapper consists of the same ports as the FPGA fabric, which is generated by the OpenFPGA command ``write_fabric_verilog``. See :ref:`openfpga_verilog_commands` for its detailed usage. +The only difference lies in that the mock wrapper contains an instance of the application HDL design which is implemented on the FPGA, while the FPGA fabric contains a complete structure of programmable resources. + +.. note:: The mock wrapper is useful for connectivity checks on FPGA datapaths. It does not cover any configuration protocols (see details in :ref:`config_protocol`) + + +.. _fig_mock_fpga_wrapper: + +.. figure:: figures/mock_fpga_wrapper.png + :width: 100% + :alt: Illustraion of a mock FPGA wrapper + + Principles of a mock FPGA wrapper: ease SoC-level design verification + + diff --git a/docs/source/manual/fpga_verilog/testbench.rst b/docs/source/manual/fpga_verilog/testbench.rst index 6b434e0fb..70e9b5f07 100644 --- a/docs/source/manual/fpga_verilog/testbench.rst +++ b/docs/source/manual/fpga_verilog/testbench.rst @@ -22,7 +22,7 @@ To enable self-testing, the FPGA and user's RTL design (simulate using an HDL si .. _fig_verilog_testbench_organization: .. figure:: figures/full_testbench_block_diagram.svg - :scale: 50% + :width: 100% :alt: Verilog testbench principles Principles of Verilog testbenches: (1) using common input stimuli; (2) applying bitstream; (3) checking output vectors. @@ -30,14 +30,14 @@ To enable self-testing, the FPGA and user's RTL design (simulate using an HDL si .. _fig_verilog_full_testbench_waveform: .. figure:: figures/full_testbench_waveform.svg - :scale: 50% + :width: 100% :alt: Full testbench waveform Illustration on the waveforms in full testbench Full Testbench ~~~~~~~~~~~~~~ -Full testbench aims at simulating an entire FPGA operating period, consisting of two phases: +Full testbench aims at simulating an entire FPGA operating period, consisting of two phases: - the **Configuration Phase**, where the synthesized design bitstream is loaded to the programmable fabric, as highlighted by the green rectangle of :numref:`fig_verilog_full_testbench_waveform`; @@ -48,7 +48,7 @@ Formal-oriented Testbench The formal-oriented testbench aims to test a programmed FPGA is instantiated with the user's bitstream. The module of the programmed FPGA is encapsulated with the same port mapping as the user's RTL design and thus can be fed to a formal tool for a 100% coverage formal verification. Compared to the full testbench, this skips the time-consuming configuration phase, reducing the simulation time, potentially also significantly accelerating the functional verification, especially for large FPGAs. -.. warning:: Formal-oriented testbenches do not validate the configuration protocol of FPGAs. It is used to validate FPGA with a wide range of benchmarks. +.. warning:: Formal-oriented testbenches do not validate the configuration protocol of FPGAs. It is used to validate FPGA with a wide range of benchmarks. General Usage ~~~~~~~~~~~~~ @@ -59,11 +59,11 @@ Inside the directory, the Verilog testbenches are organized as illustrated in :n .. _fig_verilog_testbench_hierarchy: .. figure:: ./figures/verilog_testbench_hierarchy.svg - :scale: 100% + :width: 100% Hierarchy of Verilog testbenches for a FPGA fabric implemented with an application -.. note:: ```` is the module name of users' RTL design. +.. note:: ```` is the module name of users' RTL design. .. option:: _include_netlist.v @@ -84,14 +84,13 @@ Inside the directory, the Verilog testbenches are organized as illustrated in :n .. option:: _top_formal_verification.v This netlist includes a Verilog module of a pre-configured FPGA fabric, which is a wrapper on top of the ``fpga_top.v`` netlist. - The wrapper module has the same port map as the top-level module of user's RTL design, which be directly def to formal verification tools to validate FPGA's functional equivalence. + The wrapper module has the same port map as the top-level module of user's RTL design, which be directly def to formal verification tools to validate FPGA's functional equivalence. :numref:`fig_preconfig_module` illustrates the organization of a pre-configured module, which consists of a FPGA fabric (see :ref:`fabric_netlists`) and a hard-coded bitstream. - Only used I/Os of FPGA fabric will appear in the port list of the pre-configured module. + Only used I/Os of FPGA fabric will appear in the port list of the pre-configured module. .. _fig_preconfig_module: .. figure:: ./figures/preconfig_module.png - :scale: 25% + :width: 100% Internal structure of a pre-configured FPGA module - diff --git a/docs/source/manual/index.rst b/docs/source/manual/index.rst index a00dce30a..fd4f4df56 100644 --- a/docs/source/manual/index.rst +++ b/docs/source/manual/index.rst @@ -18,3 +18,5 @@ file_formats/index + utilities/index + diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_hierarchy.png b/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_hierarchy.png new file mode 100644 index 000000000..e4e3cdcfe Binary files /dev/null and b/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_hierarchy.png differ diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_overview.png b/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_overview.png new file mode 100644 index 000000000..44c17a3dc Binary files /dev/null and b/docs/source/manual/openfpga_shell/openfpga_commands/figures/group_config_block_overview.png differ diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst index 6a872a1d1..a21c4dbfe 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst @@ -3,6 +3,8 @@ FPGA-Verilog ------------ +.. _cmd_write_fabric_verilog: + write_fabric_verilog ~~~~~~~~~~~~~~~~~~~~ @@ -49,6 +51,10 @@ write_full_testbench The output directory for all the testbench netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench`` + .. option:: --dut_module + + Specify the name of *Design Under Test* (DUT) module to be considered in the testbench. Can be either ``fpga_top`` or ``fpga_core. By default, it is ``fpga_top``. + .. option:: --bitstream The bitstream file to be loaded to the full testbench, which should be in the same file format that OpenFPGA can outputs (See detailes in :ref:`file_formats_fabric_bitstream_plain_text`). For example, ``--bitstream and2.bit`` @@ -120,6 +126,10 @@ write_preconfigured_fabric_wrapper Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names. For example, ``--file /temp/fabric/fabric_netlists.v`` + .. option:: --dut_module + + Specify the name of *Design Under Test* (DUT) module to be considered in the testbench. Can be either ``fpga_top`` or ``fpga_core. By default, it is ``fpga_top``. + .. option:: --pin_constraints_file or -pcf Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml`` @@ -166,6 +176,49 @@ __ iverilog_website_ Show verbose log +write_mock_fpga_wrapper +~~~~~~~~~~~~~~~~~~~~~~~ + + Write the Verilog wrapper which mockes a mapped FPGA fabric. See details in :ref:`fpga_verilog_mock_fpga_wrapper`. + + .. option:: --file or -f + + The output directory for the netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench`` + + .. option:: --top_module + + Specify the name of top-level module to be considered in the wrapper. Can be either ``fpga_top`` or ``fpga_core. By default, it is ``fpga_top``. + + .. option:: --pin_constraints_file or -pcf + + Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml`` + Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`. + + .. option:: --bus_group_file or -bgf + + Specify the *Bus Group File* (BGF) if you want to group pins to buses. For example, ``-bgf bus_group.xml`` + Strongly recommend when input HDL contains bus ports. See detailed file format about :ref:`file_format_bus_group_file`. + + .. option:: --explicit_port_mapping + + Use explicit port mapping when writing the Verilog netlists + + .. option:: --use_relative_path + + Force to use relative path in netlists when including other netlists. By default, this is off, which means that netlists use absolute paths when including other netlists + + .. option:: --default_net_type + + Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``. + + .. option:: --no_time_stamp + + Do not print time stamp in Verilog netlists + + .. option:: --verbose + + Show verbose log + write_preconfigured_testbench ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst index 5971f75f2..62ec61e21 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/setup_commands.rst @@ -252,7 +252,34 @@ build_fabric .. option:: --compress_routing Enable compression on routing architecture modules. Strongly recommend this as it will minimize the number of routing modules to be outputted. It can reduce the netlist size significantly. + + .. option:: --group_tile + + Group fine-grained programmable blocks, connection blocks and switch blocks into tiles. Once enabled, tiles will be added to the top-level module. Otherwise, the top-level module consists of programmable blocks, connection blocks and switch blocks. The tile style can be customized through a file. See details in :ref:`file_formats_tile_config_file`. When enabled, the Verilog netlists will contain additional netlists that model tiles (see details in :ref:`fabric_netlists_tiles`). + + .. warning:: This option does not support ``--duplicate_grid_pin``! + + .. warning:: This option requires ``--compress_routing`` to be enabled! + + .. option:: --group_config_block + + Group configuration memory blocks under each CLB/SB/CB etc. into a centralized configuration memory blocks, as depicted in :numref:`fig_group_config_block_overview`. When disabled, the configuration memory blocks are placed in a distributed way under CLB/SB/CB etc. For example, each programming resource, e.g., LUT, has a dedicated configuration memory block, being placed in the same module. When enabled, as illustrated in :numref:`fig_group_config_block_hierarchy`, the physical memory block locates under a CLB, driving a number of logical memory blocks which are close to the programmable resources. The logical memory blocks contain only pass-through wires which can be optimized out during physical design phase. + + .. _fig_group_config_block_overview: + .. figure:: ./figures/group_config_block_overview.png + :width: 100% + + Impact on grouping configuable blocks: before and after + + .. _fig_group_config_block_hierarchy: + + .. figure:: ./figures/group_config_block_hierarchy.png + :width: 100% + + Netlist hierarchy on grouped configuable blocks + + .. option:: --duplicate_grid_pin Enable pin duplication on grid modules. This is optional unless ultra-dense layout generation is needed @@ -269,6 +296,8 @@ build_fabric Output current fabric key to an XML file. For example, ``--write_fabric_key fpga_2x2.xml`` See details in :ref:`file_formats_fabric_key`. + .. warning:: This option will be deprecated. Use :ref:`cmd_write_fabric_key` as a replacement. + .. option:: --frame_view Create only frame views of the module graph. When enabled, top-level module will not include any nets. This option is made for save runtime and memory. @@ -281,6 +310,53 @@ build_fabric .. note:: This is a must-run command before launching FPGA-Verilog, FPGA-Bitstream, FPGA-SDC and FPGA-SPICE +.. _cmd_write_fabric_key: + +write_fabric_key +~~~~~~~~~~~~~~~~ + + Output current fabric key to an XML file. For example, ``write_fabric_key --file fpga_2x2.xml`` See details in :ref:`file_formats_fabric_key`. + + .. note:: This command can output module-level keys while the ``--write_fabric_key`` option in command ``build_fabric`` does NOT support! Strongly recommend to use this command to obtain fabric key. + + .. option:: --file or -f + + Specify the file name. For example, ``--file fabric_key_echo.xml``. + + .. option:: --include_module_keys + + Output module-level keys to the file. + + .. option:: --verbose + + Show verbose log + +.. _cmd_add_fpga_core_to_fabric: + +add_fpga_core_to_fabric +~~~~~~~~~~~~~~~~~~~~~~~ + + Add a wrapper module ``fpga_core`` as an intermediate layer to FPGA fabric. After this command, the existing module ``fpga_top`` will remain the top-level module while there is a new module ``fpga_core`` under it. Under fpga_core, there will be the detailed building blocks. + + .. option:: --io_naming + + This is optional. Specify the I/O naming rules when connecting I/Os of ``fpga_core`` module to the top-level module ``fpga_top``. If not defined, the ``fpga_top`` will be the same as ``fpga_core`` w.r.t. ports. See details about the file format of I/O naming rules in :ref:`file_formats_io_naming_file`. + + .. option:: --instance_name + + This is optional. Specify the instance name to be used when instanciate the ``fpga_core`` module under the top-level module ``fpga_top``. If not defined, by default it is ``fpga_core_inst``. + + .. option:: --frame_view + + Create only frame views of the module graph. When enabled, top-level module will not include any nets. This option is made for save runtime and memory. + + .. warning:: Recommend to turn the option on when bitstream generation is the only purpose of the flow. Do not use it when you need generate netlists! + + .. option:: --verbose + + Show verbose log + + write_fabric_hierarchy ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/manual/utilities/fabric_key_assistant.rst b/docs/source/manual/utilities/fabric_key_assistant.rst new file mode 100644 index 000000000..4625366d2 --- /dev/null +++ b/docs/source/manual/utilities/fabric_key_assistant.rst @@ -0,0 +1,53 @@ +.. _utility_fabric_key_assistant: + +Fabric Key Assistant +-------------------- + +Fabric Key Assistant is a tool to help users to craft fabric key files (see details in :ref:`file_formats_fabric_key`). +Note that crafting a fabric key is not an easy task for engineers, as its complexity grows exponentially with FPGA sizes. +This tool is developed to assist engineers when finalizing fabric key files. +It can apply sanity checks on hand-crafted fabric key files, helping engineers to correct and debug. + +The tool can be found at ``/build/libs/libfabrickey/test/fabric_key_assistant`` + +The tool includes the following options: + +.. option:: --reference + + Specifiy a reference fabric key file, which has been already validated by OpenFPGA. For example, the reference fabric key can be a file which is written by OpenFPGA as a default key. The reference fabric key file is treated as the baseline, on which the input fabric key file will be compared to. + + .. note:: The reference fabric key should contain all the syntax, e.g., ``name``, ``value`` and ``alias``. + +.. option:: --input + + Specify the input fabric key file, which is typically hand-crafted by users. Sanity checks will be applied to the input fabric key file by comparing the reference. + + .. note:: The input fabric key should contain only the syntax ``alias``. + +.. option:: --output + + Specify the output fabric key file, which is an updated version of the input fabric key file. Difference from the input file, the output file contains ``name`` and ``value``, which is added by linking the ``alias`` from input file to reference file. For example, the reference fabric key includes a key: + +.. code-block:: xml + + + +while the input fabric key includes a key: + +.. code-block:: xml + + + +the resulting output fabric key file includes a key: + +.. code-block:: xml + + + +.. option:: --verbose + + To enable verbose output + +.. option:: --help + + Show help desk diff --git a/docs/source/manual/utilities/index.rst b/docs/source/manual/utilities/index.rst new file mode 100644 index 000000000..a51774314 --- /dev/null +++ b/docs/source/manual/utilities/index.rst @@ -0,0 +1,13 @@ +Utilities +--------- + +OpenFPGA contains a number of utility tools to help users to craft files. + + +.. _utilities: + Utility Tools + +.. toctree:: + :maxdepth: 2 + + fabric_key_assistant diff --git a/docs/source/tutorials/arch_modeling/quick_start.rst b/docs/source/tutorials/arch_modeling/quick_start.rst index 1b31300d1..6f2d87f27 100644 --- a/docs/source/tutorials/arch_modeling/quick_start.rst +++ b/docs/source/tutorials/arch_modeling/quick_start.rst @@ -30,7 +30,7 @@ A summary of the architectural features is as follows: - K4N4 Configurable Logic Block (CLB), which consists of four Basic Logic Elements (BLEs) and a fully-connected crossbar. Each BLE contains a 4-input Look-Up Table (LUT), a Flip-Flop (FF) and a 2:1 routing multiplexer - Length-1 routing wires interconnected by Wilton-Style Switch Block (SB) -The VPR architecture description is designed for EDA needs mainly, which lacks the details physical modelingrequired by OpenFPGA. +The VPR architecture description is designed for EDA needs mainly, which lacks the details physical modeling required by OpenFPGA. Here, we show a step-by-step adaption on the architecture template. Physical I/O Modeling diff --git a/docs/source/tutorials/getting_started/shell_shortcuts.rst b/docs/source/tutorials/getting_started/shell_shortcuts.rst index cb5d01bdc..2079b48aa 100644 --- a/docs/source/tutorials/getting_started/shell_shortcuts.rst +++ b/docs/source/tutorials/getting_started/shell_shortcuts.rst @@ -46,7 +46,7 @@ Once the ``openfpga.sh`` script is sourced, you can run any following commands d .. option:: clear-task-run - Clears all run diretories of the given task + Clears all run directories of the given task .. option:: run-modelsim diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index a871fa27e..ab8e6dbd8 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -8,3 +8,5 @@ add_subdirectory(libfabrickey) add_subdirectory(libfpgabitstream) add_subdirectory(libpcf) add_subdirectory(libbusgroup) +add_subdirectory(libionamemap) +add_subdirectory(libtileconfig) diff --git a/libs/libarchopenfpga/src/circuit_types.h b/libs/libarchopenfpga/src/circuit_types.h index 35000d80e..86143bb65 100644 --- a/libs/libarchopenfpga/src/circuit_types.h +++ b/libs/libarchopenfpga/src/circuit_types.h @@ -129,10 +129,13 @@ constexpr std::array /******************************************************************** * Types of configuration protocol - * 1. configurable memories are organized and accessed as standalone elements - * 2. configurable memories are organized and accessed by a scan-chain - * 3. configurable memories are organized and accessed by memory bank - * 4. configurable memories are organized and accessed by frames + * - configurable memories are organized and accessed as standalone elements + * - configurable memories are organized and accessed by a scan-chain + * - configurable memories are organized and accessed by quicklogic memory bank + * - configurable memories are organized and accessed by memory bank + * - configurable memories are organized and accessed by frames + * - configurable memories are organized and accessed by feedthrough. Currently, + * this is only for internal use only */ enum e_config_protocol_type { CONFIG_MEM_STANDALONE, @@ -140,11 +143,13 @@ enum e_config_protocol_type { CONFIG_MEM_MEMORY_BANK, CONFIG_MEM_QL_MEMORY_BANK, CONFIG_MEM_FRAME_BASED, + CONFIG_MEM_FEEDTHROUGH, NUM_CONFIG_PROTOCOL_TYPES }; constexpr std::array CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank", - "ql_memory_bank", "frame_based"}}; + "ql_memory_bank", "frame_based", + "feedthrough"}}; #endif diff --git a/libs/libfabrickey/CMakeLists.txt b/libs/libfabrickey/CMakeLists.txt index 2dffe8fd5..8c01cc472 100644 --- a/libs/libfabrickey/CMakeLists.txt +++ b/libs/libfabrickey/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.9) project("libfabrickey") file(GLOB_RECURSE EXEC_SOURCES test/*.cpp) -file(GLOB_RECURSE LIB_SOURCES src/*.cpp) -file(GLOB_RECURSE LIB_HEADERS src/*.h) +file(GLOB_RECURSE LIB_SOURCES src/*/*.cpp) +file(GLOB_RECURSE LIB_HEADERS src/*/*.h) files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS) #Remove test executable from library @@ -20,6 +20,7 @@ set_target_properties(libfabrickey PROPERTIES PREFIX "") #Avoid extra 'lib' pref #Specify link-time dependancies target_link_libraries(libfabrickey libopenfpgautil + libopenfpgashell libarchopenfpga libvtrutil libpugiutil) diff --git a/libs/libfabrickey/key_examples/key_example.xml b/libs/libfabrickey/key_examples/key_example.xml index b9b0aa814..00d44276f 100644 --- a/libs/libfabrickey/key_examples/key_example.xml +++ b/libs/libfabrickey/key_examples/key_example.xml @@ -1,9 +1,11 @@ - - - - - - - + + + + + + + + + diff --git a/libs/libfabrickey/src/fabric_key.cpp b/libs/libfabrickey/src/base/fabric_key.cpp similarity index 68% rename from libs/libfabrickey/src/fabric_key.cpp rename to libs/libfabrickey/src/base/fabric_key.cpp index f9c84103d..a6558a258 100644 --- a/libs/libfabrickey/src/fabric_key.cpp +++ b/libs/libfabrickey/src/base/fabric_key.cpp @@ -5,6 +5,8 @@ #include "vtr_assert.h" #include "vtr_log.h" +namespace openfpga { // Begin namespace openfpga + /************************************************************************ * Member functions for class FabricKey ***********************************************************************/ @@ -39,9 +41,49 @@ FabricKey::fabric_word_line_bank_range FabricKey::wl_banks( wl_bank_ids_[region_id].end()); } +FabricKey::fabric_key_module_range FabricKey::modules() const { + return vtr::make_range(sub_key_module_ids_.begin(), + sub_key_module_ids_.end()); +} + +std::vector FabricKey::sub_keys( + const FabricKeyModuleId& module_id) const { + VTR_ASSERT(valid_module_id(module_id)); + return module_sub_keys_[module_id]; +} + /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ +size_t FabricKey::num_regions() const { return region_ids_.size(); } + +size_t FabricKey::num_keys() const { return key_ids_.size(); } + +std::vector FabricKey::find_key_by_alias( + const std::string& alias) const { + /* Throw warning on empty alias which may cause unexpected results: whole key + * is dumped! */ + if (alias.empty()) { + VTR_LOG_WARN( + "Empty alias is given! This may cause unexpected results, i.e., a whole " + "data base is dumped!\n"); + } + size_t num_found_keys = 0; + for (FabricKeyId key_id : key_ids_) { + if (key_alias(key_id) == alias) { + num_found_keys++; + } + } + std::vector found_keys; + found_keys.reserve(num_found_keys); + for (FabricKeyId key_id : key_ids_) { + if (key_alias(key_id) == alias) { + found_keys.push_back(key_id); + } + } + return found_keys; +} + std::vector FabricKey::region_keys( const FabricRegionId& region_id) const { /* validate the region_id */ @@ -87,6 +129,29 @@ std::vector FabricKey::wl_bank_data_ports( return wl_bank_data_ports_[region_id][bank_id]; } +std::string FabricKey::module_name(const FabricKeyModuleId& module_id) const { + VTR_ASSERT(valid_module_id(module_id)); + return sub_key_module_names_[module_id]; +} + +std::string FabricKey::sub_key_name(const FabricSubKeyId& key_id) const { + /* validate the key_id */ + VTR_ASSERT(valid_sub_key_id(key_id)); + return sub_key_names_[key_id]; +} + +size_t FabricKey::sub_key_value(const FabricSubKeyId& key_id) const { + /* validate the key_id */ + VTR_ASSERT(valid_sub_key_id(key_id)); + return sub_key_values_[key_id]; +} + +std::string FabricKey::sub_key_alias(const FabricSubKeyId& key_id) const { + /* validate the key_id */ + VTR_ASSERT(valid_sub_key_id(key_id)); + return sub_key_alias_[key_id]; +} + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -263,6 +328,70 @@ void FabricKey::add_data_port_to_wl_shift_register_bank( wl_bank_data_ports_[region_id][bank_id].push_back(data_port); } +void FabricKey::reserve_modules(const size_t& num_modules) { + sub_key_module_ids_.reserve(num_modules); + sub_key_module_names_.reserve(num_modules); + module_sub_keys_.reserve(num_modules); +} + +void FabricKey::reserve_module_keys(const FabricKeyModuleId& module_id, + const size_t& num_keys) { + VTR_ASSERT(valid_module_id(module_id)); + module_sub_keys_[module_id].reserve(num_keys); + sub_key_ids_.reserve(sub_key_ids_.size() + num_keys); + sub_key_names_.reserve(sub_key_names_.size() + num_keys); + sub_key_values_.reserve(sub_key_values_.size() + num_keys); + sub_key_alias_.reserve(sub_key_alias_.size() + num_keys); +} + +FabricKeyModuleId FabricKey::create_module(const std::string& name) { + /* Ensure name is not duplicated */ + auto result = module2subkey_lookup_.find(name); + if (result != module2subkey_lookup_.end()) { + return FabricKeyModuleId::INVALID(); /* Return an invalid id */ + } + /* Create a new id */ + FabricKeyModuleId module_id = FabricKeyModuleId(sub_key_module_ids_.size()); + sub_key_module_ids_.push_back(module_id); + sub_key_module_names_.push_back(name); + module_sub_keys_.emplace_back(); + /* Register in lookup */ + module2subkey_lookup_[name] = module_id; + return module_id; +} + +FabricSubKeyId FabricKey::create_module_key( + const FabricKeyModuleId& module_id) { + VTR_ASSERT(valid_module_id(module_id)); + /* Create a new id */ + FabricSubKeyId key_id = FabricSubKeyId(sub_key_ids_.size()); + sub_key_ids_.push_back(key_id); + sub_key_names_.emplace_back(); + sub_key_values_.emplace_back(); + sub_key_alias_.emplace_back(); + /* Add the new id to module */ + module_sub_keys_[module_id].emplace_back(key_id); + return key_id; +} + +void FabricKey::set_sub_key_name(const FabricSubKeyId& key_id, + const std::string& name) { + VTR_ASSERT(valid_sub_key_id(key_id)); + sub_key_names_[key_id] = name; +} + +void FabricKey::set_sub_key_value(const FabricSubKeyId& key_id, + const size_t& value) { + VTR_ASSERT(valid_sub_key_id(key_id)); + sub_key_values_[key_id] = value; +} + +void FabricKey::set_sub_key_alias(const FabricSubKeyId& key_id, + const std::string& alias) { + VTR_ASSERT(valid_sub_key_id(key_id)); + sub_key_alias_[key_id] = alias; +} + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ @@ -297,3 +426,15 @@ bool FabricKey::valid_wl_bank_id(const FabricRegionId& region_id, return (size_t(bank_id) < wl_bank_ids_[region_id].size()) && (bank_id == wl_bank_ids_[region_id][bank_id]); } + +bool FabricKey::valid_module_id(const FabricKeyModuleId& module_id) const { + return (size_t(module_id) < sub_key_module_ids_.size()) && + (module_id == sub_key_module_ids_[module_id]); +} + +bool FabricKey::valid_sub_key_id(const FabricSubKeyId& sub_key_id) const { + return (size_t(sub_key_id) < sub_key_ids_.size()) && + (sub_key_id == sub_key_ids_[sub_key_id]); +} + +} // End of namespace openfpga diff --git a/libs/libfabrickey/src/fabric_key.h b/libs/libfabrickey/src/base/fabric_key.h similarity index 70% rename from libs/libfabrickey/src/fabric_key.h rename to libs/libfabrickey/src/base/fabric_key.h index 53c9f89ac..3982cb8b8 100644 --- a/libs/libfabrickey/src/fabric_key.h +++ b/libs/libfabrickey/src/base/fabric_key.h @@ -16,6 +16,8 @@ #include "fabric_key_fwd.h" #include "openfpga_port.h" +namespace openfpga { // Begin namespace openfpga + /******************************************************************** * A data structure to describe a secure key for fabric organization * A fabric may consist of multiple regions @@ -47,12 +49,18 @@ class FabricKey { typedef vtr::vector::const_iterator fabric_word_line_bank_iterator; + typedef vtr::vector::const_iterator + fabric_sub_key_iterator; + typedef vtr::vector::const_iterator + fabric_key_module_iterator; /* Create range */ typedef vtr::Range fabric_region_range; typedef vtr::Range fabric_key_range; typedef vtr::Range fabric_bit_line_bank_range; typedef vtr::Range fabric_word_line_bank_range; + typedef vtr::Range fabric_sub_key_range; + typedef vtr::Range fabric_key_module_range; public: /* Constructors */ FabricKey(); @@ -62,36 +70,48 @@ class FabricKey { fabric_region_range regions() const; fabric_bit_line_bank_range bl_banks(const FabricRegionId& region_id) const; fabric_word_line_bank_range wl_banks(const FabricRegionId& region_id) const; + fabric_key_module_range modules() const; + std::vector sub_keys( + const FabricKeyModuleId& module_id) const; public: /* Public Accessors: Basic data query */ + size_t num_regions() const; + size_t num_keys() const; /* Access all the keys of a region */ std::vector region_keys(const FabricRegionId& region_id) const; - /* Access the name of a key */ std::string key_name(const FabricKeyId& key_id) const; - /* Access the value of a key */ size_t key_value(const FabricKeyId& key_id) const; - /* Access the alias of a key */ std::string key_alias(const FabricKeyId& key_id) const; - /* Access the coordinate of a key */ vtr::Point key_coordinate(const FabricKeyId& key_id) const; + /** @brief Find valid key ids for a given alias. Note that you should NOT send + * an empty alias which may cause a complete list of key ids to be returned + * (extremely inefficent and NOT useful). Suggest to check if the existing + * fabric key contains valid alias for each key before calling this API!!! */ + std::vector find_key_by_alias(const std::string& alias) const; + /* Check if there are any keys */ bool empty() const; /* Return a list of data ports which will be driven by a BL shift register * bank */ - std::vector bl_bank_data_ports( + std::vector bl_bank_data_ports( const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const; /* Return a list of data ports which will be driven by a WL shift register * bank */ - std::vector wl_bank_data_ports( + std::vector wl_bank_data_ports( const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const; + std::string module_name(const FabricKeyModuleId& module_id) const; + std::string sub_key_name(const FabricSubKeyId& key_id) const; + size_t sub_key_value(const FabricSubKeyId& key_id) const; + std::string sub_key_alias(const FabricSubKeyId& key_id) const; + public: /* Public Mutators: model-related */ /* Reserve a number of regions to be memory efficent */ void reserve_regions(const size_t& num_regions); @@ -115,11 +135,8 @@ class FabricKey { /* Configure attributes of a key */ void set_key_name(const FabricKeyId& key_id, const std::string& name); - void set_key_value(const FabricKeyId& key_id, const size_t& value); - void set_key_alias(const FabricKeyId& key_id, const std::string& alias); - void set_key_coordinate(const FabricKeyId& key_id, const vtr::Point& coord); @@ -136,7 +153,7 @@ class FabricKey { /* Add a data port to a given BL shift register bank */ void add_data_port_to_bl_shift_register_bank( const FabricRegionId& region_id, const FabricBitLineBankId& bank_id, - const openfpga::BasicPort& data_port); + const BasicPort& data_port); /* Create a new shift register bank for WLs and return an id */ FabricWordLineBankId create_wl_shift_register_bank( @@ -145,7 +162,20 @@ class FabricKey { /* Add a data port to a given WL shift register bank */ void add_data_port_to_wl_shift_register_bank( const FabricRegionId& region_id, const FabricWordLineBankId& bank_id, - const openfpga::BasicPort& data_port); + const BasicPort& data_port); + + /* Reserve a number of keys to be memory efficent */ + void reserve_modules(const size_t& num_modules); + void reserve_module_keys(const FabricKeyModuleId& module_id, + const size_t& num_keys); + /* Create a new key and add it to the library, return an id */ + FabricKeyModuleId create_module(const std::string& name); + FabricSubKeyId create_module_key(const FabricKeyModuleId& module_id); + /* Configure attributes of a sub key */ + void set_sub_key_name(const FabricSubKeyId& key_id, const std::string& name); + void set_sub_key_value(const FabricSubKeyId& key_id, const size_t& value); + void set_sub_key_alias(const FabricSubKeyId& key_id, + const std::string& alias); public: /* Public invalidators/validators */ bool valid_region_id(const FabricRegionId& region_id) const; @@ -156,29 +186,26 @@ class FabricKey { const FabricBitLineBankId& bank_id) const; bool valid_wl_bank_id(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const; + bool valid_module_id(const FabricKeyModuleId& module_id) const; + bool valid_sub_key_id(const FabricSubKeyId& sub_key_id) const; private: /* Internal data */ + /* ---- Top-level keys and regions ---- */ /* Unique ids for each region */ vtr::vector region_ids_; - /* Key ids for each region */ vtr::vector> region_key_ids_; /* Unique ids for each key */ vtr::vector key_ids_; - /* Names for each key */ vtr::vector key_names_; - /* Values for each key */ vtr::vector key_values_; - /* Values for each key */ vtr::vector> key_coordinates_; - /* Region for each key */ vtr::vector key_regions_; - /* Optional alias for each key, with which a key can also be represented */ vtr::vector key_alias_; @@ -187,8 +214,8 @@ class FabricKey { vtr::vector> bl_bank_ids_; /* Data ports to be connected to each BL shift register bank */ - vtr::vector>> + vtr::vector>> bl_bank_data_ports_; /* Unique ids for each WL shift register bank */ @@ -196,9 +223,23 @@ class FabricKey { vtr::vector> wl_bank_ids_; /* Data ports to be connected to each WL shift register bank */ - vtr::vector>> + vtr::vector>> wl_bank_data_ports_; + + /* ---- List of sub modules ---- */ + vtr::vector sub_key_module_ids_; + vtr::vector sub_key_module_names_; + vtr::vector> module_sub_keys_; + std::map module2subkey_lookup_; + + /* ---- Sub keys ---- */ + vtr::vector sub_key_ids_; + vtr::vector sub_key_names_; + vtr::vector sub_key_values_; + vtr::vector sub_key_alias_; }; +} // End of namespace openfpga + #endif diff --git a/libs/libfabrickey/src/fabric_key_fwd.h b/libs/libfabrickey/src/base/fabric_key_fwd.h similarity index 79% rename from libs/libfabrickey/src/fabric_key_fwd.h rename to libs/libfabrickey/src/base/fabric_key_fwd.h index 0c282092f..937977c16 100644 --- a/libs/libfabrickey/src/fabric_key_fwd.h +++ b/libs/libfabrickey/src/base/fabric_key_fwd.h @@ -12,17 +12,25 @@ #include "vtr_strong_id.h" +namespace openfpga { // Begin namespace openfpga + struct fabric_region_id_tag; struct fabric_key_id_tag; struct fabric_bit_line_bank_id_tag; struct fabric_word_line_bank_id_tag; +struct fabric_sub_key_id_tag; +struct fabric_key_module_id_tag; typedef vtr::StrongId FabricRegionId; typedef vtr::StrongId FabricKeyId; typedef vtr::StrongId FabricBitLineBankId; typedef vtr::StrongId FabricWordLineBankId; +typedef vtr::StrongId FabricSubKeyId; +typedef vtr::StrongId FabricKeyModuleId; /* Short declaration of class */ class FabricKey; +} // End of namespace openfpga + #endif diff --git a/libs/libfabrickey/src/io/fabric_key_xml_constants.h b/libs/libfabrickey/src/io/fabric_key_xml_constants.h new file mode 100644 index 000000000..726c8f265 --- /dev/null +++ b/libs/libfabrickey/src/io/fabric_key_xml_constants.h @@ -0,0 +1,32 @@ +#ifndef FABRIC_KEY_XML_CONSTANTS_H +#define FABRIC_KEY_XML_CONSTANTS_H + +namespace openfpga { // Begin namespace openfpga + +/* Constants required by XML parser */ +constexpr const char* XML_FABRIC_KEY_ROOT_NAME = "fabric_key"; +constexpr const char* XML_FABRIC_KEY_MODULE_NODE_NAME = "module"; +constexpr const char* XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME = "name"; +constexpr const char* XML_FABRIC_KEY_REGION_NODE_NAME = "region"; +constexpr const char* XML_FABRIC_KEY_REGION_ATTRIBUTE_ID_NAME = "id"; +constexpr const char* XML_FABRIC_KEY_KEY_NODE_NAME = "key"; +constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME = "id"; +constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME = "alias"; +constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME = "name"; +constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME = "value"; +constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_COLUMN_NAME = "column"; +constexpr const char* XML_FABRIC_KEY_KEY_ATTRIBUTE_ROW_NAME = "row"; +constexpr const char* XML_FABRIC_KEY_BL_SHIFT_REGISTER_BANKS_NODE_NAME = + "bl_shift_register_banks"; +constexpr const char* XML_FABRIC_KEY_WL_SHIFT_REGISTER_BANKS_NODE_NAME = + "wl_shift_register_banks"; +constexpr const char* XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME = + "bank"; +constexpr const char* + XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME = "id"; +constexpr const char* + XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME = "range"; + +} // End of namespace openfpga + +#endif diff --git a/libs/libfabrickey/src/io/read_xml_fabric_key.cpp b/libs/libfabrickey/src/io/read_xml_fabric_key.cpp new file mode 100644 index 000000000..a89dffd3d --- /dev/null +++ b/libs/libfabrickey/src/io/read_xml_fabric_key.cpp @@ -0,0 +1,461 @@ +/******************************************************************** + * This file includes the top-level function of this library + * which reads an XML of a fabric key to the associated + * data structures + *******************************************************************/ +#include + +/* Headers from pugi XML library */ +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_time.h" + +/* Headers from openfpga util library */ +#include "openfpga_port_parser.h" +#include "openfpga_reserved_words.h" +#include "openfpga_tokenizer.h" + +/* Headers from libarchfpga */ +#include "arch_error.h" +#include "fabric_key_xml_constants.h" +#include "read_xml_fabric_key.h" +#include "read_xml_util.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * Parse XML codes of a to an object of FabricKey + *******************************************************************/ +static void read_xml_module_key(pugi::xml_node& xml_component_key, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, + const FabricKeyModuleId& module_id) { + /* Find the id of component key */ + size_t id = get_attribute(xml_component_key, + XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME, loc_data) + .as_int(); + + FabricSubKeyId sub_key_id = fabric_key.sub_keys(module_id)[id]; + + if (false == fabric_key.valid_sub_key_id(sub_key_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key), + "Invalid 'id' attribute '%d' (in total %lu keys)!\n", id, + fabric_key.sub_keys(module_id).size()); + } + + VTR_ASSERT_SAFE(true == fabric_key.valid_sub_key_id(sub_key_id)); + + /* If we have an alias, set the value as well */ + const std::string& alias = + get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME, + loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_string(); + if (!alias.empty()) { + fabric_key.set_sub_key_alias(sub_key_id, alias); + } + + /* If we have the alias set, name and valus are optional then + * Otherwise, they are mandatory attributes + */ + pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL; + if (true == alias.empty()) { + required_name_value = pugiutil::ReqOpt::REQUIRED; + } + + const std::string& name = + get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME, + loc_data, required_name_value) + .as_string(); + const size_t& value = + get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME, + loc_data, required_name_value) + .as_int(); + + fabric_key.set_sub_key_name(sub_key_id, name); + fabric_key.set_sub_key_value(sub_key_id, value); +} + +/******************************************************************** + * Parse XML codes of a to an object of FabricKey + *******************************************************************/ +static void read_xml_region_key(pugi::xml_node& xml_component_key, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, + const FabricRegionId& fabric_region) { + /* Find the id of component key */ + const size_t& id = + get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME, + loc_data) + .as_int(); + + if (false == fabric_key.valid_key_id(FabricKeyId(id))) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key), + "Invalid 'id' attribute '%d' (in total %lu keys)!\n", id, + fabric_key.keys().size()); + } + + VTR_ASSERT_SAFE(true == fabric_key.valid_key_id(FabricKeyId(id))); + + /* If we have an alias, set the value as well */ + const std::string& alias = + get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME, + loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_string(); + if (!alias.empty()) { + fabric_key.set_key_alias(FabricKeyId(id), alias); + } + + /* If we have the alias set, name and valus are optional then + * Otherwise, they are mandatory attributes + */ + pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL; + if (true == alias.empty()) { + required_name_value = pugiutil::ReqOpt::REQUIRED; + } + + const std::string& name = + get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME, + loc_data, required_name_value) + .as_string(); + const size_t& value = + get_attribute(xml_component_key, XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME, + loc_data, required_name_value) + .as_int(); + + fabric_key.set_key_name(FabricKeyId(id), name); + fabric_key.set_key_value(FabricKeyId(id), value); + fabric_key.add_key_to_region(fabric_region, FabricKeyId(id)); + + /* Parse coordinates */ + vtr::Point coord; + coord.set_x(get_attribute(xml_component_key, + XML_FABRIC_KEY_KEY_ATTRIBUTE_COLUMN_NAME, loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(-1)); + coord.set_y(get_attribute(xml_component_key, + XML_FABRIC_KEY_KEY_ATTRIBUTE_ROW_NAME, loc_data, + pugiutil::ReqOpt::OPTIONAL) + .as_int(-1)); + if (fabric_key.valid_key_coordinate(coord)) { + fabric_key.set_key_coordinate(FabricKeyId(id), coord); + } +} + +/******************************************************************** + * Parse XML codes of a under to an object of + *FabricKey + *******************************************************************/ +static void read_xml_region_bl_shift_register_bank( + pugi::xml_node& xml_bank, const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, const FabricRegionId& fabric_region) { + /* Find the id of the bank */ + FabricBitLineBankId bank_id = FabricBitLineBankId( + get_attribute(xml_bank, + XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME, + loc_data) + .as_int()); + + if (!fabric_key.valid_bl_bank_id(fabric_region, bank_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank), + "Invalid 'id' attribute '%lu' (in total %lu BL banks)!\n", + size_t(bank_id), fabric_key.bl_banks(fabric_region).size()); + } + + VTR_ASSERT_SAFE(true == fabric_key.valid_bl_bank_id(fabric_region, bank_id)); + + /* Parse the ports */ + std::string data_ports = + get_attribute(xml_bank, + XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME, + loc_data) + .as_string(); + /* Split with ',' if we have multiple ports */ + openfpga::StringToken tokenizer(data_ports); + for (const std::string& data_port : tokenizer.split(',')) { + openfpga::PortParser data_port_parser(data_port); + fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, bank_id, + data_port_parser.port()); + } +} + +/******************************************************************** + * Parse XML codes of a to an object of FabricKey + *******************************************************************/ +static void read_xml_region_bl_shift_register_banks( + pugi::xml_node& xml_bl_bank, const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, const FabricRegionId& fabric_region) { + size_t num_banks = count_children( + xml_bl_bank, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME, loc_data, + pugiutil::ReqOpt::OPTIONAL); + fabric_key.reserve_bl_shift_register_banks(fabric_region, num_banks); + + for (size_t ibank = 0; ibank < num_banks; ++ibank) { + fabric_key.create_bl_shift_register_bank(fabric_region); + } + + for (pugi::xml_node xml_bank : xml_bl_bank.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_bank.name() != + std::string(XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME)) { + bad_tag(xml_bank, loc_data, xml_bl_bank, + {XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME}); + } + read_xml_region_bl_shift_register_bank(xml_bank, loc_data, fabric_key, + fabric_region); + } +} + +/******************************************************************** + * Parse XML codes of a under to an object of + *FabricKey + *******************************************************************/ +static void read_xml_region_wl_shift_register_bank( + pugi::xml_node& xml_bank, const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, const FabricRegionId& fabric_region) { + /* Find the id of the bank */ + FabricWordLineBankId bank_id = FabricWordLineBankId( + get_attribute(xml_bank, + XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME, + loc_data) + .as_int()); + + if (!fabric_key.valid_wl_bank_id(fabric_region, bank_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank), + "Invalid 'id' attribute '%lu' (in total %lu WL banks)!\n", + size_t(bank_id), fabric_key.wl_banks(fabric_region).size()); + } + + VTR_ASSERT_SAFE(true == fabric_key.valid_wl_bank_id(fabric_region, bank_id)); + + /* Parse the ports */ + std::string data_ports = + get_attribute(xml_bank, + XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME, + loc_data) + .as_string(); + /* Split with ',' if we have multiple ports */ + openfpga::StringToken tokenizer(data_ports); + for (const std::string& data_port : tokenizer.split(',')) { + openfpga::PortParser data_port_parser(data_port); + fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, bank_id, + data_port_parser.port()); + } +} + +/******************************************************************** + * Parse XML codes of a to an object of FabricKey + *******************************************************************/ +static void read_xml_region_wl_shift_register_banks( + pugi::xml_node& xml_wl_bank, const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, const FabricRegionId& fabric_region) { + size_t num_banks = count_children( + xml_wl_bank, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME, loc_data, + pugiutil::ReqOpt::OPTIONAL); + fabric_key.reserve_wl_shift_register_banks(fabric_region, num_banks); + + for (size_t ibank = 0; ibank < num_banks; ++ibank) { + fabric_key.create_wl_shift_register_bank(fabric_region); + } + + for (pugi::xml_node xml_bank : xml_wl_bank.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_bank.name() != + std::string(XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME)) { + bad_tag(xml_bank, loc_data, xml_wl_bank, + {XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME}); + } + read_xml_region_wl_shift_register_bank(xml_bank, loc_data, fabric_key, + fabric_region); + } +} + +/******************************************************************** + * Parse XML codes of a to an object of FabricKey + *******************************************************************/ +static void read_xml_fabric_region(pugi::xml_node& xml_region, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key) { + /* Find the unique id for the region */ + const FabricRegionId& region_id = FabricRegionId( + get_attribute(xml_region, XML_FABRIC_KEY_REGION_ATTRIBUTE_ID_NAME, loc_data) + .as_int()); + if (false == fabric_key.valid_region_id(region_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region), + "Invalid region id '%lu' (in total %lu regions)!\n", + size_t(region_id), fabric_key.regions().size()); + } + VTR_ASSERT_SAFE(true == fabric_key.valid_region_id(region_id)); + + /* Reserve memory space for the keys in the region */ + size_t num_keys = count_children(xml_region, XML_FABRIC_KEY_KEY_NODE_NAME, + loc_data, pugiutil::ReqOpt::OPTIONAL); + fabric_key.reserve_region_keys(region_id, num_keys); + + /* Parse the key for this region */ + if (0 < num_keys) { + pugi::xml_node xml_key = + get_first_child(xml_region, XML_FABRIC_KEY_KEY_NODE_NAME, loc_data); + while (xml_key) { + read_xml_region_key(xml_key, loc_data, fabric_key, region_id); + xml_key = xml_key.next_sibling(xml_key.name()); + } + } + + /* Parse the BL shift register bank for this region */ + pugi::xml_node xml_bl_bank = get_single_child( + xml_region, XML_FABRIC_KEY_BL_SHIFT_REGISTER_BANKS_NODE_NAME, loc_data, + pugiutil::ReqOpt::OPTIONAL); + read_xml_region_bl_shift_register_banks(xml_bl_bank, loc_data, fabric_key, + region_id); + + /* Parse the WL shift register bank for this region */ + pugi::xml_node xml_wl_bank = get_single_child( + xml_region, XML_FABRIC_KEY_WL_SHIFT_REGISTER_BANKS_NODE_NAME, loc_data, + pugiutil::ReqOpt::OPTIONAL); + read_xml_region_wl_shift_register_banks(xml_wl_bank, loc_data, fabric_key, + region_id); +} + +/******************************************************************** + * Parse XML codes of a which is a top-level module + *******************************************************************/ +static void read_xml_fabric_key_top_module(pugi::xml_node& xml_module, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key) { + size_t num_regions = + std::distance(xml_module.children().begin(), xml_module.children().end()); + /* Reserve memory space for the region */ + fabric_key.reserve_regions(num_regions); + for (size_t iregion = 0; iregion < num_regions; ++iregion) { + fabric_key.create_region(); + } + + /* Reserve memory space for the keys */ + size_t num_keys = 0; + + for (pugi::xml_node xml_region : xml_module.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_region.name() != std::string(XML_FABRIC_KEY_REGION_NODE_NAME)) { + bad_tag(xml_region, loc_data, xml_module, + {XML_FABRIC_KEY_REGION_NODE_NAME}); + } + num_keys += + std::distance(xml_region.children().begin(), xml_region.children().end()); + } + + fabric_key.reserve_keys(num_keys); + for (size_t ikey = 0; ikey < num_keys; ++ikey) { + fabric_key.create_key(); + } + + /* Iterate over the children under this node, + * each child should be named after circuit_model + */ + for (pugi::xml_node xml_region : xml_module.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_region.name() != std::string(XML_FABRIC_KEY_REGION_NODE_NAME)) { + bad_tag(xml_region, loc_data, xml_module, + {XML_FABRIC_KEY_REGION_NODE_NAME}); + } + read_xml_fabric_region(xml_region, loc_data, fabric_key); + } +} + +/******************************************************************** + * Parse XML codes of a which is a regular module + *******************************************************************/ +static void read_xml_fabric_key_module(pugi::xml_node& xml_module, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key) { + std::string name = + get_attribute(xml_module, XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME, + loc_data) + .as_string(); + FabricKeyModuleId module_id = fabric_key.create_module(name); + + /* Parse all the sub keys */ + size_t num_keys = + std::distance(xml_module.children().begin(), xml_module.children().end()); + + /* Reserve for better memory efficiency */ + fabric_key.reserve_module_keys(module_id, num_keys); + for (size_t ikey = 0; ikey < num_keys; ++ikey) { + fabric_key.create_module_key(module_id); + } + + for (pugi::xml_node xml_key : xml_module.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_key.name() != std::string(XML_FABRIC_KEY_KEY_NODE_NAME)) { + bad_tag(xml_key, loc_data, xml_module, {XML_FABRIC_KEY_KEY_NODE_NAME}); + } + read_xml_module_key(xml_key, loc_data, fabric_key, module_id); + } +} + +/******************************************************************** + * Parse XML codes of a to an object of FabricKey + * - For top-level module, we expect a fixed name. If so, we use a special + *parser + * - For regular module, we follow regular parser + *******************************************************************/ +static void read_xml_fabric_keys_by_modules(pugi::xml_node& xml_module, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key) { + std::string name = + get_attribute(xml_module, XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME, + loc_data) + .as_string(); + if (name == std::string(openfpga::FPGA_TOP_MODULE_NAME)) { + read_xml_fabric_key_top_module(xml_module, loc_data, fabric_key); + } else { + read_xml_fabric_key_module(xml_module, loc_data, fabric_key); + } +} + +/******************************************************************** + * Parse XML codes about to an object of FabricKey + *******************************************************************/ +FabricKey read_xml_fabric_key(const char* key_fname) { + vtr::ScopedStartFinishTimer timer("Read Fabric Key"); + + FabricKey fabric_key; + + /* Parse the file */ + pugi::xml_document doc; + pugiutil::loc_data loc_data; + + try { + loc_data = pugiutil::load_xml(doc, key_fname); + + pugi::xml_node xml_root = + get_single_child(doc, XML_FABRIC_KEY_ROOT_NAME, loc_data); + + /* Under the root node, we expect only modules */ + size_t num_modules = + std::distance(xml_root.children().begin(), xml_root.children().end()); + + /* Reserve for memory efficiency */ + fabric_key.reserve_modules(num_modules); + + /* Walk through the modules, fill keys one by one */ + for (pugi::xml_node xml_module : xml_root.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_module.name() != std::string(XML_FABRIC_KEY_MODULE_NODE_NAME)) { + bad_tag(xml_module, loc_data, xml_root, + {XML_FABRIC_KEY_MODULE_NODE_NAME}); + } + /* Parse fabric keys by module */ + read_xml_fabric_keys_by_modules(xml_module, loc_data, fabric_key); + } + + } catch (pugiutil::XmlError& e) { + archfpga_throw(key_fname, e.line(), "%s", e.what()); + } + + return fabric_key; +} + +} // End of namespace openfpga diff --git a/libs/libfabrickey/src/read_xml_fabric_key.h b/libs/libfabrickey/src/io/read_xml_fabric_key.h similarity index 85% rename from libs/libfabrickey/src/read_xml_fabric_key.h rename to libs/libfabrickey/src/io/read_xml_fabric_key.h index c017aba6f..49ebbab34 100644 --- a/libs/libfabrickey/src/read_xml_fabric_key.h +++ b/libs/libfabrickey/src/io/read_xml_fabric_key.h @@ -9,6 +9,11 @@ /******************************************************************** * Function declaration *******************************************************************/ + +namespace openfpga { // Begin namespace openfpga + FabricKey read_xml_fabric_key(const char* key_fname); +} // End of namespace openfpga + #endif diff --git a/libs/libfabrickey/src/io/write_xml_fabric_key.cpp b/libs/libfabrickey/src/io/write_xml_fabric_key.cpp new file mode 100644 index 000000000..a3bb10888 --- /dev/null +++ b/libs/libfabrickey/src/io/write_xml_fabric_key.cpp @@ -0,0 +1,351 @@ +/******************************************************************** + * This file includes functions that outputs a configuration protocol to XML + *format + *******************************************************************/ +/* Headers from system goes first */ +#include +#include + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpga util library */ +#include "openfpga_digest.h" +#include "openfpga_reserved_words.h" + +/* Headers from arch openfpga library */ +#include "write_xml_utils.h" + +/* Headers from fabrickey library */ +#include "fabric_key_xml_constants.h" +#include "write_xml_fabric_key.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * A writer to output a component sub key to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +static int write_xml_fabric_component_sub_key( + std::fstream& fp, const FabricKey& fabric_key, + const FabricSubKeyId& component_key, const size_t& key_idx, + const size_t& level) { + /* Validate the file stream */ + if (false == openfpga::valid_file_stream(fp)) { + return 2; + } + + openfpga::write_tab_to_file(fp, level); + fp << "<" << XML_FABRIC_KEY_KEY_NODE_NAME; + + if (false == fabric_key.valid_sub_key_id(component_key)) { + return 1; + } + + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME, key_idx); + if (!fabric_key.sub_key_name(component_key).empty()) { + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME, + fabric_key.sub_key_name(component_key).c_str()); + } + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME, + fabric_key.sub_key_value(component_key)); + + if (!fabric_key.sub_key_alias(component_key).empty()) { + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME, + fabric_key.sub_key_alias(component_key).c_str()); + } + + fp << "/>" + << "\n"; + + return 0; +} + +/******************************************************************** + * A writer to output a component key to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +static int write_xml_fabric_component_key(std::fstream& fp, + const FabricKey& fabric_key, + const FabricKeyId& component_key, + const size_t& level) { + /* Validate the file stream */ + if (false == openfpga::valid_file_stream(fp)) { + return 2; + } + + openfpga::write_tab_to_file(fp, level); + fp << "<" << XML_FABRIC_KEY_KEY_NODE_NAME; + + if (false == fabric_key.valid_key_id(component_key)) { + return 1; + } + + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ID_NAME, + size_t(component_key)); + if (!fabric_key.key_name(component_key).empty()) { + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_NAME_NAME, + fabric_key.key_name(component_key).c_str()); + } + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_VALUE_NAME, + fabric_key.key_value(component_key)); + + if (!fabric_key.key_alias(component_key).empty()) { + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ALIAS_NAME, + fabric_key.key_alias(component_key).c_str()); + } + + vtr::Point coord = fabric_key.key_coordinate(component_key); + if (fabric_key.valid_key_coordinate(coord)) { + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_COLUMN_NAME, + coord.x()); + write_xml_attribute(fp, XML_FABRIC_KEY_KEY_ATTRIBUTE_ROW_NAME, coord.y()); + } + + fp << "/>" + << "\n"; + + return 0; +} + +/******************************************************************** + * A writer to output a BL shift register bank description to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +static int write_xml_fabric_bl_shift_register_banks( + std::fstream& fp, const FabricKey& fabric_key, const FabricRegionId& region, + const size_t& level) { + /* Validate the file stream */ + if (false == openfpga::valid_file_stream(fp)) { + return 2; + } + + /* If we have an empty bank, we just skip it */ + if (0 == fabric_key.bl_banks(region).size()) { + return 0; + } + + /* Write the root node */ + openfpga::write_tab_to_file(fp, level); + fp << "<" << XML_FABRIC_KEY_BL_SHIFT_REGISTER_BANKS_NODE_NAME << ">" + << "\n"; + + for (const auto& bank : fabric_key.bl_banks(region)) { + openfpga::write_tab_to_file(fp, level + 1); + fp << "<" << XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME; + + write_xml_attribute( + fp, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME, + size_t(bank)); + + std::string port_str; + for (const auto& port : fabric_key.bl_bank_data_ports(region, bank)) { + port_str += generate_xml_port_name(port) + ","; + } + /* Chop the last comma */ + if (!port_str.empty()) { + port_str.pop_back(); + } + write_xml_attribute( + fp, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME, + port_str.c_str()); + + fp << "/>" + << "\n"; + } + + openfpga::write_tab_to_file(fp, level); + fp << "" + << "\n"; + + return 0; +} + +/******************************************************************** + * A writer to output a WL shift register bank description to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +static int write_xml_fabric_wl_shift_register_banks( + std::fstream& fp, const FabricKey& fabric_key, const FabricRegionId& region, + const size_t& level) { + /* Validate the file stream */ + if (false == openfpga::valid_file_stream(fp)) { + return 2; + } + + /* If we have an empty bank, we just skip it */ + if (0 == fabric_key.wl_banks(region).size()) { + return 0; + } + + /* Write the root node */ + openfpga::write_tab_to_file(fp, level); + fp << "<" << XML_FABRIC_KEY_WL_SHIFT_REGISTER_BANKS_NODE_NAME << ">" + << "\n"; + + for (const auto& bank : fabric_key.wl_banks(region)) { + openfpga::write_tab_to_file(fp, level + 1); + fp << "<" << XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_NODE_NAME; + + write_xml_attribute( + fp, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_ID_NAME, + size_t(bank)); + + std::string port_str; + for (const auto& port : fabric_key.wl_bank_data_ports(region, bank)) { + port_str += generate_xml_port_name(port) + ","; + } + /* Chop the last comma */ + if (!port_str.empty()) { + port_str.pop_back(); + } + write_xml_attribute( + fp, XML_FABRIC_KEY_BLWL_SHIFT_REGISTER_BANK_ATTRIBUTE_RANGE_NAME, + port_str.c_str()); + + fp << "/>" + << "\n"; + } + + openfpga::write_tab_to_file(fp, level); + fp << "" + << "\n"; + + return 0; +} + +/* Write keys under the top-level module to a file */ +static int write_xml_top_module_keys(std::fstream& fp, + const FabricKey& fabric_key, + const size_t& level) { + int err_code = 0; + /* Write the module declaration */ + openfpga::write_tab_to_file(fp, level); + fp << "<" << XML_FABRIC_KEY_MODULE_NODE_NAME << " " + << XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME << "=\"" + << FPGA_TOP_MODULE_NAME << "\"" + << ">\n"; + + /* Write region by region */ + for (const FabricRegionId& region : fabric_key.regions()) { + openfpga::write_tab_to_file(fp, level + 1); + fp << "<" << XML_FABRIC_KEY_REGION_NODE_NAME << " " + << XML_FABRIC_KEY_REGION_ATTRIBUTE_ID_NAME << "=\"" << size_t(region) + << "\"" + << ">\n"; + + /* Write shift register banks */ + write_xml_fabric_bl_shift_register_banks(fp, fabric_key, region, level + 2); + write_xml_fabric_wl_shift_register_banks(fp, fabric_key, region, level + 2); + + /* Write component by component */ + for (const FabricKeyId& key : fabric_key.region_keys(region)) { + err_code = write_xml_fabric_component_key(fp, fabric_key, key, level + 2); + if (0 != err_code) { + return err_code; + } + } + + openfpga::write_tab_to_file(fp, level + 1); + fp << "" + << "\n"; + } + + openfpga::write_tab_to_file(fp, level); + fp << "\n"; + + return err_code; +} + +/* Write keys under the a given module to a file */ +static int write_xml_module_keys(std::fstream& fp, const FabricKey& fabric_key, + const FabricKeyModuleId& module_id, + const size_t& level) { + int err_code = 0; + /* Write the module declaration */ + openfpga::write_tab_to_file(fp, level); + fp << "<" << XML_FABRIC_KEY_MODULE_NODE_NAME << " " + << XML_FABRIC_KEY_MODULE_ATTRIBUTE_NAME_NAME << "=\"" + << fabric_key.module_name(module_id) << "\"" + << ">\n"; + + /* Write component by component */ + size_t key_idx = 0; + for (const FabricSubKeyId& key : fabric_key.sub_keys(module_id)) { + err_code = write_xml_fabric_component_sub_key(fp, fabric_key, key, key_idx, + level + 1); + if (0 != err_code) { + return err_code; + } + key_idx++; + } + + openfpga::write_tab_to_file(fp, level); + fp << "\n"; + + return err_code; +} + +/******************************************************************** + * A writer to output a fabric key to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key) { + vtr::ScopedStartFinishTimer timer("Write Fabric Key"); + + /* Create a file handler */ + std::fstream fp; + /* Open the file stream */ + fp.open(std::string(fname), std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Write the root node */ + fp << "<" << XML_FABRIC_KEY_ROOT_NAME << ">" + << "\n"; + + int err_code = 0; + + /* Write the top-level module */ + err_code = write_xml_top_module_keys(fp, fabric_key, 1); + if (0 != err_code) { + return err_code; + } + + /* Write regular modules */ + for (FabricKeyModuleId module_id : fabric_key.modules()) { + err_code = write_xml_module_keys(fp, fabric_key, module_id, 1); + if (0 != err_code) { + return err_code; + } + } + + /* Finish writing the root node */ + fp << "" + << "\n"; + + /* Close the file stream */ + fp.close(); + + return err_code; +} + +} // End of namespace openfpga diff --git a/libs/libfabrickey/src/write_xml_fabric_key.h b/libs/libfabrickey/src/io/write_xml_fabric_key.h similarity index 86% rename from libs/libfabrickey/src/write_xml_fabric_key.h rename to libs/libfabrickey/src/io/write_xml_fabric_key.h index a47c2602e..0e7d8e35b 100644 --- a/libs/libfabrickey/src/write_xml_fabric_key.h +++ b/libs/libfabrickey/src/io/write_xml_fabric_key.h @@ -11,6 +11,11 @@ /******************************************************************** * Function declaration *******************************************************************/ + +namespace openfpga { // Begin namespace openfpga + int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key); +} // End of namespace openfpga + #endif diff --git a/libs/libfabrickey/src/read_xml_fabric_key.cpp b/libs/libfabrickey/src/read_xml_fabric_key.cpp deleted file mode 100644 index 3ae4d792f..000000000 --- a/libs/libfabrickey/src/read_xml_fabric_key.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/******************************************************************** - * This file includes the top-level function of this library - * which reads an XML of a fabric key to the associated - * data structures - *******************************************************************/ -#include - -/* Headers from pugi XML library */ -#include "pugixml.hpp" -#include "pugixml_util.hpp" - -/* Headers from vtr util library */ -#include "vtr_assert.h" -#include "vtr_time.h" - -/* Headers from openfpga util library */ -#include "openfpga_port_parser.h" -#include "openfpga_tokenizer.h" - -/* Headers from libarchfpga */ -#include "arch_error.h" -#include "read_xml_fabric_key.h" -#include "read_xml_util.h" - -/******************************************************************** - * Parse XML codes of a to an object of FabricKey - *******************************************************************/ -static void read_xml_region_key(pugi::xml_node& xml_component_key, - const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, - const FabricRegionId& fabric_region) { - /* Find the id of component key */ - const size_t& id = get_attribute(xml_component_key, "id", loc_data).as_int(); - - if (false == fabric_key.valid_key_id(FabricKeyId(id))) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key), - "Invalid 'id' attribute '%d' (in total %lu keys)!\n", id, - fabric_key.keys().size()); - } - - VTR_ASSERT_SAFE(true == fabric_key.valid_key_id(FabricKeyId(id))); - - /* If we have an alias, set the value as well */ - const std::string& alias = get_attribute(xml_component_key, "alias", loc_data, - pugiutil::ReqOpt::OPTIONAL) - .as_string(); - if (!alias.empty()) { - fabric_key.set_key_alias(FabricKeyId(id), alias); - } - - /* If we have the alias set, name and valus are optional then - * Otherwise, they are mandatory attributes - */ - pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL; - if (true == alias.empty()) { - required_name_value = pugiutil::ReqOpt::REQUIRED; - } - - const std::string& name = - get_attribute(xml_component_key, "name", loc_data, required_name_value) - .as_string(); - const size_t& value = - get_attribute(xml_component_key, "value", loc_data, required_name_value) - .as_int(); - - fabric_key.set_key_name(FabricKeyId(id), name); - fabric_key.set_key_value(FabricKeyId(id), value); - fabric_key.add_key_to_region(fabric_region, FabricKeyId(id)); - - /* Parse coordinates */ - vtr::Point coord; - coord.set_x(get_attribute(xml_component_key, "column", loc_data, - pugiutil::ReqOpt::OPTIONAL) - .as_int(-1)); - coord.set_y(get_attribute(xml_component_key, "row", loc_data, - pugiutil::ReqOpt::OPTIONAL) - .as_int(-1)); - if (fabric_key.valid_key_coordinate(coord)) { - fabric_key.set_key_coordinate(FabricKeyId(id), coord); - } -} - -/******************************************************************** - * Parse XML codes of a under to an object of - *FabricKey - *******************************************************************/ -static void read_xml_region_bl_shift_register_bank( - pugi::xml_node& xml_bank, const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, const FabricRegionId& fabric_region) { - /* Find the id of the bank */ - FabricBitLineBankId bank_id = - FabricBitLineBankId(get_attribute(xml_bank, "id", loc_data).as_int()); - - if (!fabric_key.valid_bl_bank_id(fabric_region, bank_id)) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank), - "Invalid 'id' attribute '%lu' (in total %lu BL banks)!\n", - size_t(bank_id), fabric_key.bl_banks(fabric_region).size()); - } - - VTR_ASSERT_SAFE(true == fabric_key.valid_bl_bank_id(fabric_region, bank_id)); - - /* Parse the ports */ - std::string data_ports = - get_attribute(xml_bank, "range", loc_data).as_string(); - /* Split with ',' if we have multiple ports */ - openfpga::StringToken tokenizer(data_ports); - for (const std::string& data_port : tokenizer.split(',')) { - openfpga::PortParser data_port_parser(data_port); - fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, bank_id, - data_port_parser.port()); - } -} - -/******************************************************************** - * Parse XML codes of a to an object of FabricKey - *******************************************************************/ -static void read_xml_region_bl_shift_register_banks( - pugi::xml_node& xml_bl_bank, const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, const FabricRegionId& fabric_region) { - size_t num_banks = - count_children(xml_bl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL); - fabric_key.reserve_bl_shift_register_banks(fabric_region, num_banks); - - for (size_t ibank = 0; ibank < num_banks; ++ibank) { - fabric_key.create_bl_shift_register_bank(fabric_region); - } - - for (pugi::xml_node xml_bank : xml_bl_bank.children()) { - /* Error out if the XML child has an invalid name! */ - if (xml_bank.name() != std::string("bank")) { - bad_tag(xml_bank, loc_data, xml_bl_bank, {"bank"}); - } - read_xml_region_bl_shift_register_bank(xml_bank, loc_data, fabric_key, - fabric_region); - } -} - -/******************************************************************** - * Parse XML codes of a under to an object of - *FabricKey - *******************************************************************/ -static void read_xml_region_wl_shift_register_bank( - pugi::xml_node& xml_bank, const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, const FabricRegionId& fabric_region) { - /* Find the id of the bank */ - FabricWordLineBankId bank_id = - FabricWordLineBankId(get_attribute(xml_bank, "id", loc_data).as_int()); - - if (!fabric_key.valid_wl_bank_id(fabric_region, bank_id)) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank), - "Invalid 'id' attribute '%lu' (in total %lu WL banks)!\n", - size_t(bank_id), fabric_key.wl_banks(fabric_region).size()); - } - - VTR_ASSERT_SAFE(true == fabric_key.valid_wl_bank_id(fabric_region, bank_id)); - - /* Parse the ports */ - std::string data_ports = - get_attribute(xml_bank, "range", loc_data).as_string(); - /* Split with ',' if we have multiple ports */ - openfpga::StringToken tokenizer(data_ports); - for (const std::string& data_port : tokenizer.split(',')) { - openfpga::PortParser data_port_parser(data_port); - fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, bank_id, - data_port_parser.port()); - } -} - -/******************************************************************** - * Parse XML codes of a to an object of FabricKey - *******************************************************************/ -static void read_xml_region_wl_shift_register_banks( - pugi::xml_node& xml_wl_bank, const pugiutil::loc_data& loc_data, - FabricKey& fabric_key, const FabricRegionId& fabric_region) { - size_t num_banks = - count_children(xml_wl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL); - fabric_key.reserve_wl_shift_register_banks(fabric_region, num_banks); - - for (size_t ibank = 0; ibank < num_banks; ++ibank) { - fabric_key.create_wl_shift_register_bank(fabric_region); - } - - for (pugi::xml_node xml_bank : xml_wl_bank.children()) { - /* Error out if the XML child has an invalid name! */ - if (xml_bank.name() != std::string("bank")) { - bad_tag(xml_bank, loc_data, xml_wl_bank, {"bank"}); - } - read_xml_region_wl_shift_register_bank(xml_bank, loc_data, fabric_key, - fabric_region); - } -} - -/******************************************************************** - * Parse XML codes of a to an object of FabricKey - *******************************************************************/ -static void read_xml_fabric_region(pugi::xml_node& xml_region, - const pugiutil::loc_data& loc_data, - FabricKey& fabric_key) { - /* Find the unique id for the region */ - const FabricRegionId& region_id = - FabricRegionId(get_attribute(xml_region, "id", loc_data).as_int()); - if (false == fabric_key.valid_region_id(region_id)) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region), - "Invalid region id '%lu' (in total %lu regions)!\n", - size_t(region_id), fabric_key.regions().size()); - } - VTR_ASSERT_SAFE(true == fabric_key.valid_region_id(region_id)); - - /* Reserve memory space for the keys in the region */ - size_t num_keys = - count_children(xml_region, "key", loc_data, pugiutil::ReqOpt::OPTIONAL); - fabric_key.reserve_region_keys(region_id, num_keys); - - /* Parse the key for this region */ - if (0 < num_keys) { - pugi::xml_node xml_key = get_first_child(xml_region, "key", loc_data); - while (xml_key) { - read_xml_region_key(xml_key, loc_data, fabric_key, region_id); - xml_key = xml_key.next_sibling(xml_key.name()); - } - } - - /* Parse the BL shift register bank for this region */ - pugi::xml_node xml_bl_bank = - get_single_child(xml_region, "bl_shift_register_banks", loc_data, - pugiutil::ReqOpt::OPTIONAL); - read_xml_region_bl_shift_register_banks(xml_bl_bank, loc_data, fabric_key, - region_id); - - /* Parse the WL shift register bank for this region */ - pugi::xml_node xml_wl_bank = - get_single_child(xml_region, "wl_shift_register_banks", loc_data, - pugiutil::ReqOpt::OPTIONAL); - read_xml_region_wl_shift_register_banks(xml_wl_bank, loc_data, fabric_key, - region_id); -} - -/******************************************************************** - * Parse XML codes about to an object of FabricKey - *******************************************************************/ -FabricKey read_xml_fabric_key(const char* key_fname) { - vtr::ScopedStartFinishTimer timer("Read Fabric Key"); - - FabricKey fabric_key; - - /* Parse the file */ - pugi::xml_document doc; - pugiutil::loc_data loc_data; - - try { - loc_data = pugiutil::load_xml(doc, key_fname); - - pugi::xml_node xml_root = get_single_child(doc, "fabric_key", loc_data); - - size_t num_regions = - std::distance(xml_root.children().begin(), xml_root.children().end()); - /* Reserve memory space for the region */ - fabric_key.reserve_regions(num_regions); - for (size_t iregion = 0; iregion < num_regions; ++iregion) { - fabric_key.create_region(); - } - - /* Reserve memory space for the keys */ - size_t num_keys = 0; - - for (pugi::xml_node xml_region : xml_root.children()) { - /* Error out if the XML child has an invalid name! */ - if (xml_region.name() != std::string("region")) { - bad_tag(xml_region, loc_data, xml_root, {"region"}); - } - num_keys += std::distance(xml_region.children().begin(), - xml_region.children().end()); - } - - fabric_key.reserve_keys(num_keys); - for (size_t ikey = 0; ikey < num_keys; ++ikey) { - fabric_key.create_key(); - } - - /* Iterate over the children under this node, - * each child should be named after circuit_model - */ - for (pugi::xml_node xml_region : xml_root.children()) { - /* Error out if the XML child has an invalid name! */ - if (xml_region.name() != std::string("region")) { - bad_tag(xml_region, loc_data, xml_root, {"region"}); - } - read_xml_fabric_region(xml_region, loc_data, fabric_key); - } - } catch (pugiutil::XmlError& e) { - archfpga_throw(key_fname, e.line(), "%s", e.what()); - } - - return fabric_key; -} diff --git a/libs/libfabrickey/src/utils/check_fabric_key.cpp b/libs/libfabrickey/src/utils/check_fabric_key.cpp new file mode 100644 index 000000000..1e8964a33 --- /dev/null +++ b/libs/libfabrickey/src/utils/check_fabric_key.cpp @@ -0,0 +1,117 @@ +/************************************************************************ + * Check functions for the content of fabric key to avoid conflicts with + * other data structures + * These functions are not universal methods for the FabricKey class + * They are made to ease the development in some specific purposes + * Please classify such functions in this file + ***********************************************************************/ +#include "check_fabric_key.h" + +#include "vtr_assert.h" +#include "vtr_log.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/** @brief Sanity checks for fabric key alias attribute: + * - Each alias should NOT be empty + * - Each alias should be defined only once! + */ +int check_fabric_key_alias(const FabricKey& input_key, const bool& verbose) { + /* Check each key now */ + size_t num_errors = 0; + float progress = 0.; + size_t num_keys_checked = 0; + + std::map alias_count; + for (FabricKeyId key_id : input_key.keys()) { + /* Note that this is slow. May consider to build a map first */ + std::string curr_alias = input_key.key_alias(key_id); + progress = static_cast(num_keys_checked) / + static_cast(input_key.num_keys()) * 100.0; + VTR_LOGV(verbose, "[%lu%] Checking key alias '%s'\r", size_t(progress), + curr_alias.c_str()); + if (curr_alias.empty()) { + VTR_LOG_ERROR( + "Empty key alias (id='%lu') found in keys which is invalid!\n", + size_t(key_id)); + num_errors++; + } + auto result = alias_count.find(curr_alias); + if (result == alias_count.end()) { + alias_count[curr_alias] = 0; + } else { + alias_count[curr_alias] += 1; + } + num_keys_checked++; + } + for (const auto& kv : alias_count) { + if (kv.second > 1) { + std::string key_id_str; + std::vector found_keys = + input_key.find_key_by_alias(kv.first); + for (FabricKeyId found_key_id : found_keys) { + key_id_str += std::to_string(size_t(found_key_id)) + ","; + } + key_id_str.pop_back(); /* Remove last comma */ + VTR_LOG_ERROR( + "Duplicated key alias '%s' found %lu times in keys (ids: %s), which is " + "invalid!\n", + kv.first.c_str(), kv.second, key_id_str.c_str()); + num_errors++; + } + } + + return num_errors; +} + +/** @brief Sanity checks for fabric key name and value attribute: + * - Each name should not be empty + * - Each value should be larger than zero ! + */ +int check_fabric_key_names_and_values(const FabricKey& input_key, + const bool& verbose) { + /* Check each key now */ + size_t num_errors = 0; + float progress = 0.; + size_t num_keys_checked = 0; + + std::map> key_value_count; + for (FabricKeyId key_id : input_key.keys()) { + /* Note that this is slow. May consider to build a map first */ + std::string curr_name = input_key.key_name(key_id); + size_t curr_value = input_key.key_value(key_id); + progress = static_cast(num_keys_checked) / + static_cast(input_key.num_keys()) * 100.0; + VTR_LOGV(verbose, "[%lu%] Checking key names and values '(%s, %lu)'\r", + size_t(progress), curr_name.c_str(), curr_value); + if (curr_name.empty()) { + VTR_LOG_ERROR( + "Empty key name (id='%lu') found in keys which is invalid!\n", + size_t(key_id)); + num_errors++; + } + auto result = key_value_count[curr_name].find(curr_value); + if (result == key_value_count[curr_name].end()) { + key_value_count[curr_name][curr_value] = 0; + } else { + key_value_count[curr_name][curr_value] += 1; + } + num_keys_checked++; + } + for (const auto& key_name_kv : key_value_count) { + for (const auto& key_value_kv : key_name_kv.second) { + if (key_value_kv.second > 1) { + VTR_LOG_ERROR( + "Duplicated key name and value pair (%s, %lu) found %lu times in " + "keys, which is invalid!\n", + key_name_kv.first.c_str(), key_value_kv.first, key_value_kv.second); + num_errors++; + } + } + } + + return num_errors; +} + +} /* end namespace openfpga */ diff --git a/libs/libfabrickey/src/utils/check_fabric_key.h b/libs/libfabrickey/src/utils/check_fabric_key.h new file mode 100644 index 000000000..63f3f31db --- /dev/null +++ b/libs/libfabrickey/src/utils/check_fabric_key.h @@ -0,0 +1,23 @@ +#ifndef CHECK_FABRIC_KEY_H +#define CHECK_FABRIC_KEY_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "fabric_key.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int check_fabric_key_alias(const FabricKey& input_key, const bool& verbose); + +int check_fabric_key_names_and_values(const FabricKey& input_key, + const bool& verbose); + +} /* end namespace openfpga */ + +#endif diff --git a/libs/libfabrickey/src/write_xml_fabric_key.cpp b/libs/libfabrickey/src/write_xml_fabric_key.cpp deleted file mode 100644 index 133c05ddd..000000000 --- a/libs/libfabrickey/src/write_xml_fabric_key.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/******************************************************************** - * This file includes functions that outputs a configuration protocol to XML - *format - *******************************************************************/ -/* Headers from system goes first */ -#include -#include - -/* Headers from vtr util library */ -#include "vtr_assert.h" -#include "vtr_log.h" -#include "vtr_time.h" - -/* Headers from openfpga util library */ -#include "openfpga_digest.h" - -/* Headers from arch openfpga library */ -#include "write_xml_utils.h" - -/* Headers from fabrickey library */ -#include "write_xml_fabric_key.h" - -/******************************************************************** - * A writer to output a component key to XML format - * - * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture - * Return 2 if fail when creating files - *******************************************************************/ -static int write_xml_fabric_component_key(std::fstream& fp, - const FabricKey& fabric_key, - const FabricKeyId& component_key) { - /* Validate the file stream */ - if (false == openfpga::valid_file_stream(fp)) { - return 2; - } - - openfpga::write_tab_to_file(fp, 2); - fp << " coord = fabric_key.key_coordinate(component_key); - if (fabric_key.valid_key_coordinate(coord)) { - write_xml_attribute(fp, "column", coord.x()); - write_xml_attribute(fp, "row", coord.y()); - } - - fp << "/>" - << "\n"; - - return 0; -} - -/******************************************************************** - * A writer to output a BL shift register bank description to XML format - * - * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture - * Return 2 if fail when creating files - *******************************************************************/ -static int write_xml_fabric_bl_shift_register_banks( - std::fstream& fp, const FabricKey& fabric_key, const FabricRegionId& region) { - /* Validate the file stream */ - if (false == openfpga::valid_file_stream(fp)) { - return 2; - } - - /* If we have an empty bank, we just skip it */ - if (0 == fabric_key.bl_banks(region).size()) { - return 0; - } - - /* Write the root node */ - openfpga::write_tab_to_file(fp, 2); - fp << "" - << "\n"; - - for (const auto& bank : fabric_key.bl_banks(region)) { - openfpga::write_tab_to_file(fp, 3); - fp << "" - << "\n"; - } - - openfpga::write_tab_to_file(fp, 2); - fp << "" - << "\n"; - - return 0; -} - -/******************************************************************** - * A writer to output a WL shift register bank description to XML format - * - * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture - * Return 2 if fail when creating files - *******************************************************************/ -static int write_xml_fabric_wl_shift_register_banks( - std::fstream& fp, const FabricKey& fabric_key, const FabricRegionId& region) { - /* Validate the file stream */ - if (false == openfpga::valid_file_stream(fp)) { - return 2; - } - - /* If we have an empty bank, we just skip it */ - if (0 == fabric_key.wl_banks(region).size()) { - return 0; - } - - /* Write the root node */ - openfpga::write_tab_to_file(fp, 2); - fp << "" - << "\n"; - - for (const auto& bank : fabric_key.wl_banks(region)) { - openfpga::write_tab_to_file(fp, 3); - fp << "" - << "\n"; - } - - openfpga::write_tab_to_file(fp, 2); - fp << "" - << "\n"; - - return 0; -} - -/******************************************************************** - * A writer to output a fabric key to XML format - * - * Return 0 if successful - * Return 1 if there are more serious bugs in the architecture - * Return 2 if fail when creating files - *******************************************************************/ -int write_xml_fabric_key(const char* fname, const FabricKey& fabric_key) { - vtr::ScopedStartFinishTimer timer("Write Fabric Key"); - - /* Create a file handler */ - std::fstream fp; - /* Open the file stream */ - fp.open(std::string(fname), std::fstream::out | std::fstream::trunc); - - /* Validate the file stream */ - openfpga::check_file_stream(fname, fp); - - /* Write the root node */ - fp << "" - << "\n"; - - int err_code = 0; - - /* Write region by region */ - for (const FabricRegionId& region : fabric_key.regions()) { - openfpga::write_tab_to_file(fp, 1); - fp << "\n"; - - /* Write shift register banks */ - write_xml_fabric_bl_shift_register_banks(fp, fabric_key, region); - write_xml_fabric_wl_shift_register_banks(fp, fabric_key, region); - - /* Write component by component */ - for (const FabricKeyId& key : fabric_key.region_keys(region)) { - err_code = write_xml_fabric_component_key(fp, fabric_key, key); - if (0 != err_code) { - return err_code; - } - } - - openfpga::write_tab_to_file(fp, 1); - fp << "" - << "\n"; - } - - /* Finish writing the root node */ - fp << "" - << "\n"; - - /* Close the file stream */ - fp.close(); - - return err_code; -} diff --git a/libs/libfabrickey/test/fabric_key_assistant.cpp b/libs/libfabrickey/test/fabric_key_assistant.cpp new file mode 100644 index 000000000..c0befce57 --- /dev/null +++ b/libs/libfabrickey/test/fabric_key_assistant.cpp @@ -0,0 +1,233 @@ +/******************************************************************** + * Unit test functions to validate the correctness of + * 1. parser of data structures + * 2. writer of data structures + *******************************************************************/ +/* Headers from vtrutils */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from fabric key */ +#include "check_fabric_key.h" +#include "command_echo.h" +#include "command_exit_codes.h" +#include "command_parser.h" +#include "read_xml_fabric_key.h" +#include "write_xml_fabric_key.h" + +/** @brief Initialize the options from command-line inputs and organize in the + * format that is ready for parsing */ +static std::vector format_argv(const std::string& cmd_name, + int argc, const char** argv) { + std::vector cmd_opts; + cmd_opts.push_back(cmd_name); + for (int iarg = 1; iarg < argc; ++iarg) { + cmd_opts.push_back(std::string(argv[iarg])); + } + return cmd_opts; +} + +/** @brief Checks to be done: + * - Each alias of reference key can be found in the input key + */ +static int check_input_and_ref_key_alias_match( + const openfpga::FabricKey& input_key, const openfpga::FabricKey& ref_key, + const bool& verbose) { + size_t num_errors = 0; + size_t num_keys_checked = 0; + float progress = 0.; + VTR_LOG( + "Checking key alias matching between reference key and input keys...\n"); + for (openfpga::FabricKeyId key_id : ref_key.keys()) { + /* Note that this is slow. May consider to build a map first */ + std::string curr_alias = ref_key.key_alias(key_id); + std::vector input_found_keys = + input_key.find_key_by_alias(curr_alias); + progress = static_cast(num_keys_checked) / + static_cast(ref_key.num_keys()) * 100.0; + VTR_LOGV(verbose, "[%lu%] Checking key alias '%s'\r", size_t(progress), + curr_alias.c_str()); + if (input_found_keys.empty()) { + VTR_LOG_ERROR( + "Invalid alias '%s' in the reference key (id='%lu'), which does not " + "exist in the input key!\n", + curr_alias.c_str(), size_t(key_id)); + num_errors++; + } + if (input_found_keys.size() > 1) { + VTR_LOG_ERROR( + "Invalid alias '%s' in the input key (id='%lu'), which have been " + "found %lu times!\n", + curr_alias.c_str(), size_t(key_id), input_found_keys.size()); + num_errors++; + } + num_keys_checked++; + } + VTR_LOG( + "Checking key alias matching between reference key and input keys... %s\n", + num_errors ? "[Fail]" : "[Pass]"); + return num_errors ? openfpga::CMD_EXEC_FATAL_ERROR + : openfpga::CMD_EXEC_SUCCESS; +} + +/** @brief Checks to be done: + * - Number of configuration regions match + * - Number of keys match + */ +static int check_input_key(const openfpga::FabricKey& input_key, + const openfpga::FabricKey& ref_key, + const bool& verbose) { + if (ref_key.num_regions() != input_key.num_regions()) { + VTR_LOG_ERROR( + "Different number of configuration regions between reference key " + "(='%lu') and input key ('=%lu')!\n", + ref_key.num_regions(), input_key.num_regions()); + return openfpga::CMD_EXEC_FATAL_ERROR; + } + if (ref_key.num_keys() != input_key.num_keys()) { + VTR_LOG_ERROR( + "Different number of keys between reference key (='%lu') and input key " + "('=%lu')!\n", + ref_key.num_keys(), input_key.num_keys()); + return openfpga::CMD_EXEC_FATAL_ERROR; + } + size_t num_errors = 0; + size_t curr_num_err = 0; + VTR_LOG("Checking key alias in reference key...\n"); + curr_num_err = openfpga::check_fabric_key_alias(ref_key, verbose); + VTR_LOG("Checking key alias in reference key... %s\n", + curr_num_err ? "[Fail]" : "[Pass]"); + VTR_LOG("Checking key names and values in reference key...\n"); + curr_num_err = openfpga::check_fabric_key_names_and_values(ref_key, verbose); + num_errors += curr_num_err; + VTR_LOG("Checking key names and valus in reference key... %s\n", + curr_num_err ? "[Fail]" : "[Pass]"); + VTR_LOG("Checking key alias in input key...\n"); + curr_num_err = openfpga::check_fabric_key_alias(input_key, verbose); + num_errors += curr_num_err; + VTR_LOG("Checking key alias in input key... %s\n", + curr_num_err ? "[Fail]" : "[Pass]"); + num_errors += + check_input_and_ref_key_alias_match(input_key, ref_key, verbose); + return num_errors ? openfpga::CMD_EXEC_FATAL_ERROR + : openfpga::CMD_EXEC_SUCCESS; +} + +/** @brief Checks to be done: + * - Each alias of input key can be found in the reference key + * - Update input key with pair of name and value which matches the alias from + * the reference key + */ +static int update_input_key(openfpga::FabricKey& input_key, + const openfpga::FabricKey& ref_key, + const bool& verbose) { + size_t num_errors = 0; + size_t num_keys_checked = 0; + float progress = 0.; + VTR_LOG("Pairing key alias between reference key and input keys...\n"); + for (openfpga::FabricKeyId key_id : input_key.keys()) { + /* Note that this is slow. May consider to build a map first */ + std::string curr_alias = input_key.key_alias(key_id); + std::vector ref_found_keys = + ref_key.find_key_by_alias(curr_alias); + progress = static_cast(num_keys_checked) / + static_cast(input_key.num_keys()) * 100.0; + VTR_LOGV(verbose, "[%lu%] Pairing key alias '%s'\r", size_t(progress), + curr_alias.c_str()); + if (ref_found_keys.empty()) { + VTR_LOG_ERROR( + "Invalid alias '%s' in the input key (id='%lu'), which does not " + "exist in the reference key!\n", + curr_alias.c_str(), size_t(key_id)); + num_errors++; + } + if (ref_found_keys.size() > 1) { + VTR_LOG_ERROR( + "Invalid alias '%s' in the reference key (id='%lu'), which have been " + "found %lu times!\n", + curr_alias.c_str(), size_t(key_id)); + num_errors++; + } + /* Now we have a key, get the name and value, and update input key */ + input_key.set_key_name(key_id, ref_key.key_name(ref_found_keys[0])); + input_key.set_key_value(key_id, ref_key.key_value(ref_found_keys[0])); + VTR_LOGV(verbose, "[%lu%] Pairing key alias '%s' -> ('%s', %lu)\r", + size_t(progress), curr_alias.c_str(), + input_key.key_name(key_id).c_str(), input_key.key_value(key_id)); + num_keys_checked++; + } + return num_errors ? openfpga::CMD_EXEC_FATAL_ERROR + : openfpga::CMD_EXEC_SUCCESS; +} + +/** @brief Checks to be done: + * - Number of configuration regions match + * - Number of keys match + * - Each alias can be found in the reference key + */ +static int check_and_update_input_key(openfpga::FabricKey& input_key, + const openfpga::FabricKey& ref_key, + const bool& verbose) { + int status = openfpga::CMD_EXEC_SUCCESS; + status = check_input_key(input_key, ref_key, verbose); + if (status != openfpga::CMD_EXEC_SUCCESS) { + return openfpga::CMD_EXEC_FATAL_ERROR; + } + return update_input_key(input_key, ref_key, verbose); +} + +int main(int argc, const char** argv) { + /* Create a new command and Initialize the options available in the user + * interface */ + openfpga::Command cmd("fabric_key_assistant"); + openfpga::CommandOptionId opt_ref = + cmd.add_option("reference", true, "Specify the reference fabric key file"); + cmd.set_option_require_value(opt_ref, openfpga::OPT_STRING); + openfpga::CommandOptionId opt_input = + cmd.add_option("input", true, "Specify the hand-crafted fabric key file"); + cmd.set_option_require_value(opt_input, openfpga::OPT_STRING); + openfpga::CommandOptionId opt_output = cmd.add_option( + "output", true, "Specify the final fabric key file to be outputted"); + cmd.set_option_require_value(opt_output, openfpga::OPT_STRING); + openfpga::CommandOptionId opt_verbose = + cmd.add_option("verbose", false, "Show verbose outputs"); + openfpga::CommandOptionId opt_help = + cmd.add_option("help", false, "Show help desk"); + + /* Parse the option, to avoid issues, we use the command name to replace the + * argv[0] */ + std::vector cmd_opts = format_argv(cmd.name(), argc, argv); + + openfpga::CommandContext cmd_ctx(cmd); + if (false == parse_command(cmd_opts, cmd, cmd_ctx) || + cmd_ctx.option_enable(cmd, opt_help)) { + /* Echo the command */ + print_command_options(cmd); + return openfpga::CMD_EXEC_FATAL_ERROR; + } else { + /* Let user to confirm selected options */ + print_command_context(cmd, cmd_ctx); + } + + /* Parse the fabric key from an XML file */ + VTR_LOG("Read the reference fabric key from an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_ref).c_str()); + openfpga::FabricKey ref_key = + openfpga::read_xml_fabric_key(cmd_ctx.option_value(cmd, opt_ref).c_str()); + + VTR_LOG("Read the hand-crafted fabric key from an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_input).c_str()); + openfpga::FabricKey input_key = + openfpga::read_xml_fabric_key(cmd_ctx.option_value(cmd, opt_input).c_str()); + + /* Check the input key */ + if (check_and_update_input_key(input_key, ref_key, + cmd_ctx.option_enable(cmd, opt_verbose))) { + return openfpga::CMD_EXEC_FATAL_ERROR; + } + + VTR_LOG("Write the final fabric key to an XML file: %s.\n", + cmd_ctx.option_value(cmd, opt_output).c_str()); + return openfpga::write_xml_fabric_key( + cmd_ctx.option_value(cmd, opt_output).c_str(), input_key); +} diff --git a/libs/libfabrickey/test/test_fabric_key.cpp b/libs/libfabrickey/test/test_fabric_key.cpp index 014c53bef..7d412f64f 100644 --- a/libs/libfabrickey/test/test_fabric_key.cpp +++ b/libs/libfabrickey/test/test_fabric_key.cpp @@ -16,14 +16,14 @@ int main(int argc, const char** argv) { VTR_ASSERT((2 == argc) || (3 == argc)); /* Parse the fabric key from an XML file */ - FabricKey test_key = read_xml_fabric_key(argv[1]); + openfpga::FabricKey test_key = openfpga::read_xml_fabric_key(argv[1]); VTR_LOG("Read the fabric key from an XML file: %s.\n", argv[1]); /* Output the circuit library to an XML file * This is optional only used when there is a second argument */ if (3 <= argc) { - write_xml_fabric_key(argv[2], test_key); + openfpga::write_xml_fabric_key(argv[2], test_key); VTR_LOG("Echo the fabric key to an XML file: %s.\n", argv[2]); } } diff --git a/libs/libfpgabitstream/src/bitstream_manager.cpp b/libs/libfpgabitstream/src/bitstream_manager.cpp index d82c5832f..cf18a6e86 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager.cpp @@ -6,6 +6,7 @@ #include #include "vtr_assert.h" +#include "vtr_log.h" /* begin namespace openfpga */ namespace openfpga { @@ -200,10 +201,20 @@ ConfigBlockId BitstreamManager::create_block() { } ConfigBlockId BitstreamManager::add_block(const std::string& block_name) { - ConfigBlockId block = create_block(); - set_block_name(block, block_name); + ConfigBlockId new_block = create_block(); + set_block_name(new_block, block_name); + return new_block; +} - return block; +ConfigBlockId BitstreamManager::find_or_create_child_block( + const ConfigBlockId& block_id, const std::string& child_block_name) { + ConfigBlockId curr_block = find_child_block(block_id, child_block_name); + if (valid_block_id(curr_block)) { + return curr_block; + } + curr_block = add_block(child_block_name); + add_child_block(block_id, curr_block); + return curr_block; } void BitstreamManager::set_block_name(const ConfigBlockId& block_id, diff --git a/libs/libfpgabitstream/src/bitstream_manager.h b/libs/libfpgabitstream/src/bitstream_manager.h index aaf25b14c..4af15084d 100644 --- a/libs/libfpgabitstream/src/bitstream_manager.h +++ b/libs/libfpgabitstream/src/bitstream_manager.h @@ -181,6 +181,11 @@ class BitstreamManager { /* Add a new block of configuration bits to the bitstream manager */ ConfigBlockId add_block(const std::string& block_name); + /* Try to find the child block in a bitstream manager with a given name. If + * not found, create a new child block */ + ConfigBlockId find_or_create_child_block(const ConfigBlockId& block_id, + const std::string& child_block_name); + /* Set a name for a block */ void set_block_name(const ConfigBlockId& block_id, const std::string& block_name); @@ -234,6 +239,9 @@ class BitstreamManager { vtr::vector parent_block_ids_; vtr::vector> child_block_ids_; + /* Fast look-up by block name to ids */ + std::map block_name2ids_; + /* The ids of the inputs of routing multiplexer blocks which is propagated to * outputs By default, it will be -2 (which is invalid) A valid id starts from * -1 -1 indicates an unused routing multiplexer. It will be converted to a diff --git a/libs/libfpgabitstream/src/bitstream_manager_utils.cpp b/libs/libfpgabitstream/src/bitstream_manager_utils.cpp index c80431793..9a2ef1277 100644 --- a/libs/libfpgabitstream/src/bitstream_manager_utils.cpp +++ b/libs/libfpgabitstream/src/bitstream_manager_utils.cpp @@ -19,15 +19,23 @@ namespace openfpga { * Return a vector of the block ids, where the top-level block * locates in the head, while the leaf block locates in the tail * top, next, ... , block + * Optionally, the top block name in the path can be specified. Useful to trim + *the hierarchy with a given range *******************************************************************/ std::vector find_bitstream_manager_block_hierarchy( - const BitstreamManager& bitstream_manager, const ConfigBlockId& block) { + const BitstreamManager& bitstream_manager, const ConfigBlockId& block, + const std::string& top_block_name) { std::vector block_hierarchy; ConfigBlockId temp_block = block; /* Generate a tree of parent block */ while (true == bitstream_manager.valid_block_id(temp_block)) { block_hierarchy.push_back(temp_block); + /* Check if we have reached the designated top block */ + if (!top_block_name.empty() && + bitstream_manager.block_name(temp_block) == top_block_name) { + break; + } /* Go to upper level */ temp_block = bitstream_manager.block_parent(temp_block); } diff --git a/libs/libfpgabitstream/src/bitstream_manager_utils.h b/libs/libfpgabitstream/src/bitstream_manager_utils.h index f30793eb7..e427f834c 100644 --- a/libs/libfpgabitstream/src/bitstream_manager_utils.h +++ b/libs/libfpgabitstream/src/bitstream_manager_utils.h @@ -16,7 +16,8 @@ namespace openfpga { std::vector find_bitstream_manager_block_hierarchy( - const BitstreamManager& bitstream_manager, const ConfigBlockId& block); + const BitstreamManager& bitstream_manager, const ConfigBlockId& block, + const std::string& top_block_name = ""); std::vector find_bitstream_manager_top_blocks( const BitstreamManager& bitstream_manager); diff --git a/libs/libionamemap/CMakeLists.txt b/libs/libionamemap/CMakeLists.txt new file mode 100644 index 000000000..e99236d35 --- /dev/null +++ b/libs/libionamemap/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.9) + +project("libionamemap") + +file(GLOB_RECURSE EXEC_SOURCES test/*.cpp) +file(GLOB_RECURSE LIB_SOURCES src/*/*.cpp) +file(GLOB_RECURSE LIB_HEADERS src/*/*.h) +files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS) + +#Remove test executable from library +list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES}) + +#Create the library +add_library(libionamemap STATIC + ${LIB_HEADERS} + ${LIB_SOURCES}) +target_include_directories(libionamemap PUBLIC ${LIB_INCLUDE_DIRS}) +set_target_properties(libionamemap PROPERTIES PREFIX "") #Avoid extra 'lib' prefix + +#Specify link-time dependancies +target_link_libraries(libionamemap + libarchopenfpga + libopenfpgautil + libopenfpgashell + libvtrutil + libpugiutil) + +#Create the test executable +foreach(testsourcefile ${EXEC_SOURCES}) + # Use a simple string replace, to cut off .cpp. + get_filename_component(testname ${testsourcefile} NAME_WE) + add_executable(${testname} ${testsourcefile}) + # Make sure the library is linked to each test executable + target_link_libraries(${testname} libionamemap) +endforeach(testsourcefile ${EXEC_SOURCES}) + +install(TARGETS libionamemap DESTINATION bin) diff --git a/libs/libionamemap/example/example.xml b/libs/libionamemap/example/example.xml new file mode 100644 index 000000000..e00081951 --- /dev/null +++ b/libs/libionamemap/example/example.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/libs/libionamemap/src/base/io_name_map.cpp b/libs/libionamemap/src/base/io_name_map.cpp new file mode 100644 index 000000000..000c2eeaf --- /dev/null +++ b/libs/libionamemap/src/base/io_name_map.cpp @@ -0,0 +1,348 @@ +/****************************************************************************** + * Memember functions for data structure IoLocationMap + ******************************************************************************/ +/* Headers from vtrutil library */ +#include "io_name_map.h" + +#include + +#include "command_exit_codes.h" +#include "openfpga_port_parser.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* begin namespace openfpga */ +namespace openfpga { + +IoNameMap::IoNameMap() { + DUMMY_PORT_DIR_STRING_ = {"input", "output", "inout"}; +} + +/************************************************** + * Public Accessors + *************************************************/ +std::vector IoNameMap::fpga_top_ports() const { + std::vector ports; + + for (auto it = top2core_io_name_map_.begin(); + it != top2core_io_name_map_.end(); ++it) { + ports.push_back(str2port(it->first)); + } + + return ports; +} + +BasicPort IoNameMap::fpga_core_port(const BasicPort& fpga_top_port) const { + BasicPort core_port; + /* First, find the pin name matching */ + auto result_key = top2core_io_name_keys_.find(fpga_top_port.get_name()); + if (result_key == top2core_io_name_keys_.end()) { + return core_port; /* Not found, return invalid port */ + } + /* Second, find the exact key */ + std::string top_port_key; + for (std::string cand : result_key->second) { + BasicPort cand_port = str2port(cand); + /* if the top port is part of the cand port, e.g., clk[1] vs. clk[0:2], the + * candidate is the key that we want! */ + if (cand_port.contained(fpga_top_port)) { + top_port_key = cand; + break; + } + } + if (top_port_key.empty()) { + return core_port; /* Not found, return invalid port */ + } + auto result = top2core_io_name_map_.find(top_port_key); + if (result != top2core_io_name_map_.end() && result->second.is_valid()) { + BasicPort top_port_pool = str2port(top_port_key); + BasicPort fpga_top_port_lsb(fpga_top_port.get_name(), + fpga_top_port.get_lsb(), + fpga_top_port.get_lsb()); + BasicPort fpga_top_port_msb(fpga_top_port.get_name(), + fpga_top_port.get_msb(), + fpga_top_port.get_msb()); + size_t ipin_anchor_lsb = top_port_pool.find_ipin(fpga_top_port_lsb); + size_t ipin_anchor_msb = top_port_pool.find_ipin(fpga_top_port_msb); + /* Now find the exact pin and spot the core port with pin index */ + if (ipin_anchor_lsb < top_port_pool.get_width() && + ipin_anchor_msb < top_port_pool.get_width()) { + core_port.set_name(result->second.get_name()); + core_port.set_lsb(result->second.pins()[ipin_anchor_lsb]); + core_port.set_msb(result->second.pins()[ipin_anchor_msb]); + } + } + return core_port; +} + +BasicPort IoNameMap::fpga_top_port(const BasicPort& fpga_core_port) const { + BasicPort top_port; + /* First, find the pin name matching */ + auto result_key = core2top_io_name_keys_.find(fpga_core_port.get_name()); + if (result_key == core2top_io_name_keys_.end()) { + return top_port; /* Not found, return invalid port */ + } + /* Second, find the exact key */ + std::string core_port_key; + for (std::string cand : result_key->second) { + BasicPort cand_port = str2port(cand); + /* if the top port is part of the cand port, e.g., clk[1] vs. clk[0:2], the + * candidate is the key that we want! */ + if (cand_port.contained(fpga_core_port)) { + core_port_key = cand; + break; + } + } + if (core_port_key.empty()) { + return top_port; /* Not found, return invalid port */ + } + auto result = core2top_io_name_map_.find(core_port_key); + if (result != core2top_io_name_map_.end() && result->second.is_valid()) { + BasicPort core_port_pool = str2port(core_port_key); + BasicPort fpga_core_port_lsb(fpga_core_port.get_name(), + fpga_core_port.get_lsb(), + fpga_core_port.get_lsb()); + BasicPort fpga_core_port_msb(fpga_core_port.get_name(), + fpga_core_port.get_msb(), + fpga_core_port.get_msb()); + size_t ipin_anchor_lsb = core_port_pool.find_ipin(fpga_core_port); + size_t ipin_anchor_msb = core_port_pool.find_ipin(fpga_core_port); + /* Now find the exact pin and spot the core port with pin index */ + if (ipin_anchor_lsb < core_port_pool.get_width() && + ipin_anchor_msb < core_port_pool.get_width()) { + top_port.set_name(result->second.get_name()); + top_port.set_lsb(result->second.pins()[ipin_anchor_lsb]); + top_port.set_msb(result->second.pins()[ipin_anchor_msb]); + } + } + return top_port; +} + +IoNameMap::e_port_mapping_status IoNameMap::fpga_core_port_mapping_status( + const BasicPort& fpga_core_port, const bool& verbose) const { + /* First, find the pin name matching */ + auto result_key = core2top_io_name_keys_.find(fpga_core_port.get_name()); + if (result_key == core2top_io_name_keys_.end()) { + return IoNameMap::e_port_mapping_status::NONE; + } + /* Second, find the exact port. Create a scoreboard and check every pin. + * Expect only one hit per pin. Error on any pin which has been hit twice + * (indicate overlapped ports). Error on any pin which has no hit (indicate + * partially unmapped) */ + std::vector scoreboard(fpga_core_port.get_width(), 0); + for (std::string cand : result_key->second) { + BasicPort cand_port = str2port(cand); + for (auto pin : cand_port.pins()) { + scoreboard[pin - fpga_core_port.get_lsb()]++; + } + } + for (int8_t bit : scoreboard) { + if (bit == 0) { + VTR_LOGV_ERROR(verbose, + "Unmapped pin '%lu' of fpga_core port '%s'! Partially " + "mapping is not allowed\n", + fpga_core_port.pins()[bit + fpga_core_port.get_lsb()], + fpga_core_port.to_verilog_string().c_str()); + return IoNameMap::e_port_mapping_status::PARTIAL; + } + if (bit > 1) { + VTR_LOGV_ERROR(verbose, + "Overlapped %d times on pin '%lu' of fpga_core port '%s' " + "when mapping!\n", + bit, fpga_core_port.pins()[bit + fpga_core_port.get_lsb()], + fpga_core_port.to_verilog_string().c_str()); + return IoNameMap::e_port_mapping_status::OVERLAPPED; + } + } + return IoNameMap::e_port_mapping_status::FULL; +} + +bool IoNameMap::fpga_top_port_is_dummy(const BasicPort& fpga_top_port) const { + return !fpga_core_port(fpga_top_port).is_valid(); +} + +IoNameMap::e_dummy_port_direction IoNameMap::fpga_top_dummy_port_direction( + const BasicPort& fpga_top_port) const { + for (auto& kv : dummy_port_direction_) { + BasicPort cand = str2port(kv.first); + if (cand.contained(fpga_top_port)) { + return kv.second; + } + } + /* Return an invalid port type */ + return IoNameMap::e_dummy_port_direction::NUM_TYPES; +} + +bool IoNameMap::empty() const { + return top2core_io_name_keys_.empty() && top2core_io_name_map_.empty() && + core2top_io_name_keys_.empty() && core2top_io_name_map_.empty() && + dummy_port_direction_.empty(); +} + +int IoNameMap::set_io_pair(const BasicPort& fpga_top_port, + const BasicPort& fpga_core_port) { + /* Ensure the two ports are matching in size */ + if (fpga_top_port.get_width() != fpga_core_port.get_width()) { + VTR_LOG_ERROR( + "Unable to pair two ports 'fpga_top.%s[%lu:%lu]' and " + "'fpga_core.%s[%lu:%lu]' which are in the same size!\n", + fpga_top_port.get_name().c_str(), fpga_top_port.get_lsb(), + fpga_top_port.get_msb(), fpga_core_port.get_name().c_str(), + fpga_core_port.get_lsb(), fpga_core_port.get_msb()); + return CMD_EXEC_FATAL_ERROR; + } + VTR_ASSERT_SAFE(fpga_top_port.get_width() != fpga_core_port.get_width()); + /* Register in the key first, and then add to the exact name mapping */ + { + std::string top_port_str = port2str(fpga_top_port); + auto result_key = top2core_io_name_keys_.find(fpga_top_port.get_name()); + if (result_key == top2core_io_name_keys_.end()) { + /* Add to the key registery */ + top2core_io_name_keys_[fpga_top_port.get_name()].push_back(top_port_str); + top2core_io_name_map_[top_port_str] = fpga_core_port; + } else { + /* Ensure that the key is not duplicated */ + if (std::find(result_key->second.begin(), result_key->second.end(), + top_port_str) == result_key->second.end()) { + top2core_io_name_keys_[fpga_top_port.get_name()].push_back( + top_port_str); + top2core_io_name_map_[top_port_str] = fpga_core_port; + } else { + /* Throw a warning since we have to overwrite */ + VTR_LOG_WARN( + "Overwrite the top-to-core pin mapping: top pin '%s' to core pin " + "'%s' (previously was '%s')!\n", + top_port_str.c_str(), port2str(fpga_core_port).c_str(), + port2str(top2core_io_name_map_[top_port_str]).c_str()); + top2core_io_name_map_[top_port_str] = fpga_core_port; + } + } + } + /* Now, do similar to the core port */ + { + std::string core_port_str = port2str(fpga_core_port); + auto result_key = core2top_io_name_keys_.find(fpga_core_port.get_name()); + if (result_key == core2top_io_name_keys_.end()) { + /* Add to the key registery */ + core2top_io_name_keys_[fpga_core_port.get_name()].push_back( + core_port_str); + core2top_io_name_map_[core_port_str] = fpga_top_port; + } else { + /* Ensure that the key is not duplicated */ + if (std::find(result_key->second.begin(), result_key->second.end(), + core_port_str) == result_key->second.end()) { + core2top_io_name_keys_[fpga_core_port.get_name()].push_back( + core_port_str); + core2top_io_name_map_[core_port_str] = fpga_top_port; + } else { + /* Throw a warning since we have to overwrite */ + VTR_LOG_WARN( + "Overwrite the core-to-top pin mapping: core pin '%s' to top pin " + "'%s' (previously was '%s')!\n", + core_port_str.c_str(), port2str(fpga_top_port).c_str(), + port2str(core2top_io_name_map_[core_port_str]).c_str()); + core2top_io_name_map_[core_port_str] = fpga_top_port; + } + } + } + return CMD_EXEC_SUCCESS; +} + +int IoNameMap::set_dummy_io(const BasicPort& fpga_top_port, + const e_dummy_port_direction& direction) { + /* Must be a true dummy port, none of its pins have been paired! */ + std::string top_port_str = port2str(fpga_top_port); + /* First, find the pin name matching */ + auto result_key = top2core_io_name_keys_.find(fpga_top_port.get_name()); + if (result_key == top2core_io_name_keys_.end()) { + /* Add to the key registery */ + top2core_io_name_keys_[fpga_top_port.get_name()].push_back(top_port_str); + top2core_io_name_map_[top_port_str] = BasicPort(); + } else { + /* Ensure that the key is not duplicated */ + if (std::find(result_key->second.begin(), result_key->second.end(), + top_port_str) == result_key->second.end()) { + top2core_io_name_keys_[fpga_top_port.get_name()].push_back(top_port_str); + top2core_io_name_map_[top_port_str] = BasicPort(); + } else { + /* Throw a error because the dummy pin should NOT be mapped before! */ + VTR_LOG_ERROR( + "Dummy port '%s' of fpga_top is already mapped " + "to a valid pin '%s' of fpga_core!\n", + port2str(fpga_top_port).c_str(), + port2str(top2core_io_name_map_[top_port_str]).c_str()); + return CMD_EXEC_FATAL_ERROR; + } + } + /* Add the direction list */ + bool dir_defined = false; + for (auto& kv : dummy_port_direction_) { + BasicPort cand = str2port(kv.first); + if (cand.contained(fpga_top_port)) { + if (kv.second != direction) { + /* Throw a error because the dummy pin should NOT be mapped before! */ + VTR_LOG_ERROR( + "Dummy port '%s' of fpga_top is already assigned to a different " + "direction through another dummy port definition '%s'!\n", + port2str(fpga_top_port).c_str(), port2str(cand).c_str()); + return CMD_EXEC_FATAL_ERROR; + } + dir_defined = true; + break; + } + } + if (!dir_defined) { + dummy_port_direction_[top_port_str] = direction; + } + return CMD_EXEC_SUCCESS; +} + +std::string IoNameMap::port2str(const BasicPort& port) const { + return port.to_verilog_string(); +} + +BasicPort IoNameMap::str2port(const std::string& port_str) const { + return PortParser(port_str).port(); +} + +std::string IoNameMap::dummy_port_dir_all2str() const { + std::string full_types = "["; + for (int itype = size_t(IoNameMap::e_dummy_port_direction::INPUT); + itype != size_t(IoNameMap::e_dummy_port_direction::NUM_TYPES); ++itype) { + full_types += std::string(DUMMY_PORT_DIR_STRING_[itype]) + std::string("|"); + } + full_types.pop_back(); + full_types += "]"; + return full_types; +} + +IoNameMap::e_dummy_port_direction IoNameMap::str2dummy_port_dir( + const std::string& dir_str, const bool& verbose) const { + for (int itype = size_t(IoNameMap::e_dummy_port_direction::INPUT); + itype != size_t(IoNameMap::e_dummy_port_direction::NUM_TYPES); ++itype) { + if (dir_str == std::string(DUMMY_PORT_DIR_STRING_[itype])) { + return static_cast(itype); + } + } + VTR_LOGV_ERROR(verbose, "Invalid direction for dummy port! Expect %s\n", + dummy_port_dir_all2str().c_str()); + return IoNameMap::e_dummy_port_direction::NUM_TYPES; +} + +std::string IoNameMap::dummy_port_dir2str(const e_dummy_port_direction& dir, + const bool& verbose) const { + if (!valid_dummy_port_direction(dir)) { + VTR_LOGV_ERROR(verbose, "Invalid direction for dummy port! Expect %s\n", + dummy_port_dir_all2str().c_str()); + return std::string(); + } + return std::string(DUMMY_PORT_DIR_STRING_[size_t(dir)]); +} + +bool IoNameMap::valid_dummy_port_direction( + const IoNameMap::e_dummy_port_direction& direction) const { + return direction != IoNameMap::e_dummy_port_direction::NUM_TYPES; +} + +} /* end namespace openfpga */ diff --git a/libs/libionamemap/src/base/io_name_map.h b/libs/libionamemap/src/base/io_name_map.h new file mode 100644 index 000000000..b1f107a10 --- /dev/null +++ b/libs/libionamemap/src/base/io_name_map.h @@ -0,0 +1,111 @@ +#ifndef IO_NAME_MAP_H +#define IO_NAME_MAP_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include + +#include "openfpga_port.h" + +/* Begin namespace openfpga */ +namespace openfpga { + +/** + * @brief I/O name map is a data structure to show mapping between the ports + * of fpga_top and fpga_core, which are the two possible top-level modules that + * modeling a complete FPGA fabric Using the data structure, developers can find + * - the corresponding port of fpga_core, with a given port of fpga_top + * - the corresponding port of fpga_top, with a given port of fpga_core + */ +class IoNameMap { + public: /* Types */ + enum class e_dummy_port_direction { INPUT = 0, OUTPUT, INOUT, NUM_TYPES }; + enum class e_port_mapping_status { + NONE = 0, + PARTIAL, + FULL, + OVERLAPPED, + NUM_TYPES + }; + + public: /* Constructors */ + IoNameMap(); + + public: /* Public accessors */ + /** @brief Get all the fpga top ports */ + std::vector fpga_top_ports() const; + /** @brief With a given port at fpga_top, find the corresponding I/O at + * fpga_core. Return an invalid port if not found */ + BasicPort fpga_core_port(const BasicPort& fpga_top_port) const; + /** @brief With a given port at fpga_core, find the corresponding I/O at + * fpga_top. Return an invalid port if not found */ + BasicPort fpga_top_port(const BasicPort& fpga_core_port) const; + /** @brief Identify if the fpga_top port is dummy or not */ + bool fpga_top_port_is_dummy(const BasicPort& fpga_top_port) const; + /** @brief Get the direction of a dummy port */ + e_dummy_port_direction fpga_top_dummy_port_direction( + const BasicPort& fpga_top_port) const; + /** @brief Check if a core port, by considering its port name only, has been + * fully/partially/no mapped to fpga top. For example, there is a core port + * 'a[0:3]', while only 'a[0]' is mapped to the fpga top. We can use the port + * name find it quickly + */ + e_port_mapping_status fpga_core_port_mapping_status( + const BasicPort& fpga_core_port, const bool& verbose = false) const; + /** @brief Identify if there are any naming rules inside */ + bool empty() const; + + public: /* Public mutators */ + /** @brief Create the one-on-one mapping between an port of fpga_top and + * fpga_core. Return 0 for success, return 1 for fail */ + int set_io_pair(const BasicPort& fpga_top_port, + const BasicPort& fpga_core_port); + /** @brief Add a dummy port at the fpga top, which is not mapped any port at + * fpga_core */ + int set_dummy_io(const BasicPort& fpga_top_port, + const e_dummy_port_direction& direction); + + public: /* Public utility */ + /** @brief Parse the dummy port direction from string to valid type. Parser + * error can be turned on */ + e_dummy_port_direction str2dummy_port_dir(const std::string& dir_str, + const bool& verbose = false) const; + /** @brief Output the string representing dummy port direction */ + std::string dummy_port_dir2str(const e_dummy_port_direction& dir, + const bool& verbose = false) const; + /** @brief Validate the dummy port direction */ + bool valid_dummy_port_direction( + const e_dummy_port_direction& direction) const; + + private: /* Internal utility */ + /* Convert a port info to string, which can be used to store keys */ + std::string port2str(const BasicPort& port) const; + /* Convert a string to port, which can be used to echo internal info */ + BasicPort str2port(const std::string& port_str) const; + /* Generate a string include all the valid directions of the dummy port. + * Useful for printing debugging messages */ + std::string dummy_port_dir_all2str() const; + + private: /* Internal Data */ + /* fpga_top -> fpga_core io_name_keys. Use the port name to find all the port + * details. For instance: prog_clk -> ["prog_clk[0:1]", "prog_clk[2:3]"] The + * keys are then used to spot the fpga core ports in the io_name_map_. For + * instance: "prog_clk[0:1]" -> pclk[0:1] + */ + std::map> top2core_io_name_keys_; + std::map top2core_io_name_map_; + + std::map> core2top_io_name_keys_; + std::map core2top_io_name_map_; + + std::map dummy_port_direction_; + + /* Constants */ + std::array + DUMMY_PORT_DIR_STRING_; +}; + +} /* End namespace openfpga*/ + +#endif diff --git a/libs/libionamemap/src/io/io_name_map_xml_constants.h b/libs/libionamemap/src/io/io_name_map_xml_constants.h new file mode 100644 index 000000000..f7d7fe74e --- /dev/null +++ b/libs/libionamemap/src/io/io_name_map_xml_constants.h @@ -0,0 +1,17 @@ +#ifndef IO_NAME_MAP_XML_CONSTANTS_H +#define IO_NAME_MAP_XML_CONSTANTS_H + +/* Constants required by XML parser */ + +constexpr const char* XML_IO_NAME_MAP_ROOT_NAME = "ports"; +constexpr const char* XML_IO_NAME_MAP_NODE_NAME = "port"; +constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_TOP_NAME = "top_name"; +constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_CORE_NAME = "core_name"; +constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_IS_DUMMY = "is_dummy"; +constexpr const char* XML_IO_NAME_MAP_ATTRIBUTE_DIRECTION = "direction"; + +constexpr std::array + XML_IO_NAME_MAP_DUMMY_PORT_DIRECTION_STRING = { + {"input", "output", "inout"}}; // String versions of side orientations + +#endif diff --git a/libs/libionamemap/src/io/read_xml_io_name_map.cpp b/libs/libionamemap/src/io/read_xml_io_name_map.cpp new file mode 100644 index 000000000..4fc9f231a --- /dev/null +++ b/libs/libionamemap/src/io/read_xml_io_name_map.cpp @@ -0,0 +1,104 @@ +/******************************************************************** + * This file includes the top-level function of this library + * which reads an XML of clock network file to the associated + * data structures + *******************************************************************/ +#include + +/* Headers from pugi XML library */ +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from libopenfpga util library */ +#include "openfpga_port_parser.h" + +/* Headers from libarchfpga */ +#include "arch_error.h" +#include "command_exit_codes.h" +#include "io_name_map_xml_constants.h" +#include "read_xml_io_name_map.h" +#include "read_xml_util.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * Parse XML codes of a to an object of I/O naming + *******************************************************************/ +static int read_xml_io_map_port(pugi::xml_node& xml_port, + const pugiutil::loc_data& loc_data, + IoNameMap& io_name_map) { + /* Parse fpga top port information */ + std::string top_name = + get_attribute(xml_port, XML_IO_NAME_MAP_ATTRIBUTE_TOP_NAME, loc_data) + .as_string(); + BasicPort top_port = openfpga::PortParser(top_name).port(); + + /* For dummy port, create the dummy io */ + bool is_dummy = get_attribute(xml_port, XML_IO_NAME_MAP_ATTRIBUTE_IS_DUMMY, + loc_data, pugiutil::ReqOpt::OPTIONAL) + .as_bool(false); + if (is_dummy) { + std::string dir_str = + get_attribute(xml_port, XML_IO_NAME_MAP_ATTRIBUTE_DIRECTION, loc_data) + .as_string(); + IoNameMap::e_dummy_port_direction dummy_port_dir = + io_name_map.str2dummy_port_dir(dir_str, true); + if (!io_name_map.valid_dummy_port_direction(dummy_port_dir)) { + VTR_LOG_ERROR("Invalid direction for dummy port '%s'!\n", + top_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + return io_name_map.set_dummy_io(top_port, + dummy_port_dir); /* Early return */ + } + + /* This is not a dummy io, create the io mapping */ + std::string core_name = + get_attribute(xml_port, XML_IO_NAME_MAP_ATTRIBUTE_CORE_NAME, loc_data) + .as_string(); + BasicPort core_port = openfpga::PortParser(core_name).port(); + + return io_name_map.set_io_pair(top_port, core_port); +} + +/******************************************************************** + * Parse XML codes about to an object of ClockNetwork + *******************************************************************/ +int read_xml_io_name_map(const char* fname, IoNameMap& io_name_map) { + vtr::ScopedStartFinishTimer timer("Read I/O naming rules"); + + int status = CMD_EXEC_SUCCESS; + + /* Parse the file */ + pugi::xml_document doc; + pugiutil::loc_data loc_data; + + try { + loc_data = pugiutil::load_xml(doc, fname); + + pugi::xml_node xml_root = + get_single_child(doc, XML_IO_NAME_MAP_ROOT_NAME, loc_data); + + for (pugi::xml_node xml_port : xml_root.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_port.name() != std::string(XML_IO_NAME_MAP_NODE_NAME)) { + bad_tag(xml_port, loc_data, xml_root, {XML_IO_NAME_MAP_NODE_NAME}); + } + status = read_xml_io_map_port(xml_port, loc_data, io_name_map); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + } catch (pugiutil::XmlError& e) { + archfpga_throw(fname, e.line(), "%s", e.what()); + } + + return status; +} + +} // End of namespace openfpga diff --git a/libs/libionamemap/src/io/read_xml_io_name_map.h b/libs/libionamemap/src/io/read_xml_io_name_map.h new file mode 100644 index 000000000..5fc441a84 --- /dev/null +++ b/libs/libionamemap/src/io/read_xml_io_name_map.h @@ -0,0 +1,21 @@ +#ifndef READ_XML_IO_NAME_MAP_H +#define READ_XML_IO_NAME_MAP_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "io_name_map.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +namespace openfpga { // Begin namespace openfpga + +int read_xml_io_name_map(const char* fname, IoNameMap& io_name_map); + +} // End of namespace openfpga + +#endif diff --git a/libs/libionamemap/src/io/write_xml_io_name_map.cpp b/libs/libionamemap/src/io/write_xml_io_name_map.cpp new file mode 100644 index 000000000..2b52f7a23 --- /dev/null +++ b/libs/libionamemap/src/io/write_xml_io_name_map.cpp @@ -0,0 +1,106 @@ +/******************************************************************** + * This file includes functions that outputs a clock network object to XML + *format + *******************************************************************/ +/* Headers from system goes first */ +#include +#include + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpga util library */ +#include "openfpga_digest.h" + +/* Headers from arch openfpga library */ +#include "write_xml_utils.h" + +/* Headers from pin constraint library */ +#include "io_name_map_xml_constants.h" +#include "write_xml_io_name_map.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * A writer to output a I/O name mapping to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +static int write_xml_io_map_port(std::fstream& fp, const IoNameMap& io_name_map, + const BasicPort& fpga_top_port) { + /* Validate the file stream */ + if (false == openfpga::valid_file_stream(fp)) { + return 2; + } + + openfpga::write_tab_to_file(fp, 1); + fp << "<" << XML_IO_NAME_MAP_NODE_NAME << ""; + write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_TOP_NAME, + generate_xml_port_name(fpga_top_port).c_str()); + + if (io_name_map.fpga_top_port_is_dummy(fpga_top_port)) { + write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_IS_DUMMY, "true"); + IoNameMap::e_dummy_port_direction dir = + io_name_map.fpga_top_dummy_port_direction(fpga_top_port); + write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_DIRECTION, + io_name_map.dummy_port_dir2str(dir, true).c_str()); + } else { + BasicPort fpga_core_port = io_name_map.fpga_core_port(fpga_top_port); + write_xml_attribute(fp, XML_IO_NAME_MAP_ATTRIBUTE_CORE_NAME, + generate_xml_port_name(fpga_core_port).c_str()); + } + fp << ">" + << "\n"; + + return 0; +} + +/******************************************************************** + * A writer to output an object to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +int write_xml_io_name_map(const char* fname, const IoNameMap& io_name_map) { + vtr::ScopedStartFinishTimer timer("Write I/O naming rules"); + + /* Create a file handler */ + std::fstream fp; + /* Open the file stream */ + fp.open(std::string(fname), std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Write the root node */ + fp << "<" << XML_IO_NAME_MAP_ROOT_NAME; + fp << ">" + << "\n"; + + int err_code = 0; + + /* Write each port */ + for (BasicPort fpga_top_port : io_name_map.fpga_top_ports()) { + /* Write bus */ + err_code = write_xml_io_map_port(fp, io_name_map, fpga_top_port); + if (0 != err_code) { + return err_code; + } + } + + /* Finish writing the root node */ + fp << "" + << "\n"; + + /* Close the file stream */ + fp.close(); + + return err_code; +} + +} // End of namespace openfpga diff --git a/libs/libionamemap/src/io/write_xml_io_name_map.h b/libs/libionamemap/src/io/write_xml_io_name_map.h new file mode 100644 index 000000000..b51064fd9 --- /dev/null +++ b/libs/libionamemap/src/io/write_xml_io_name_map.h @@ -0,0 +1,20 @@ +#ifndef WRITE_XML_IO_NAME_MAP_H +#define WRITE_XML_IO_NAME_MAP_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "io_name_map.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +namespace openfpga { // Begin namespace openfpga + +int write_xml_io_name_map(const char* fname, const IoNameMap& io_name_map); + +} // End of namespace openfpga + +#endif diff --git a/libs/libionamemap/test/xml_io_io_name_map.cpp b/libs/libionamemap/test/xml_io_io_name_map.cpp new file mode 100644 index 000000000..9140bdc13 --- /dev/null +++ b/libs/libionamemap/test/xml_io_io_name_map.cpp @@ -0,0 +1,38 @@ +/******************************************************************** + * Unit test functions to validate the correctness of + * 1. parser of data structures + * 2. writer of data structures + *******************************************************************/ +/* Headers from vtrutils */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from readarchopenfpga */ +#include "read_xml_io_name_map.h" +#include "write_xml_io_name_map.h" + +int main(int argc, const char** argv) { + /* Ensure we have only one or two argument */ + VTR_ASSERT((2 == argc) || (3 == argc)); + + int status = 0; + + /* Parse the circuit library from an XML file */ + openfpga::IoNameMap io_name_map; + status = openfpga::read_xml_io_name_map(argv[1], io_name_map); + if (status != 0) { + return status; + } + VTR_LOG("Parsed %lu fpga top ports from XML.\n", + io_name_map.fpga_top_ports().size()); + + /* Output the bus group to an XML file + * This is optional only used when there is a second argument + */ + if (3 <= argc) { + status = openfpga::write_xml_io_name_map(argv[2], io_name_map); + VTR_LOG("Write the I/O name mapping to an XML file: %s.\n", argv[2]); + } + + return status; +} diff --git a/libs/libopenfpgautil/src/openfpga_decode.cpp b/libs/libopenfpgautil/src/openfpga_decode.cpp index 988bec456..30aa2d128 100644 --- a/libs/libopenfpgautil/src/openfpga_decode.cpp +++ b/libs/libopenfpgautil/src/openfpga_decode.cpp @@ -2,10 +2,10 @@ * This file includes functions that are used to decode integer to binary *vectors or the reverse operation ***************************************************************************************/ -#include /* Headers from vtrutil library */ #include "openfpga_decode.h" + #include "vtr_assert.h" /* begin namespace openfpga */ @@ -109,12 +109,28 @@ std::string combine_two_1hot_str(const std::string& code1, * Output: * index | 0 | 1 | 2 * ret | 0 | 0 | 1 + * + * ToDo: Need to revisit and change all the feature that call to this function + * Had studied the code, should be safe to make the change + * Apparently we only want to store 0 or 1 (binary vector) + * Yet we store it in a vector on size_t (8 Bytes) + * We are using 8x memory that we supposed to + * uint8_t is good enough + * Not a bug, but is a serious unoptimized issue ********************************************************************/ std::vector itobin_vec(const size_t& in_int, const size_t& bin_len) { + /* bin_len must be in valid range*/ + VTR_ASSERT(bin_len > 0 && bin_len <= 64); std::vector ret(bin_len, 0); /* Make sure we do not have any overflow! */ - VTR_ASSERT((in_int < pow(2., bin_len))); + /* If the length is 64 bits, in_int can be any number since this is the max + bit length, and BTW pow(2, 64) itself should be zero (from 64bits size_t + perspective). Once we fix the bintoi_charvec() bug, without this change, it + will cause assertion */ + if (bin_len < 64) { + VTR_ASSERT(in_int < (size_t(1) << bin_len)); + } size_t temp = in_int; for (size_t i = 0; i < bin_len; i++) { @@ -140,10 +156,18 @@ std::vector itobin_vec(const size_t& in_int, const size_t& bin_len) { * which has a smaller memory footprint than size_t ********************************************************************/ std::vector itobin_charvec(const size_t& in_int, const size_t& bin_len) { + /* bin_len must be in valid range*/ + VTR_ASSERT(bin_len > 0 && bin_len <= 64); std::vector ret(bin_len, '0'); /* Make sure we do not have any overflow! */ - VTR_ASSERT((in_int < pow(2., bin_len))); + /* If the length is 64 bits, in_int can be any number since this is the max + bit length, and BTW pow(2, 64) itself should be zero (from 64bits size_t + perspective). Once we fix the bintoi_charvec() bug, without this change, it + will cause assertion */ + if (bin_len < 64) { + VTR_ASSERT(in_int < (size_t(1) << bin_len)); + } size_t temp = in_int; for (size_t i = 0; i < bin_len; i++) { @@ -170,11 +194,14 @@ std::vector itobin_charvec(const size_t& in_int, const size_t& bin_len) { * which has a smaller memory footprint than size_t ********************************************************************/ size_t bintoi_charvec(const std::vector& bin) { + /* bin.size() must be in valid range*/ + VTR_ASSERT(bin.size() > 0 && bin.size() <= 64); + size_t ret = 0; for (size_t i = 0; i < bin.size(); ++i) { if ('1' == bin[i]) { - ret += pow(2., i); + ret |= ((size_t)(1) << i); } } diff --git a/libs/libopenfpgautil/src/openfpga_port.cpp b/libs/libopenfpgautil/src/openfpga_port.cpp index 2ca18f27e..cb42393ca 100644 --- a/libs/libopenfpgautil/src/openfpga_port.cpp +++ b/libs/libopenfpgautil/src/openfpga_port.cpp @@ -111,6 +111,25 @@ std::string BasicPort::to_verilog_string() const { std::to_string(get_msb()) + "]"; } +size_t BasicPort::find_ipin(const BasicPort& ref_port) const { + /* Port name should match first */ + if (!this->mergeable(ref_port)) { + return get_width(); /* Name does not match, no need to find the pin index, + return an invalid range */ + } + /* it should be only a pin (width = 1) */ + if (!ref_port.is_valid() || ref_port.get_width() != 1) { + return get_width(); /* Return an invalid range */ + } + /* Must cache the pin list otherwise the begin() and end() are not constant */ + auto pin_list = pins(); + auto it = std::find(pin_list.begin(), pin_list.end(), ref_port.get_lsb()); + if (it == pin_list.end()) { + return get_width(); /* Out of range, return an invalid range */ + } + return it - pin_list.begin(); +} + /************************************************************************ * Overloaded operators ***********************************************************************/ diff --git a/libs/libopenfpgautil/src/openfpga_port.h b/libs/libopenfpgautil/src/openfpga_port.h index 013a74b7b..be86334b5 100644 --- a/libs/libopenfpgautil/src/openfpga_port.h +++ b/libs/libopenfpgautil/src/openfpga_port.h @@ -37,6 +37,10 @@ class BasicPort { size_t get_origin_port_width() const; std::string to_verilog_string() const; /* Generate verilog-style string, e.g., a[0:1] */ + /** @brief Find the index of the pin in the reference port w.r.t. to this + * port. For example, given a reference pin 'a[1]', this port is 'a[0:2]', the + * pin is the second pin in the port. As a result, the index will be 1. */ + size_t find_ipin(const BasicPort& ref_port) const; public: /* Mutators */ void set(const BasicPort& basic_port); /* copy */ diff --git a/libs/libopenfpgautil/src/openfpga_reserved_words.h b/libs/libopenfpgautil/src/openfpga_reserved_words.h index 05d1e2d2e..3317b12ff 100644 --- a/libs/libopenfpgautil/src/openfpga_reserved_words.h +++ b/libs/libopenfpgautil/src/openfpga_reserved_words.h @@ -12,6 +12,8 @@ namespace openfpga { /* Top-level module name */ constexpr const char* FPGA_TOP_MODULE_NAME = "fpga_top"; +constexpr const char* FPGA_CORE_MODULE_NAME = "fpga_core"; +constexpr const char* FPGA_CORE_INSTANCE_NAME = "fpga_instance"; /* Configuration chain naming constant strings */ constexpr const char* CONFIGURABLE_MEMORY_CHAIN_IN_NAME = "ccff_head"; @@ -39,6 +41,11 @@ constexpr const char* GRID_MEM_INSTANCE_PREFIX = "mem_"; constexpr const char* SWITCH_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; constexpr const char* CONNECTION_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; constexpr const char* MEMORY_MODULE_POSTFIX = "_mem"; +constexpr const char* MEMORY_FEEDTHROUGH_MODULE_POSTFIX = "_feedthrough_mem"; +constexpr const char* MEMORY_FEEDTHROUGH_DATA_IN_PORT_NAME = + "feedthrough_mem_in"; +constexpr const char* MEMORY_FEEDTHROUGH_DATA_IN_INV_PORT_NAME = + "feedthrough_mem_inb"; constexpr const char* MEMORY_BL_PORT_NAME = "bl"; constexpr const char* MEMORY_WL_PORT_NAME = "wl"; constexpr const char* MEMORY_WLR_PORT_NAME = "wlr"; @@ -66,6 +73,7 @@ constexpr const char* INV_PORT_POSTFIX = "_inv"; /* Bitstream file strings */ constexpr const char* BITSTREAM_XML_FILE_NAME_POSTFIX = "_bitstream.xml"; +constexpr const char* DEFAULT_TILE_DIR_NAME = "tile/"; constexpr const char* DEFAULT_LB_DIR_NAME = "lb/"; constexpr const char* DEFAULT_RR_DIR_NAME = "routing/"; constexpr const char* DEFAULT_SUBMODULE_DIR_NAME = "sub_module/"; diff --git a/libs/libtileconfig/CMakeLists.txt b/libs/libtileconfig/CMakeLists.txt new file mode 100644 index 000000000..96d2da1d2 --- /dev/null +++ b/libs/libtileconfig/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.9) + +project("libtileconfig") + +file(GLOB_RECURSE EXEC_SOURCES test/*.cpp) +file(GLOB_RECURSE LIB_SOURCES src/*/*.cpp) +file(GLOB_RECURSE LIB_HEADERS src/*/*.h) +files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS) + +#Remove test executable from library +list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES}) + +#Create the library +add_library(libtileconfig STATIC + ${LIB_HEADERS} + ${LIB_SOURCES}) +target_include_directories(libtileconfig PUBLIC ${LIB_INCLUDE_DIRS}) +set_target_properties(libtileconfig PROPERTIES PREFIX "") #Avoid extra 'lib' prefix + +#Specify link-time dependancies +target_link_libraries(libtileconfig + libarchopenfpga + libopenfpgautil + libopenfpgashell + libvtrutil + libpugiutil) + +#Create the test executable +foreach(testsourcefile ${EXEC_SOURCES}) + # Use a simple string replace, to cut off .cpp. + get_filename_component(testname ${testsourcefile} NAME_WE) + add_executable(${testname} ${testsourcefile}) + # Make sure the library is linked to each test executable + target_link_libraries(${testname} libtileconfig) +endforeach(testsourcefile ${EXEC_SOURCES}) + +install(TARGETS libtileconfig DESTINATION bin) diff --git a/libs/libtileconfig/example/tile_config_example.xml b/libs/libtileconfig/example/tile_config_example.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/libs/libtileconfig/example/tile_config_example.xml @@ -0,0 +1 @@ + diff --git a/libs/libtileconfig/src/base/tile_config.cpp b/libs/libtileconfig/src/base/tile_config.cpp new file mode 100644 index 000000000..49fa8e52f --- /dev/null +++ b/libs/libtileconfig/src/base/tile_config.cpp @@ -0,0 +1,76 @@ +/****************************************************************************** + * Memember functions for data structure TileConfig + ******************************************************************************/ +#include "tile_config.h" + +#include + +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* begin namespace openfpga */ +namespace openfpga { + +TileConfig::TileConfig() { + style_ = TileConfig::e_style::NUM_TYPES; /* Deposit an invalid value */ + STYLE_STRING_ = {"top_left", "top_right", "bottom_left", "bottom_right", + "custom"}; +} + +/************************************************** + * Public Accessors + *************************************************/ +TileConfig::e_style TileConfig::style() const { return style_; } + +std::string TileConfig::style_to_string() const { return style2str(style_); } + +bool TileConfig::is_valid() const { + return style_ != TileConfig::e_style::NUM_TYPES; +} + +int TileConfig::set_style(const std::string& value) { + style_ = str2style(value); + return valid_style(style_); +} + +std::string TileConfig::style_all2str() const { + std::string full_types = "["; + for (int itype = size_t(TileConfig::e_style::TOP_LEFT); + itype != size_t(TileConfig::e_style::NUM_TYPES); ++itype) { + full_types += std::string(STYLE_STRING_[itype]) + std::string("|"); + } + full_types.pop_back(); + full_types += "]"; + return full_types; +} + +TileConfig::e_style TileConfig::str2style(const std::string& style_str, + const bool& verbose) const { + for (int itype = size_t(TileConfig::e_style::TOP_LEFT); + itype != size_t(TileConfig::e_style::NUM_TYPES); ++itype) { + if (style_str == std::string(STYLE_STRING_[itype])) { + return static_cast(itype); + } + } + VTR_LOGV_ERROR(verbose, "Invalid style for tile configuration! Expect %s\n", + style_all2str().c_str()); + return TileConfig::e_style::NUM_TYPES; +} + +std::string TileConfig::style2str(const TileConfig::e_style& style, + const bool& verbose) const { + if (!valid_style(style)) { + VTR_LOGV_ERROR(verbose, "Invalid style for tile configuration! Expect %s\n", + style_all2str().c_str()); + return std::string(); + } + return std::string(STYLE_STRING_[size_t(style)]); +} + +bool TileConfig::valid_style(const TileConfig::e_style& style) const { + return style != TileConfig::e_style::NUM_TYPES; +} + +} /* end namespace openfpga */ diff --git a/libs/libtileconfig/src/base/tile_config.h b/libs/libtileconfig/src/base/tile_config.h new file mode 100644 index 000000000..41dd8acd9 --- /dev/null +++ b/libs/libtileconfig/src/base/tile_config.h @@ -0,0 +1,67 @@ +#ifndef TILE_CONFIG_H +#define TILE_CONFIG_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include +#include + +/* Begin namespace openfpga */ +namespace openfpga { + +/** + * @brief tile configuration is a data structure to represent how programmable + * blocks and routing blocks are grouped into tiles + */ +class TileConfig { + public: /* Types */ + enum class e_style { + TOP_LEFT = 0, + TOP_RIGHT, + BOTTOM_LEFT, + BOTTOM_RIGHT, + CUSTOM, + NUM_TYPES + }; + + public: /* Constructors */ + TileConfig(); + + public: /* Public accessors */ + /** @brief Get all the fpga style */ + e_style style() const; + std::string style_to_string() const; + + public: /* Public mutators */ + /** @brief Create the one-on-one mapping between an port of fpga_top and + * fpga_core. Return 0 for success, return 1 for fail */ + int set_style(const std::string& value); + + public: /* Public utility */ + /** @brief identify if the tile config is valid or not */ + bool is_valid() const; + /** @brief Parse the style from string to valid type. Parser + * error can be turned on */ + e_style str2style(const std::string& style_str, + const bool& verbose = false) const; + /** @brief Output the string representing style */ + std::string style2str(const e_style& style, + const bool& verbose = false) const; + /** @brief Validate the style */ + bool valid_style(const e_style& style) const; + + private: /* Internal utility */ + /* Generate a string include all the valid style + * Useful for printing debugging messages */ + std::string style_all2str() const; + + private: /* Internal Data */ + e_style style_; + /* Constants */ + std::array STYLE_STRING_; +}; + +} /* End namespace openfpga*/ + +#endif diff --git a/libs/libtileconfig/src/io/read_xml_tile_config.cpp b/libs/libtileconfig/src/io/read_xml_tile_config.cpp new file mode 100644 index 000000000..f332f5688 --- /dev/null +++ b/libs/libtileconfig/src/io/read_xml_tile_config.cpp @@ -0,0 +1,55 @@ +/******************************************************************** + * This file includes the top-level function of this library + * which reads an XML of clock network file to the associated + * data structures + *******************************************************************/ +#include + +/* Headers from pugi XML library */ +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from libarchfpga */ +#include "arch_error.h" +#include "command_exit_codes.h" +#include "read_xml_tile_config.h" +#include "read_xml_util.h" +#include "tile_config_xml_constants.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * Parse XML codes about to an object of ClockNetwork + *******************************************************************/ +int read_xml_tile_config(const char* fname, TileConfig& tile_config) { + vtr::ScopedStartFinishTimer timer("Read tile configuration rules"); + + int status = CMD_EXEC_SUCCESS; + + /* Parse the file */ + pugi::xml_document doc; + pugiutil::loc_data loc_data; + + try { + loc_data = pugiutil::load_xml(doc, fname); + + pugi::xml_node xml_root = + get_single_child(doc, XML_TILE_CONFIG_ROOT_NAME, loc_data); + + std::string style = + get_attribute(xml_root, XML_TILE_CONFIG_ATTRIBUTE_STYLE_NAME, loc_data) + .as_string(); + tile_config.set_style(style); + } catch (pugiutil::XmlError& e) { + archfpga_throw(fname, e.line(), "%s", e.what()); + } + + return status; +} + +} // End of namespace openfpga diff --git a/libs/libtileconfig/src/io/read_xml_tile_config.h b/libs/libtileconfig/src/io/read_xml_tile_config.h new file mode 100644 index 000000000..7e80f612e --- /dev/null +++ b/libs/libtileconfig/src/io/read_xml_tile_config.h @@ -0,0 +1,21 @@ +#ifndef READ_XML_TILE_CONFIG_H +#define READ_XML_TILE_CONFIG_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "pugixml.hpp" +#include "pugixml_util.hpp" +#include "tile_config.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +namespace openfpga { // Begin namespace openfpga + +int read_xml_tile_config(const char* fname, TileConfig& tile_config); + +} // End of namespace openfpga + +#endif diff --git a/libs/libtileconfig/src/io/tile_config_xml_constants.h b/libs/libtileconfig/src/io/tile_config_xml_constants.h new file mode 100644 index 000000000..583aa8d3c --- /dev/null +++ b/libs/libtileconfig/src/io/tile_config_xml_constants.h @@ -0,0 +1,8 @@ +#ifndef TILE_CONFIG_XML_CONSTANTS_H +#define TILE_CONFIG_XML_CONSTANTS_H + +/* Constants required by XML parser */ +constexpr const char* XML_TILE_CONFIG_ROOT_NAME = "tiles"; +constexpr const char* XML_TILE_CONFIG_ATTRIBUTE_STYLE_NAME = "style"; + +#endif diff --git a/libs/libtileconfig/src/io/write_xml_tile_config.cpp b/libs/libtileconfig/src/io/write_xml_tile_config.cpp new file mode 100644 index 000000000..48e1254df --- /dev/null +++ b/libs/libtileconfig/src/io/write_xml_tile_config.cpp @@ -0,0 +1,59 @@ +/******************************************************************** + * This file includes functions that outputs a clock network object to XML + *format + *******************************************************************/ +/* Headers from system goes first */ +#include +#include + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from arch openfpga library */ +#include "openfpga_digest.h" +#include "write_xml_utils.h" + +/* Headers from pin constraint library */ +#include "tile_config_xml_constants.h" +#include "write_xml_tile_config.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * A writer to output an object to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +int write_xml_tile_config(const char* fname, const TileConfig& tile_config) { + vtr::ScopedStartFinishTimer timer("Write tile configuration rules"); + + /* Create a file handler */ + std::fstream fp; + /* Open the file stream */ + fp.open(std::string(fname), std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + int err_code = 0; + + /* Write the root node */ + fp << "<" << XML_TILE_CONFIG_ROOT_NAME; + + write_xml_attribute(fp, XML_TILE_CONFIG_ATTRIBUTE_STYLE_NAME, + tile_config.style_to_string().c_str()); + /* Finish writing the root node */ + fp << "/>" + << "\n"; + + /* Close the file stream */ + fp.close(); + + return err_code; +} + +} // End of namespace openfpga diff --git a/libs/libtileconfig/src/io/write_xml_tile_config.h b/libs/libtileconfig/src/io/write_xml_tile_config.h new file mode 100644 index 000000000..f0456db38 --- /dev/null +++ b/libs/libtileconfig/src/io/write_xml_tile_config.h @@ -0,0 +1,20 @@ +#ifndef WRITE_XML_TILE_CONFIG_H +#define WRITE_XML_TILE_CONFIG_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "tile_config.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +namespace openfpga { // Begin namespace openfpga + +int write_xml_tile_config(const char* fname, const TileConfig& tile_config); + +} // End of namespace openfpga + +#endif diff --git a/libs/libtileconfig/test/xml_io_tile_config.cpp b/libs/libtileconfig/test/xml_io_tile_config.cpp new file mode 100644 index 000000000..bd4a15c9d --- /dev/null +++ b/libs/libtileconfig/test/xml_io_tile_config.cpp @@ -0,0 +1,37 @@ +/******************************************************************** + * Unit test functions to validate the correctness of + * 1. parser of data structures + * 2. writer of data structures + *******************************************************************/ +/* Headers from vtrutils */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from readarchopenfpga */ +#include "read_xml_tile_config.h" +#include "write_xml_tile_config.h" + +int main(int argc, const char** argv) { + /* Ensure we have only one or two argument */ + VTR_ASSERT((2 == argc) || (3 == argc)); + + int status = 0; + + /* Parse the circuit library from an XML file */ + openfpga::TileConfig tile_config; + status = openfpga::read_xml_tile_config(argv[1], tile_config); + if (status != 0) { + return status; + } + VTR_LOG("Parsed tile configuration from XML file: %s\n", argv[1]); + + /* Output the bus group to an XML file + * This is optional only used when there is a second argument + */ + if (3 <= argc) { + status = openfpga::write_xml_tile_config(argv[2], tile_config); + VTR_LOG("Write the tile configuration to an XML file: %s.\n", argv[2]); + } + + return status; +} diff --git a/openfpga.sh b/openfpga.sh index f02783f1c..39ef65a29 100755 --- a/openfpga.sh +++ b/openfpga.sh @@ -133,7 +133,7 @@ goto-task () { done } -# Clears enviroment variables and fucntions +# Clears environment variables and functions unset-openfpga (){ unset -v OPENFPGA_PATH unset -f list-tasks run-task run-flow goto-task goto-root >/dev/null 2>&1 diff --git a/openfpga/CMakeLists.txt b/openfpga/CMakeLists.txt index 31a4e37b9..bea2fa94d 100644 --- a/openfpga/CMakeLists.txt +++ b/openfpga/CMakeLists.txt @@ -41,6 +41,8 @@ target_link_libraries(libopenfpga libpcf libvtrutil libbusgroup + libionamemap + libtileconfig libpugixml libvpr) diff --git a/openfpga/src/annotation/annotate_rr_graph.cpp b/openfpga/src/annotation/annotate_rr_graph.cpp index 84a994577..3a904aefd 100644 --- a/openfpga/src/annotation/annotate_rr_graph.cpp +++ b/openfpga/src/annotation/annotate_rr_graph.cpp @@ -21,7 +21,7 @@ namespace openfpga { /* Build a RRChan Object with the given channel type and coorindators */ static RRChan build_one_rr_chan(const DeviceContext& vpr_device_ctx, - const t_rr_type& chan_type, + const t_rr_type& chan_type, const size_t& layer, vtr::Point& chan_coord) { std::vector chan_rr_nodes; @@ -32,7 +32,7 @@ static RRChan build_one_rr_chan(const DeviceContext& vpr_device_ctx, /* Collect rr_nodes for this channel */ chan_rr_nodes = find_rr_graph_chan_nodes( - vpr_device_ctx.rr_graph, chan_coord.x(), chan_coord.y(), chan_type); + vpr_device_ctx.rr_graph, layer, chan_coord.x(), chan_coord.y(), chan_type); /* Fill the rr_chan */ for (const RRNodeId& chan_rr_node : chan_rr_nodes) { rr_chan.add_node(vpr_device_ctx.rr_graph, chan_rr_node, @@ -96,6 +96,7 @@ static RRChan build_one_rr_chan(const DeviceContext& vpr_device_ctx, */ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, const vtr::Point& gsb_range, + const size_t& layer, const vtr::Point& gsb_coord, const bool& include_clock) { /* Create an object to return */ @@ -133,7 +134,7 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, /* Routing channels*/ /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, coordinate); + rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, layer, coordinate); chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ chan_dir_to_port_dir_mapping[1] = @@ -147,12 +148,12 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, opin_grid_side[1] = LEFT; /* Include Grid[x][y+1] RIGHT side outputs pins */ temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes( - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x(), + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, layer, gsb_coord.x(), gsb_coord.y() + 1, OPIN, opin_grid_side[0]); /* Include Grid[x+1][y+1] Left side output pins */ temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes( - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x() + 1, - gsb_coord.y() + 1, OPIN, opin_grid_side[1]); + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, layer, + gsb_coord.x() + 1, gsb_coord.y() + 1, OPIN, opin_grid_side[1]); break; case RIGHT: /* RIGHT = 1 */ @@ -165,7 +166,7 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ /* Collect rr_nodes for Tracks for top: chany[x][y+1] */ /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, coordinate); + rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, layer, coordinate); chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */ chan_dir_to_port_dir_mapping[1] = @@ -180,12 +181,12 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, /* include Grid[x+1][y+1] Bottom side output pins */ temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes( - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x() + 1, - gsb_coord.y() + 1, OPIN, opin_grid_side[0]); + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, layer, + gsb_coord.x() + 1, gsb_coord.y() + 1, OPIN, opin_grid_side[0]); /* include Grid[x+1][y] Top side output pins */ temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes( - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x() + 1, - gsb_coord.y(), OPIN, opin_grid_side[1]); + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, layer, + gsb_coord.x() + 1, gsb_coord.y(), OPIN, opin_grid_side[1]); break; case BOTTOM: /* BOTTOM = 2*/ /* For the border, we should take special care */ @@ -197,7 +198,7 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ /* Collect rr_nodes for Tracks for bottom: chany[x][y] */ /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, coordinate); + rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, layer, coordinate); chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ chan_dir_to_port_dir_mapping[1] = @@ -211,11 +212,11 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, opin_grid_side[1] = RIGHT; /* include Grid[x+1][y] Left side output pins */ temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes( - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x() + 1, - gsb_coord.y(), OPIN, opin_grid_side[0]); + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, layer, + gsb_coord.x() + 1, gsb_coord.y(), OPIN, opin_grid_side[0]); /* include Grid[x][y] Right side output pins */ temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes( - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x(), + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, layer, gsb_coord.x(), gsb_coord.y(), OPIN, opin_grid_side[1]); break; case LEFT: /* LEFT = 3 */ @@ -228,7 +229,7 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, /* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */ /* Collect rr_nodes for Tracks for left: chanx[x][y] */ /* Create a rr_chan object and check if it is unique in the graph */ - rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, coordinate); + rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, layer, coordinate); chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */ chan_dir_to_port_dir_mapping[1] = @@ -241,11 +242,11 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, opin_grid_side[1] = TOP; /* include Grid[x][y+1] Bottom side outputs pins */ temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes( - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x(), + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, layer, gsb_coord.x(), gsb_coord.y() + 1, OPIN, opin_grid_side[0]); /* include Grid[x][y] Top side output pins */ temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes( - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, gsb_coord.x(), + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, layer, gsb_coord.x(), gsb_coord.y(), OPIN, opin_grid_side[1]); break; default: @@ -369,9 +370,9 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx, continue; } /* Collect IPIN rr_nodes*/ - temp_ipin_rr_nodes = - find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid, ix, - iy, IPIN, ipin_rr_node_grid_side, include_clock); + temp_ipin_rr_nodes = find_rr_graph_grid_nodes( + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, layer, ix, iy, IPIN, + ipin_rr_node_grid_side, include_clock); /* Fill the ipin nodes of RRGSB */ for (const RRNodeId& inode : temp_ipin_rr_nodes) { /* Skip those has no configurable outgoing, they should NOT appear in the @@ -422,6 +423,7 @@ void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, gsb_range.x(), gsb_range.y()); size_t gsb_cnt = 0; + size_t layer = 0; /* For each switch block, determine the size of array */ for (size_t ix = 0; ix < gsb_range.x(); ++ix) { for (size_t iy = 0; iy < gsb_range.y(); ++iy) { @@ -433,8 +435,7 @@ void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx, build_rr_gsb(vpr_device_ctx, vtr::Point(vpr_device_ctx.grid.width() - 2, vpr_device_ctx.grid.height() - 2), - vtr::Point(ix, iy), include_clock); - + layer, vtr::Point(ix, iy), include_clock); /* Add to device_rr_gsb */ vtr::Point gsb_coordinate = rr_gsb.get_sb_coordinate(); device_rr_gsb.add_rr_gsb(gsb_coordinate, rr_gsb); diff --git a/openfpga/src/annotation/annotate_simulation_setting.cpp b/openfpga/src/annotation/annotate_simulation_setting.cpp index 3c3c7b3ee..40056f51c 100644 --- a/openfpga/src/annotation/annotate_simulation_setting.cpp +++ b/openfpga/src/annotation/annotate_simulation_setting.cpp @@ -15,8 +15,8 @@ /* Headers from vpr library */ #include "AnalysisDelayCalculator.h" #include "annotate_simulation_setting.h" +#include "concrete_timing_info.h" #include "net_delay.h" -#include "timing_info.h" /* begin namespace openfpga */ namespace openfpga { @@ -212,7 +212,7 @@ int annotate_simulation_setting( make_net_pins_matrix((const Netlist<>&)cluster_ctx.clb_nlist); /* Load the net delays */ load_net_delay_from_routing((const Netlist<>&)cluster_ctx.clb_nlist, - net_delay, false); + net_delay); /* Do final timing analysis */ auto analysis_delay_calc = std::make_shared( diff --git a/openfpga/src/annotation/append_clock_rr_graph.cpp b/openfpga/src/annotation/append_clock_rr_graph.cpp index e59f19398..a52a86ed2 100644 --- a/openfpga/src/annotation/append_clock_rr_graph.cpp +++ b/openfpga/src/annotation/append_clock_rr_graph.cpp @@ -44,6 +44,7 @@ static size_t estimate_clock_rr_graph_num_chan_nodes( * Note that switch blocks do not require any new nodes but new edges *******************************************************************/ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, + const size_t& layer, const bool& through_channel, const ClockNetwork& clk_ntwk) { size_t num_nodes = 0; @@ -54,7 +55,7 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, /* Bypass if the routing channel does not exist when through channels are * not allowed */ if ((false == through_channel) && - (false == is_chanx_exist(grids, chanx_coord))) { + (false == is_chanx_exist(grids, layer, chanx_coord))) { continue; } /* Estimate the routing tracks required by clock routing only */ @@ -68,7 +69,7 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, /* Bypass if the routing channel does not exist when through channel are * not allowed */ if ((false == through_channel) && - (false == is_chany_exist(grids, chany_coord))) { + (false == is_chany_exist(grids, layer, chany_coord))) { continue; } /* Estimate the routing tracks required by clock routing only */ @@ -87,11 +88,12 @@ static size_t estimate_clock_rr_graph_num_nodes(const DeviceGrid& grids, static void add_rr_graph_block_clock_nodes( RRGraphBuilder& rr_graph_builder, RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, const ClockNetwork& clk_ntwk, - const vtr::Point chan_coord, const t_rr_type& chan_type, - const int& cost_index_offset, const bool& verbose) { + const size_t& layer, const vtr::Point chan_coord, + const t_rr_type& chan_type, const int& cost_index_offset, + const bool& verbose) { size_t orig_chan_width = rr_graph_view.node_lookup() - .find_channel_nodes(chan_coord.x(), chan_coord.y(), chan_type) + .find_channel_nodes(layer, chan_coord.x(), chan_coord.y(), chan_type) .size(); size_t curr_node_ptc = orig_chan_width; @@ -115,9 +117,10 @@ static void add_rr_graph_block_clock_nodes( for (size_t ipin = 0; ipin < num_pins / 2; ++ipin) { for (auto node_dir : {Direction::INC, Direction::DEC}) { RRNodeId clk_node = rr_graph_builder.create_node( - chan_coord.x(), chan_coord.y(), chan_type, curr_node_ptc); + layer, chan_coord.x(), chan_coord.y(), chan_type, curr_node_ptc); rr_graph_builder.set_node_direction(clk_node, node_dir); rr_graph_builder.set_node_capacity(clk_node, 1); + rr_graph_builder.set_node_layer(clk_node, layer); /* set cost_index using segment id */ rr_graph_builder.set_node_cost_index( clk_node, RRIndexedDataId(cost_index_offset + @@ -145,13 +148,11 @@ static void add_rr_graph_block_clock_nodes( * Add clock nodes one by one to the routing resource graph. * Assign node-level attributes properly and register in dedicated lookup *******************************************************************/ -static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, - RRClockSpatialLookup& clk_rr_lookup, - const RRGraphView& rr_graph_view, - const DeviceGrid& grids, - const bool& through_channel, - const ClockNetwork& clk_ntwk, - const bool& verbose) { +static void add_rr_graph_clock_nodes( + RRGraphBuilder& rr_graph_builder, RRClockSpatialLookup& clk_rr_lookup, + const RRGraphView& rr_graph_view, const DeviceGrid& grids, + const size_t& layer, const bool& through_channel, + const ClockNetwork& clk_ntwk, const bool& verbose) { /* Pre-allocate memory: Must do otherwise data will be messed up! */ clk_rr_lookup.reserve_nodes(grids.width(), grids.height(), clk_ntwk.num_trees(), clk_ntwk.max_tree_depth(), @@ -164,12 +165,12 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, /* Bypass if the routing channel does not exist when through channels are * not allowed */ if ((false == through_channel) && - (false == is_chanx_exist(grids, chanx_coord))) { + (false == is_chanx_exist(grids, layer, chanx_coord))) { continue; } - add_rr_graph_block_clock_nodes(rr_graph_builder, clk_rr_lookup, - rr_graph_view, clk_ntwk, chanx_coord, - CHANX, CHANX_COST_INDEX_START, verbose); + add_rr_graph_block_clock_nodes( + rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, layer, + chanx_coord, CHANX, CHANX_COST_INDEX_START, verbose); VTR_ASSERT(rr_graph_view.valid_node( clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); @@ -186,13 +187,13 @@ static void add_rr_graph_clock_nodes(RRGraphBuilder& rr_graph_builder, /* Bypass if the routing channel does not exist when through channel are * not allowed */ if ((false == through_channel) && - (false == is_chany_exist(grids, chany_coord))) { + (false == is_chany_exist(grids, layer, chany_coord))) { continue; } add_rr_graph_block_clock_nodes( - rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, chany_coord, - CHANY, CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments(), - verbose); + rr_graph_builder, clk_rr_lookup, rr_graph_view, clk_ntwk, layer, + chany_coord, CHANY, + CHANX_COST_INDEX_START + rr_graph_view.num_rr_segments(), verbose); VTR_ASSERT(rr_graph_view.valid_node( clk_rr_lookup.find_node(1, 0, ClockTreeId(0), ClockLevelId(0), ClockTreePinId(0), Direction::INC))); @@ -392,11 +393,12 @@ static std::vector find_clock_track2track_node( *******************************************************************/ static void try_find_and_add_clock_track2ipin_node( std::vector& des_nodes, const DeviceGrid& grids, - const RRGraphView& rr_graph_view, const vtr::Point& grid_coord, - const e_side& pin_side, const ClockNetwork& clk_ntwk, - const ClockTreeId& clk_tree, const ClockTreePinId& clk_pin) { - t_physical_tile_type_ptr grid_type = - grids[grid_coord.x()][grid_coord.y()].type; + const RRGraphView& rr_graph_view, const size_t& layer, + const vtr::Point& grid_coord, const e_side& pin_side, + const ClockNetwork& clk_ntwk, const ClockTreeId& clk_tree, + const ClockTreePinId& clk_pin) { + t_physical_tile_type_ptr grid_type = grids.get_physical_type( + t_physical_tile_loc(grid_coord.x(), grid_coord.y(), layer)); for (std::string tap_pin_name : clk_ntwk.tree_flatten_taps(clk_tree, clk_pin)) { /* tap pin name could be 'io[5:5].a2f[0]' */ @@ -405,7 +407,7 @@ static void try_find_and_add_clock_track2ipin_node( continue; } RRNodeId des_node = rr_graph_view.node_lookup().find_node( - grid_coord.x(), grid_coord.y(), IPIN, grid_pin_idx, pin_side); + layer, grid_coord.x(), grid_coord.y(), IPIN, grid_pin_idx, pin_side); if (rr_graph_view.valid_node(des_node)) { des_nodes.push_back(des_node); } @@ -440,36 +442,36 @@ static void try_find_and_add_clock_track2ipin_node( *******************************************************************/ static std::vector find_clock_track2ipin_node( const DeviceGrid& grids, const RRGraphView& rr_graph_view, - const t_rr_type& chan_type, const vtr::Point& chan_coord, - const ClockNetwork& clk_ntwk, const ClockTreeId& clk_tree, - const ClockTreePinId& clk_pin) { + const t_rr_type& chan_type, const size_t& layer, + const vtr::Point& chan_coord, const ClockNetwork& clk_ntwk, + const ClockTreeId& clk_tree, const ClockTreePinId& clk_pin) { std::vector des_nodes; if (chan_type == CHANX) { /* Get the clock IPINs at the BOTTOM side of adjacent grids [x][y+1] */ vtr::Point bot_grid_coord(chan_coord.x(), chan_coord.y() + 1); try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, - bot_grid_coord, BOTTOM, clk_ntwk, - clk_tree, clk_pin); + layer, bot_grid_coord, BOTTOM, + clk_ntwk, clk_tree, clk_pin); /* Get the clock IPINs at the TOP side of adjacent grids [x][y] */ vtr::Point top_grid_coord(chan_coord.x(), chan_coord.y()); try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, - top_grid_coord, TOP, clk_ntwk, + layer, top_grid_coord, TOP, clk_ntwk, clk_tree, clk_pin); } else { VTR_ASSERT(chan_type == CHANY); /* Get the clock IPINs at the LEFT side of adjacent grids [x][y+1] */ vtr::Point left_grid_coord(chan_coord.x() + 1, chan_coord.y()); try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, - left_grid_coord, LEFT, clk_ntwk, - clk_tree, clk_pin); + layer, left_grid_coord, LEFT, + clk_ntwk, clk_tree, clk_pin); /* Get the clock IPINs at the RIGHT side of adjacent grids [x][y] */ vtr::Point right_grid_coord(chan_coord.x(), chan_coord.y()); try_find_and_add_clock_track2ipin_node(des_nodes, grids, rr_graph_view, - right_grid_coord, RIGHT, clk_ntwk, - clk_tree, clk_pin); + layer, right_grid_coord, RIGHT, + clk_ntwk, clk_tree, clk_pin); } return des_nodes; @@ -481,7 +483,7 @@ static std::vector find_clock_track2ipin_node( static void add_rr_graph_block_clock_edges( RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, - const DeviceGrid& grids, const ClockNetwork& clk_ntwk, + const DeviceGrid& grids, const size_t& layer, const ClockNetwork& clk_ntwk, const vtr::Point& chan_coord, const t_rr_type& chan_type, const bool& verbose) { size_t edge_count = 0; @@ -524,7 +526,7 @@ static void add_rr_graph_block_clock_edges( /* Create edges */ VTR_ASSERT(rr_graph_view.valid_node(des_node)); rr_graph_builder.create_edge(src_node, des_node, - clk_ntwk.default_switch()); + clk_ntwk.default_switch(), false); edge_count++; } VTR_LOGV(verbose, "\tWill add %lu edges to other clock nodes\n", @@ -535,12 +537,12 @@ static void add_rr_graph_block_clock_edges( if (clk_ntwk.is_last_level(itree, ilvl)) { size_t curr_edge_count = edge_count; for (RRNodeId des_node : find_clock_track2ipin_node( - grids, rr_graph_view, chan_type, chan_coord, clk_ntwk, itree, - ClockTreePinId(ipin))) { + grids, rr_graph_view, chan_type, layer, chan_coord, clk_ntwk, + itree, ClockTreePinId(ipin))) { /* Create edges */ VTR_ASSERT(rr_graph_view.valid_node(des_node)); rr_graph_builder.create_edge(src_node, des_node, - clk_ntwk.default_switch()); + clk_ntwk.default_switch(), false); edge_count++; } VTR_LOGV(verbose, "\tWill add %lu edges to other IPIN\n", @@ -579,7 +581,7 @@ static void add_rr_graph_block_clock_edges( static void add_rr_graph_clock_edges( RRGraphBuilder& rr_graph_builder, size_t& num_edges_to_create, const RRClockSpatialLookup& clk_rr_lookup, const RRGraphView& rr_graph_view, - const DeviceGrid& grids, const bool& through_channel, + const DeviceGrid& grids, const size_t& layer, const bool& through_channel, const ClockNetwork& clk_ntwk, const bool& verbose) { /* Add edges which is driven by X-direction clock routing tracks */ for (size_t iy = 0; iy < grids.height() - 1; ++iy) { @@ -588,11 +590,11 @@ static void add_rr_graph_clock_edges( /* Bypass if the routing channel does not exist when through channels are * not allowed */ if ((false == through_channel) && - (false == is_chanx_exist(grids, chanx_coord))) { + (false == is_chanx_exist(grids, layer, chanx_coord))) { continue; } add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, - clk_rr_lookup, rr_graph_view, grids, + clk_rr_lookup, rr_graph_view, grids, layer, clk_ntwk, chanx_coord, CHANX, verbose); } } @@ -604,11 +606,11 @@ static void add_rr_graph_clock_edges( /* Bypass if the routing channel does not exist when through channel are * not allowed */ if ((false == through_channel) && - (false == is_chany_exist(grids, chany_coord))) { + (false == is_chany_exist(grids, layer, chany_coord))) { continue; } add_rr_graph_block_clock_edges(rr_graph_builder, num_edges_to_create, - clk_rr_lookup, rr_graph_view, grids, + clk_rr_lookup, rr_graph_view, grids, layer, clk_ntwk, chany_coord, CHANY, verbose); } } @@ -647,7 +649,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, /* Estimate the number of nodes and pre-allocate */ size_t orig_num_nodes = vpr_device_ctx.rr_graph.num_nodes(); size_t num_clock_nodes = estimate_clock_rr_graph_num_nodes( - vpr_device_ctx.grid, vpr_device_ctx.arch->through_channel, clk_ntwk); + vpr_device_ctx.grid, 0, vpr_device_ctx.arch->through_channel, clk_ntwk); vpr_device_ctx.rr_graph_builder.unlock_storage(); vpr_device_ctx.rr_graph_builder.reserve_nodes(num_clock_nodes + orig_num_nodes); @@ -658,7 +660,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, /* Add clock nodes */ add_rr_graph_clock_nodes(vpr_device_ctx.rr_graph_builder, clk_rr_lookup, - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, 0, vpr_device_ctx.arch->through_channel, clk_ntwk, verbose); VTR_LOGV(verbose, @@ -673,7 +675,7 @@ int append_clock_rr_graph(DeviceContext& vpr_device_ctx, add_rr_graph_clock_edges( vpr_device_ctx.rr_graph_builder, num_clock_edges, static_cast(clk_rr_lookup), - vpr_device_ctx.rr_graph, vpr_device_ctx.grid, + vpr_device_ctx.rr_graph, vpr_device_ctx.grid, 0, vpr_device_ctx.arch->through_channel, clk_ntwk, verbose); VTR_LOGV(verbose, "Added %lu clock edges to routing " diff --git a/openfpga/src/annotation/device_rr_gsb.cpp b/openfpga/src/annotation/device_rr_gsb.cpp index 9811bdcab..963d53bc1 100644 --- a/openfpga/src/annotation/device_rr_gsb.cpp +++ b/openfpga/src/annotation/device_rr_gsb.cpp @@ -78,7 +78,8 @@ size_t DeviceRRGSB::get_num_cb_unique_module(const t_rr_type& cb_type) const { } /* Identify if a GSB actually exists at a location */ -bool DeviceRRGSB::is_gsb_exist(const vtr::Point coord) const { +bool DeviceRRGSB::is_gsb_exist(const RRGraphView& rr_graph, + const vtr::Point coord) const { /* Out of range, does not exist */ if (false == validate_coordinate(coord)) { return false; @@ -93,7 +94,7 @@ bool DeviceRRGSB::is_gsb_exist(const vtr::Point coord) const { return true; } - if (true == get_gsb(coord).is_sb_exist()) { + if (true == get_gsb(coord).is_sb_exist(rr_graph)) { return true; } @@ -145,34 +146,14 @@ const RRGSB& DeviceRRGSB::get_cb_unique_module(const t_rr_type& cb_type, /* Give a coordinate of a rr switch block, and return its unique mirror */ const RRGSB& DeviceRRGSB::get_cb_unique_module( const t_rr_type& cb_type, const vtr::Point& coordinate) const { - VTR_ASSERT(validate_cb_type(cb_type)); - VTR_ASSERT(validate_coordinate(coordinate)); - size_t cb_unique_module_id; - - switch (cb_type) { - case CHANX: - cb_unique_module_id = - cbx_unique_module_id_[coordinate.x()][coordinate.y()]; - break; - case CHANY: - cb_unique_module_id = - cby_unique_module_id_[coordinate.x()][coordinate.y()]; - break; - default: - VTR_LOG_ERROR("Invalid type of connection block!\n"); - exit(1); - } - - return get_cb_unique_module(cb_type, cb_unique_module_id); + return get_cb_unique_module(cb_type, + get_cb_unique_module_index(cb_type, coordinate)); } /* Give a coordinate of a rr switch block, and return its unique mirror */ const RRGSB& DeviceRRGSB::get_sb_unique_module( const vtr::Point& coordinate) const { - VTR_ASSERT(validate_coordinate(coordinate)); - size_t sb_unique_module_id = - sb_unique_module_id_[coordinate.x()][coordinate.y()]; - return get_sb_unique_module(sb_unique_module_id); + return get_sb_unique_module(get_sb_unique_module_index(coordinate)); } /************************************************************************ @@ -550,4 +531,35 @@ bool DeviceRRGSB::validate_cb_type(const t_rr_type& cb_type) const { return ((CHANX == cb_type) || (CHANY == cb_type)); } +size_t DeviceRRGSB::get_sb_unique_module_index( + const vtr::Point& coordinate) const { + VTR_ASSERT(validate_coordinate(coordinate)); + size_t sb_unique_module_id = + sb_unique_module_id_[coordinate.x()][coordinate.y()]; + return sb_unique_module_id; +} + +size_t DeviceRRGSB::get_cb_unique_module_index( + const t_rr_type& cb_type, const vtr::Point& coordinate) const { + VTR_ASSERT(validate_cb_type(cb_type)); + VTR_ASSERT(validate_coordinate(coordinate)); + size_t cb_unique_module_id; + + switch (cb_type) { + case CHANX: + cb_unique_module_id = + cbx_unique_module_id_[coordinate.x()][coordinate.y()]; + break; + case CHANY: + cb_unique_module_id = + cby_unique_module_id_[coordinate.x()][coordinate.y()]; + break; + default: + VTR_LOG_ERROR("Invalid type of connection block!\n"); + exit(1); + } + + return cb_unique_module_id; +} + } /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/device_rr_gsb.h b/openfpga/src/annotation/device_rr_gsb.h index 5873bb192..245b1646b 100644 --- a/openfpga/src/annotation/device_rr_gsb.h +++ b/openfpga/src/annotation/device_rr_gsb.h @@ -58,7 +58,15 @@ class DeviceRRGSB { const vtr::Point& coordinate) const; size_t get_num_cb_unique_module(const t_rr_type& cb_type) const; /* get the number of unique mirrors of CBs */ - bool is_gsb_exist(const vtr::Point coord) const; + bool is_gsb_exist(const RRGraphView& rr_graph, + const vtr::Point coord) const; + /* Get the index of the unique Switch block module with a given GSB + * coordinate. Note: Do NOT use sb coordinate!!! */ + size_t get_sb_unique_module_index(const vtr::Point& coordinate) const; + /* Get the index of the unique Connection block module with a given GSB + * coordinate. Note: Do NOT use sb coordinate!!! */ + size_t get_cb_unique_module_index(const t_rr_type& cb_type, + const vtr::Point& coordinate) const; public: /* Mutators */ void reserve( diff --git a/openfpga/src/annotation/fabric_tile.cpp b/openfpga/src/annotation/fabric_tile.cpp new file mode 100644 index 000000000..367fa5cef --- /dev/null +++ b/openfpga/src/annotation/fabric_tile.cpp @@ -0,0 +1,708 @@ +/************************************************************************ + * Member functions for class FabricTile + ***********************************************************************/ +#include "fabric_tile.h" + +#include "build_top_module_utils.h" +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_log.h" + +/* namespace openfpga begins */ +namespace openfpga { + +vtr::Point FabricTile::tile_coordinate( + const FabricTileId& tile_id) const { + VTR_ASSERT(valid_tile_id(tile_id)); + return coords_[tile_id]; +} + +vtr::Point FabricTile::unique_tile_coordinate( + const FabricTileId& tile_id) const { + vtr::Point tile_coord = tile_coordinate(tile_id); + FabricTileId unique_fabric_tile_id = unique_tile(tile_coord); + return tile_coordinate(unique_fabric_tile_id); +} + +FabricTileId FabricTile::find_unique_tile(const FabricTileId& tile_id) const { + vtr::Point tile_coord = tile_coordinate(tile_id); + return unique_tile(tile_coord); +} + +std::vector> FabricTile::pb_coordinates( + const FabricTileId& tile_id) const { + VTR_ASSERT(valid_tile_id(tile_id)); + std::vector> pb_root_coords; + pb_root_coords.reserve(pb_coords_[tile_id].size()); + for (auto curr_rect : pb_coords_[tile_id]) { + pb_root_coords.push_back(curr_rect.bottom_left()); + } + return pb_root_coords; +} + +std::vector> FabricTile::cb_coordinates( + const FabricTileId& tile_id, const t_rr_type& cb_type) const { + VTR_ASSERT(valid_tile_id(tile_id)); + switch (cb_type) { + case CHANX: + return cbx_coords_[tile_id]; + case CHANY: + return cby_coords_[tile_id]; + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } + return std::vector>(); +} + +std::vector> FabricTile::sb_coordinates( + const FabricTileId& tile_id) const { + VTR_ASSERT(valid_tile_id(tile_id)); + return sb_coords_[tile_id]; +} + +FabricTileId FabricTile::unique_tile(const vtr::Point& coord) const { + /* Return invalid Id when out of range! */ + if (coord.x() < tile_coord2unique_tile_ids_.size()) { + if (coord.y() < tile_coord2unique_tile_ids_[coord.x()].size()) { + return tile_coord2unique_tile_ids_[coord.x()][coord.y()]; + } + } + return FabricTileId::INVALID(); +} + +FabricTileId FabricTile::find_tile(const vtr::Point& coord) const { + if (coord.x() >= tile_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "Tile coordinate [%lu][%lu] exceeds the maximum range [%lu][%lu]!\n", + coord.x(), coord.y(), tile_coord2id_lookup_.size(), + tile_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + if (coord.y() >= tile_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "Tile coordinate [%lu][%lu] exceeds the maximum range [%lu][%lu]!\n", + coord.x(), coord.y(), tile_coord2id_lookup_.size(), + tile_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + return tile_coord2id_lookup_[coord.x()][coord.y()]; +} + +FabricTileId FabricTile::find_tile_by_pb_coordinate( + const vtr::Point& coord) const { + if (pb_coord2id_lookup_.empty()) { + return FabricTileId::INVALID(); + } + if (coord.x() >= pb_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "Programmable block coordinate [%lu][%lu] exceeds the maximum range " + "[%lu][%lu]!\n", + coord.x(), coord.y(), pb_coord2id_lookup_.size(), + pb_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + if (coord.y() >= pb_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "Programmable block coordinate [%lu][%lu] exceeds the maximum range " + "[%lu][%lu]!\n", + coord.x(), coord.y(), pb_coord2id_lookup_.size(), + pb_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + return pb_coord2id_lookup_[coord.x()][coord.y()]; +} + +FabricTileId FabricTile::find_tile_by_cb_coordinate( + const t_rr_type& cb_type, const vtr::Point& coord) const { + switch (cb_type) { + case CHANX: { + if (cbx_coord2id_lookup_.empty()) { + return FabricTileId::INVALID(); + } + if (coord.x() >= cbx_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "X-direction connection block coordinate [%lu][%lu] exceeds the " + "maximum range [%lu][%lu]!\n", + coord.x(), coord.y(), cbx_coord2id_lookup_.size(), + cbx_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + if (coord.y() >= cbx_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "X-direction connection block coordinate [%lu][%lu] exceeds the " + "maximum range [%lu][%lu]!\n", + coord.x(), coord.y(), cbx_coord2id_lookup_.size(), + cbx_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + return cbx_coord2id_lookup_[coord.x()][coord.y()]; + } + case CHANY: { + if (cby_coord2id_lookup_.empty()) { + return FabricTileId::INVALID(); + } + if (coord.x() >= cby_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "Y-direction connection block coordinate [%lu][%lu] exceeds the " + "maximum range [%lu][%lu]!\n", + coord.x(), coord.y(), cby_coord2id_lookup_.size(), + cby_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + if (coord.y() >= cby_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "Y-direction connection block coordinate [%lu][%lu] exceeds the " + "maximum range [%lu][%lu]!\n", + coord.x(), coord.y(), cby_coord2id_lookup_.size(), + cby_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + return cby_coord2id_lookup_[coord.x()][coord.y()]; + } + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} + +FabricTileId FabricTile::find_tile_by_sb_coordinate( + const vtr::Point& coord) const { + if (sb_coord2id_lookup_.empty()) { + return FabricTileId::INVALID(); + } + if (coord.x() >= sb_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "Switch block coordinate [%lu][%lu] exceeds the maximum range " + "[%lu][%lu]!\n", + coord.x(), coord.y(), sb_coord2id_lookup_.size(), + sb_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + if (coord.y() >= sb_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "Switch block coordinate [%lu][%lu] exceeds the maximum range " + "[%lu][%lu]!\n", + coord.x(), coord.y(), sb_coord2id_lookup_.size(), + sb_coord2id_lookup_[0].size()); + return FabricTileId::INVALID(); + } + return sb_coord2id_lookup_[coord.x()][coord.y()]; +} + +bool FabricTile::pb_in_tile(const FabricTileId& tile_id, + const vtr::Point& coord, + const bool& use_gsb_coord) const { + if (use_gsb_coord) { + return !pb_gsb_coords_[tile_id].empty() && + find_pb_index_in_tile(tile_id, coord, use_gsb_coord) != + pb_gsb_coords_[tile_id].size(); + } + return !pb_coords_[tile_id].empty() && + find_pb_index_in_tile(tile_id, coord) != pb_coords_[tile_id].size(); +} + +size_t FabricTile::find_pb_index_in_tile(const FabricTileId& tile_id, + const vtr::Point& coord, + const bool& use_gsb_coord) const { + VTR_ASSERT(valid_tile_id(tile_id)); + if (use_gsb_coord) { + for (size_t idx = 0; idx < pb_gsb_coords_[tile_id].size(); ++idx) { + vtr::Point curr_coord = pb_gsb_coords_[tile_id][idx]; + if (curr_coord == coord) { + return idx; + } + } + /* Not found, return an invalid index */ + return pb_gsb_coords_[tile_id].size(); + } else { + for (size_t idx = 0; idx < pb_coords_[tile_id].size(); ++idx) { + if (pb_coords_[tile_id][idx].coincident(coord)) { + return idx; + } + } + /* Not found, return an invalid index */ + return pb_coords_[tile_id].size(); + } +} + +bool FabricTile::sb_in_tile(const FabricTileId& tile_id, + const vtr::Point& coord) const { + return !sb_coords_[tile_id].empty() && + find_sb_index_in_tile(tile_id, coord) != sb_coords_[tile_id].size(); +} + +size_t FabricTile::find_sb_index_in_tile( + const FabricTileId& tile_id, const vtr::Point& coord) const { + VTR_ASSERT(valid_tile_id(tile_id)); + for (size_t idx = 0; idx < sb_coords_[tile_id].size(); ++idx) { + vtr::Point curr_coord = sb_coords_[tile_id][idx]; + if (curr_coord == coord) { + return idx; + } + } + /* Not found, return an invalid index */ + return sb_coords_[tile_id].size(); +} + +bool FabricTile::cb_in_tile(const FabricTileId& tile_id, + const t_rr_type& cb_type, + const vtr::Point& coord) const { + switch (cb_type) { + case CHANX: + return !cbx_coords_[tile_id].empty() && + find_cb_index_in_tile(tile_id, cb_type, coord) != + cbx_coords_[tile_id].size(); + case CHANY: + return !cby_coords_[tile_id].empty() && + find_cb_index_in_tile(tile_id, cb_type, coord) != + cby_coords_[tile_id].size(); + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} + +size_t FabricTile::find_cb_index_in_tile( + const FabricTileId& tile_id, const t_rr_type& cb_type, + const vtr::Point& coord) const { + VTR_ASSERT(valid_tile_id(tile_id)); + switch (cb_type) { + case CHANX: + for (size_t idx = 0; idx < cbx_coords_[tile_id].size(); ++idx) { + vtr::Point curr_coord = cbx_coords_[tile_id][idx]; + if (curr_coord == coord) { + return idx; + } + } + return cbx_coords_[tile_id].size(); + case CHANY: + for (size_t idx = 0; idx < cby_coords_[tile_id].size(); ++idx) { + vtr::Point curr_coord = cby_coords_[tile_id][idx]; + if (curr_coord == coord) { + return idx; + } + } + return cby_coords_[tile_id].size(); + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} + +vtr::Point FabricTile::find_cb_coordinate_in_unique_tile( + const FabricTileId& tile_id, const t_rr_type& cb_type, + const vtr::Point& cb_coord) const { + size_t cb_idx_in_curr_tile = + find_cb_index_in_tile(tile_id, cb_type, cb_coord); + FabricTileId unique_tile = find_unique_tile(tile_id); + return cb_coordinates(unique_tile, cb_type)[cb_idx_in_curr_tile]; +} + +vtr::Point FabricTile::find_pb_coordinate_in_unique_tile( + const FabricTileId& tile_id, const vtr::Point& pb_coord) const { + size_t pb_idx_in_curr_tile = find_pb_index_in_tile(tile_id, pb_coord); + FabricTileId unique_tile = find_unique_tile(tile_id); + return pb_coordinates(unique_tile)[pb_idx_in_curr_tile]; +} + +vtr::Point FabricTile::find_sb_coordinate_in_unique_tile( + const FabricTileId& tile_id, const vtr::Point& sb_coord) const { + size_t sb_idx_in_curr_tile = find_sb_index_in_tile(tile_id, sb_coord); + FabricTileId unique_tile = find_unique_tile(tile_id); + return sb_coordinates(unique_tile)[sb_idx_in_curr_tile]; +} + +std::vector FabricTile::unique_tiles() const { + return unique_tile_ids_; +} + +bool FabricTile::empty() const { return ids_.empty(); } + +FabricTileId FabricTile::create_tile(const vtr::Point& coord) { + FabricTileId tile_id = FabricTileId(ids_.size()); + ids_.push_back(tile_id); + coords_.push_back(coord); + pb_coords_.emplace_back(); + pb_gsb_coords_.emplace_back(); + cbx_coords_.emplace_back(); + cby_coords_.emplace_back(); + sb_coords_.emplace_back(); + + /* Register in fast look-up */ + if (register_tile_in_lookup(tile_id, coord)) { + return tile_id; + } + return FabricTileId::INVALID(); +} + +void FabricTile::init(const vtr::Point& max_coord) { + tile_coord2id_lookup_.resize(max_coord.x()); + pb_coord2id_lookup_.resize(max_coord.x()); + cbx_coord2id_lookup_.resize(max_coord.x()); + cby_coord2id_lookup_.resize(max_coord.x()); + sb_coord2id_lookup_.resize(max_coord.x()); + for (size_t ix = 0; ix < max_coord.x(); ++ix) { + tile_coord2id_lookup_[ix].resize(max_coord.y(), FabricTileId::INVALID()); + pb_coord2id_lookup_[ix].resize(max_coord.y(), FabricTileId::INVALID()); + cbx_coord2id_lookup_[ix].resize(max_coord.y(), FabricTileId::INVALID()); + cby_coord2id_lookup_[ix].resize(max_coord.y(), FabricTileId::INVALID()); + sb_coord2id_lookup_[ix].resize(max_coord.y(), FabricTileId::INVALID()); + } + tile_coord2unique_tile_ids_.resize(max_coord.x()); + for (size_t ix = 0; ix < max_coord.x(); ++ix) { + tile_coord2unique_tile_ids_[ix].resize(max_coord.y(), + FabricTileId::INVALID()); + } +} + +bool FabricTile::register_tile_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord) { + if (coord.x() >= tile_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given x='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.x(), tile_coord2id_lookup_.size()); + return false; + } + if (coord.y() >= tile_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given y='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.y(), tile_coord2id_lookup_[coord.x()].size()); + return false; + } + /* Throw error if this coord is already registered! */ + if (tile_coord2id_lookup_[coord.x()][coord.y()]) { + VTR_LOG_ERROR("Tile at [%lu][%lu] has already been registered!\n", + coord.x(), coord.y()); + return false; + } + tile_coord2id_lookup_[coord.x()][coord.y()] = tile_id; + + return true; +} + +bool FabricTile::register_pb_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord) { + if (coord.x() >= pb_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given x='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.x(), pb_coord2id_lookup_.size()); + return false; + } + if (coord.y() >= pb_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given y='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.y(), pb_coord2id_lookup_[coord.x()].size()); + return false; + } + /* Throw error if this coord is already registered! */ + if (pb_coord2id_lookup_[coord.x()][coord.y()] && + pb_coord2id_lookup_[coord.x()][coord.y()] != tile_id) { + VTR_LOG_ERROR( + "Programmable block at [%lu][%lu] has already been registered!\n", + coord.x(), coord.y()); + return false; + } + pb_coord2id_lookup_[coord.x()][coord.y()] = tile_id; + + return true; +} + +bool FabricTile::register_cbx_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord) { + if (coord.x() >= cbx_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given x='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.x(), cbx_coord2id_lookup_.size()); + return false; + } + if (coord.y() >= cbx_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given y='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.y(), cbx_coord2id_lookup_[coord.x()].size()); + return false; + } + /* Throw error if this coord is already registered! */ + if (cbx_coord2id_lookup_[coord.x()][coord.y()]) { + VTR_LOG_ERROR( + "X-direction connection block at [%lu][%lu] has already been " + "registered!\n", + coord.x(), coord.y()); + return false; + } + cbx_coord2id_lookup_[coord.x()][coord.y()] = tile_id; + + return true; +} + +bool FabricTile::register_cby_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord) { + if (coord.x() >= cby_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given x='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.x(), cby_coord2id_lookup_.size()); + return false; + } + if (coord.y() >= cby_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given y='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.y(), cby_coord2id_lookup_[coord.x()].size()); + return false; + } + /* Throw error if this coord is already registered! */ + if (cby_coord2id_lookup_[coord.x()][coord.y()]) { + VTR_LOG_ERROR( + "Y-direction connection block at [%lu][%lu] has already been " + "registered!\n", + coord.x(), coord.y()); + return false; + } + cby_coord2id_lookup_[coord.x()][coord.y()] = tile_id; + + return true; +} + +bool FabricTile::register_sb_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord) { + if (coord.x() >= sb_coord2id_lookup_.size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given x='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.x(), sb_coord2id_lookup_.size()); + return false; + } + if (coord.y() >= sb_coord2id_lookup_[coord.x()].size()) { + VTR_LOG_ERROR( + "Fast look-up has not been re-allocated properly! Given y='%lu' exceeds " + "the upper-bound '%lu'!\n", + coord.y(), sb_coord2id_lookup_[coord.x()].size()); + return false; + } + /* Throw error if this coord is already registered! */ + if (sb_coord2id_lookup_[coord.x()][coord.y()]) { + VTR_LOG_ERROR("Switch block at [%lu][%lu] has already been registered!\n", + coord.x(), coord.y()); + return false; + } + sb_coord2id_lookup_[coord.x()][coord.y()] = tile_id; + + return true; +} + +void FabricTile::invalidate_tile_in_lookup(const vtr::Point& coord) { + tile_coord2id_lookup_[coord.x()][coord.y()] = FabricTileId::INVALID(); +} + +void FabricTile::invalidate_pb_in_lookup(const vtr::Point& coord) { + pb_coord2id_lookup_[coord.x()][coord.y()] = FabricTileId::INVALID(); +} + +void FabricTile::invalidate_cbx_in_lookup(const vtr::Point& coord) { + cbx_coord2id_lookup_[coord.x()][coord.y()] = FabricTileId::INVALID(); +} + +void FabricTile::invalidate_cby_in_lookup(const vtr::Point& coord) { + cby_coord2id_lookup_[coord.x()][coord.y()] = FabricTileId::INVALID(); +} + +void FabricTile::invalidate_sb_in_lookup(const vtr::Point& coord) { + sb_coord2id_lookup_[coord.x()][coord.y()] = FabricTileId::INVALID(); +} + +bool FabricTile::set_tile_coordinate(const FabricTileId& tile_id, + const vtr::Point& coord) { + VTR_ASSERT(valid_tile_id(tile_id)); + /* Invalidate previous coordinate in look-up */ + invalidate_tile_in_lookup(coords_[tile_id]); + /* update coordinate */ + coords_[tile_id] = coord; + /* Register in fast look-up */ + return register_tile_in_lookup(tile_id, coord); +} + +int FabricTile::add_pb_coordinate(const FabricTileId& tile_id, + const vtr::Point& coord, + const vtr::Point& gsb_coord) { + VTR_ASSERT(valid_tile_id(tile_id)); + pb_coords_[tile_id].push_back(vtr::Rect(coord, coord)); + pb_gsb_coords_[tile_id].push_back(gsb_coord); + /* Register in fast look-up */ + return register_pb_in_lookup(tile_id, coord); +} + +int FabricTile::set_pb_max_coordinate(const FabricTileId& tile_id, + const size_t& pb_index, + const vtr::Point& max_coord) { + VTR_ASSERT(valid_tile_id(tile_id)); + if (pb_index >= pb_coords_[tile_id].size()) { + VTR_LOG_ERROR( + "Invalid pb_index '%lu' is out of range of programmable block list " + "(size='%lu') of tile[%lu][%lu]!\n", + pb_index, pb_coords_[tile_id].size(), tile_coordinate(tile_id).x(), + tile_coordinate(tile_id).y()); + return CMD_EXEC_FATAL_ERROR; + } + if (max_coord.x() < pb_coords_[tile_id][pb_index].xmin() || + max_coord.y() < pb_coords_[tile_id][pb_index].ymin()) { + VTR_LOG_ERROR( + "Invalid max. coordinate (%lu, %lu) is out of range of programmable " + "block list (%lu, %lu) <-> (%lu, %lu) of tile[%lu][%lu]!\n", + max_coord.x(), max_coord.y(), pb_coords_[tile_id][pb_index].xmin(), + pb_coords_[tile_id][pb_index].ymin(), + pb_coords_[tile_id][pb_index].xmax(), + pb_coords_[tile_id][pb_index].ymax(), tile_coordinate(tile_id).x(), + tile_coordinate(tile_id).y()); + return CMD_EXEC_FATAL_ERROR; + } + pb_coords_[tile_id][pb_index].set_xmax(max_coord.x()); + pb_coords_[tile_id][pb_index].set_ymax(max_coord.y()); + /* Update fast lookup */ + for (size_t ix = pb_coords_[tile_id][pb_index].xmin(); + ix <= pb_coords_[tile_id][pb_index].xmax(); ++ix) { + for (size_t iy = pb_coords_[tile_id][pb_index].ymin(); + iy <= pb_coords_[tile_id][pb_index].ymax(); ++iy) { + register_pb_in_lookup(tile_id, vtr::Point(ix, iy)); + } + } + return CMD_EXEC_SUCCESS; +} + +int FabricTile::add_cb_coordinate(const FabricTileId& tile_id, + const t_rr_type& cb_type, + const vtr::Point& coord) { + VTR_ASSERT(valid_tile_id(tile_id)); + switch (cb_type) { + case CHANX: + cbx_coords_[tile_id].push_back(coord); + /* Register in fast look-up */ + return register_cbx_in_lookup(tile_id, coord); + case CHANY: + cby_coords_[tile_id].push_back(coord); + /* Register in fast look-up */ + return register_cby_in_lookup(tile_id, coord); + default: + VTR_LOG("Invalid type of connection block!\n"); + exit(1); + } +} + +int FabricTile::add_sb_coordinate(const FabricTileId& tile_id, + const vtr::Point& coord) { + VTR_ASSERT(valid_tile_id(tile_id)); + sb_coords_[tile_id].push_back(coord); + /* Register in fast look-up */ + return register_sb_in_lookup(tile_id, coord); +} + +void FabricTile::clear() { + ids_.clear(); + coords_.clear(); + pb_coords_.clear(); + pb_gsb_coords_.clear(); + cbx_coords_.clear(); + cby_coords_.clear(); + sb_coords_.clear(); + tile_coord2id_lookup_.clear(); + pb_coord2id_lookup_.clear(); + cbx_coord2id_lookup_.clear(); + cby_coord2id_lookup_.clear(); + sb_coord2id_lookup_.clear(); + tile_coord2unique_tile_ids_.clear(); + unique_tile_ids_.clear(); +} + +bool FabricTile::valid_tile_id(const FabricTileId& tile_id) const { + return (size_t(tile_id) < ids_.size()) && (tile_id == ids_[tile_id]); +} + +bool FabricTile::equivalent_tile(const FabricTileId& tile_a, + const FabricTileId& tile_b, + const DeviceGrid& grids, + const DeviceRRGSB& device_rr_gsb) const { + /* The number of cbx, cby and sb blocks should be the same */ + if (pb_coords_[tile_a].size() != pb_coords_[tile_b].size() || + pb_gsb_coords_[tile_a].size() != pb_gsb_coords_[tile_b].size() || + cbx_coords_[tile_a].size() != cbx_coords_[tile_b].size() || + cby_coords_[tile_a].size() != cby_coords_[tile_b].size() || + sb_coords_[tile_a].size() != sb_coords_[tile_b].size()) { + return false; + } + /* The pb of two tiles should be the same, otherwise not equivalent */ + for (size_t iblk = 0; iblk < pb_coords_[tile_a].size(); ++iblk) { + vtr::Point tile_a_pb_coord = pb_coords_[tile_a][iblk].bottom_left(); + vtr::Point tile_b_pb_coord = pb_coords_[tile_b][iblk].bottom_left(); + if (generate_grid_block_module_name_in_top_module(std::string(), grids, + tile_a_pb_coord) != + generate_grid_block_module_name_in_top_module(std::string(), grids, + tile_b_pb_coord)) { + return false; + } + } + /* Each CBx should have the same unique modules in the device rr_gsb */ + for (size_t iblk = 0; iblk < cbx_coords_[tile_a].size(); ++iblk) { + if (device_rr_gsb.get_cb_unique_module_index(CHANX, + cbx_coords_[tile_a][iblk]) != + device_rr_gsb.get_cb_unique_module_index(CHANX, + cbx_coords_[tile_b][iblk])) { + return false; + } + } + for (size_t iblk = 0; iblk < cby_coords_[tile_a].size(); ++iblk) { + if (device_rr_gsb.get_cb_unique_module_index(CHANY, + cby_coords_[tile_a][iblk]) != + device_rr_gsb.get_cb_unique_module_index(CHANY, + cby_coords_[tile_b][iblk])) { + return false; + } + } + for (size_t iblk = 0; iblk < sb_coords_[tile_a].size(); ++iblk) { + if (device_rr_gsb.get_sb_unique_module_index(sb_coords_[tile_a][iblk]) != + device_rr_gsb.get_sb_unique_module_index(sb_coords_[tile_b][iblk])) { + return false; + } + } + return true; +} + +int FabricTile::build_unique_tiles(const DeviceGrid& grids, + const DeviceRRGSB& device_rr_gsb, + const bool& verbose) { + for (size_t ix = 0; ix < grids.width(); ++ix) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + if (!valid_tile_id(tile_coord2id_lookup_[ix][iy])) { + continue; /* Skip invalid tile (which does not exist) */ + } + bool is_unique_tile = true; + for (FabricTileId unique_tile_id : unique_tile_ids_) { + if (equivalent_tile(tile_coord2id_lookup_[ix][iy], unique_tile_id, + grids, device_rr_gsb)) { + VTR_LOGV(verbose, + "Tile[%lu][%lu] is a mirror to the unique tile[%lu][%lu]\n", + ix, iy, tile_coordinate(unique_tile_id).x(), + tile_coordinate(unique_tile_id).y()); + is_unique_tile = false; + tile_coord2unique_tile_ids_[ix][iy] = unique_tile_id; + break; + } + } + /* Update list if this is a unique tile */ + if (is_unique_tile) { + VTR_LOGV(verbose, "Tile[%lu][%lu] is added as a new unique tile\n", ix, + iy); + unique_tile_ids_.push_back(tile_coord2id_lookup_[ix][iy]); + tile_coord2unique_tile_ids_[ix][iy] = tile_coord2id_lookup_[ix][iy]; + } + } + } + return 0; +} + +} /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/fabric_tile.h b/openfpga/src/annotation/fabric_tile.h new file mode 100644 index 000000000..0dc27332b --- /dev/null +++ b/openfpga/src/annotation/fabric_tile.h @@ -0,0 +1,198 @@ +#ifndef FABRIC_TILE_H +#define FABRIC_TILE_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include + +#include "device_grid.h" +#include "device_rr_gsb.h" +#include "fabric_tile_fwd.h" +#include "vtr_geometry.h" +#include "vtr_vector.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/******************************************************************** + * Object models the tiles in an FPGA fabric + * This includes: + * 1. a collection of tiles, each which contains a programmable block and + *surrounding routing blocks + * 2. a collection of unique tiles + *******************************************************************/ +class FabricTile { + public: /* Accessors */ + vtr::Point tile_coordinate(const FabricTileId& tile_id) const; + /* Return all the root (bottom-left point) coordinates of programmable blocks + * under a given tile. */ + std::vector> pb_coordinates( + const FabricTileId& tile_id) const; + std::vector> cb_coordinates( + const FabricTileId& tile_id, const t_rr_type& cb_type) const; + std::vector> sb_coordinates( + const FabricTileId& tile_id) const; + /** @brief With a given coordinate, find the id of the unique tile (which is + * the same as the tile in structure) */ + FabricTileId unique_tile(const vtr::Point& coord) const; + /** @brief With a given tile id, find the id of its unique tile (which is + * the same as the tile in structure) */ + FabricTileId find_unique_tile(const FabricTileId& tile_id) const; + /** @brief Find the tile info with a given coordinate */ + FabricTileId find_tile(const vtr::Point& coord) const; + /** @brief Find the id of a tile, with a given coordinate of the programmable + * block under the tile */ + FabricTileId find_tile_by_pb_coordinate( + const vtr::Point& coord) const; + /** @brief Find the id of a tile, with a given coordinate of the connection + * block under the tile */ + FabricTileId find_tile_by_cb_coordinate( + const t_rr_type& cb_type, const vtr::Point& coord) const; + /** @brief Find the id of a tile, with a given coordinate of the switch block + * under the tile */ + FabricTileId find_tile_by_sb_coordinate( + const vtr::Point& coord) const; + /** @brief Find the coordinate of the unique tile w.r.t the tile with a tile + * id */ + vtr::Point unique_tile_coordinate(const FabricTileId& tile_id) const; + /** @brief Return a list of unique tiles */ + std::vector unique_tiles() const; + /** @brief Find the index of a programmable block in the internal list by a + * given coordinate. Note that the coord can be either the one in device grid + * or the one of gsb which the programmable block belongs to */ + size_t find_pb_index_in_tile(const FabricTileId& tile_id, + const vtr::Point& coord, + const bool& use_gsb_coord = false) const; + /** @brief Find the index of a switch block in the internal list by a given + * coordinate. */ + size_t find_sb_index_in_tile(const FabricTileId& tile_id, + const vtr::Point& coord) const; + /** @brief Find the index of a connection block in the internal list by a + * given coordinate. */ + size_t find_cb_index_in_tile(const FabricTileId& tile_id, + const t_rr_type& cb_type, + const vtr::Point& coord) const; + /** @brief Find the coodinate of a connection block in its unique tile. For + * example, a cbx[1][0] is the 2nd element of the connection block list in + * tile[1][1], while the unique tile of tile[1][1] is tile[2][2]. We will find + * the 2nd element of the connection block list in tile[2][2] and return its + * coordinate. Error out on any exception. */ + vtr::Point find_cb_coordinate_in_unique_tile( + const FabricTileId& tile_id, const t_rr_type& cb_type, + const vtr::Point& cb_coord) const; + /** @brief Find the coodinate of a programmable block in its unique tile. For + * example, a pb[1][0] is the 2nd element of the programmable block list in + * tile[1][1], while the unique tile of tile[1][1] is tile[2][2]. We will find + * the 2nd element of the programmable block list in tile[2][2] and return its + * coordinate. Error out on any exception. */ + vtr::Point find_pb_coordinate_in_unique_tile( + const FabricTileId& tile_id, const vtr::Point& pb_coord) const; + /** @brief Find the coodinate of a switch block in its unique tile. For + * example, a pb[1][0] is the 2nd element of the switch block list in + * tile[1][1], while the unique tile of tile[1][1] is tile[2][2]. We will find + * the 2nd element of the switch block list in tile[2][2] and return its + * coordinate. Error out on any exception. */ + vtr::Point find_sb_coordinate_in_unique_tile( + const FabricTileId& tile_id, const vtr::Point& sb_coord) const; + /** @brief Check if a programmable block (with a coordinate) exists in a tile. + * Note that the coord can be either the one in device grid or the one of gsb + * which the programmable block belongs to + */ + bool pb_in_tile(const FabricTileId& tile_id, const vtr::Point& coord, + const bool& use_gsb_coord = false) const; + /** @brief Check if a switch block (with a coordinate) exists in a tile */ + bool sb_in_tile(const FabricTileId& tile_id, + const vtr::Point& coord) const; + /** @brief Check if a connection block (with a coordinate) exists in a tile */ + bool cb_in_tile(const FabricTileId& tile_id, const t_rr_type& cb_type, + const vtr::Point& coord) const; + /** @brief Identify if the fabric tile is empty: no tiles are defined */ + bool empty() const; + + public: /* Mutators */ + FabricTileId create_tile(const vtr::Point& coord); + bool set_tile_coordinate(const FabricTileId& tile_id, + const vtr::Point& coord); + int add_pb_coordinate(const FabricTileId& tile_id, + const vtr::Point& coord, + const vtr::Point& gsb_coord); + /* Set the top-right coordinate of a pb. This is mainly for heterogeneous + * blocks, whose height or width can be > 1 */ + int set_pb_max_coordinate(const FabricTileId& tile_id, const size_t& pb_index, + const vtr::Point& max_coord); + int add_cb_coordinate(const FabricTileId& tile_id, const t_rr_type& cb_type, + const vtr::Point& coord); + int add_sb_coordinate(const FabricTileId& tile_id, + const vtr::Point& coord); + /** @brief Build a list of unique tiles by comparing the coordinates in + * DeviceRRGSB */ + void build_unique_tiles(); + /** @brief Clear all the content */ + void clear(); + /** @brief Initialize the data with a given range. Used by constructors */ + void init(const vtr::Point& max_coord); + /** @brief Identify the number of unique tiles and keep in the lookup */ + int build_unique_tiles(const DeviceGrid& grids, + const DeviceRRGSB& device_rr_gsb, const bool& verbose); + + public: /* Validators */ + bool valid_tile_id(const FabricTileId& tile_id) const; + + private: /* Internal validators */ + /** @brief Identify if two tile are equivalent in their sub-modules, including + * pb, cbx, cby and sb */ + bool equivalent_tile(const FabricTileId& tile_a, const FabricTileId& tile_b, + const DeviceGrid& grids, + const DeviceRRGSB& device_rr_gsb) const; + + private: /* Internal builders */ + void invalidate_tile_in_lookup(const vtr::Point& coord); + void invalidate_pb_in_lookup(const vtr::Point& coord); + void invalidate_cbx_in_lookup(const vtr::Point& coord); + void invalidate_cby_in_lookup(const vtr::Point& coord); + void invalidate_sb_in_lookup(const vtr::Point& coord); + bool register_tile_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord); + bool register_pb_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord); + bool register_cbx_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord); + bool register_cby_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord); + bool register_sb_in_lookup(const FabricTileId& tile_id, + const vtr::Point& coord); + + private: /* Internal Data */ + vtr::vector ids_; + vtr::vector> coords_; + /* Coordinates w.r.t. RRGSB + * Note that we keep two coordinates for the programmable block: regular one + * (in device grid) and the one in gsb. This is to ease the lookup/search for + * coordinates through both device grid and gsb. Client functions need one of + * the them depending on the scenario. In future, once we refactor the RRGSB + * organization (to follow bottom-left corner style). This limitation can be + * resolved. + */ + vtr::vector>> pb_coords_; + vtr::vector>> pb_gsb_coords_; + vtr::vector>> cbx_coords_; + vtr::vector>> cby_coords_; + vtr::vector>> sb_coords_; + /* A few fast lookup to spot tile by coordinate of programmable blocks, + * connection blocks and switch blocks */ + std::vector> pb_coord2id_lookup_; + std::vector> cbx_coord2id_lookup_; + std::vector> cby_coord2id_lookup_; + std::vector> sb_coord2id_lookup_; + /* A fast lookup to spot tile by coordinate */ + std::vector> tile_coord2id_lookup_; + std::vector> + tile_coord2unique_tile_ids_; /* Use [x][y] to get the id of the unique tile + with a given coordinate */ + std::vector unique_tile_ids_; +}; + +} /* End namespace openfpga*/ + +#endif diff --git a/openfpga/src/annotation/fabric_tile_fwd.h b/openfpga/src/annotation/fabric_tile_fwd.h new file mode 100644 index 000000000..ee51de07a --- /dev/null +++ b/openfpga/src/annotation/fabric_tile_fwd.h @@ -0,0 +1,23 @@ +/************************************************** + * This file includes only declarations for + * the data structures for fabric tiles + * Please refer to fabric_tiles.h for more details + *************************************************/ +#ifndef FABRIC_TILE_FWD_H +#define FABRIC_TILE_FWD_H + +#include "vtr_strong_id.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/* Strong Ids for ModuleManager */ +struct fabric_tile_id_tag; + +typedef vtr::StrongId FabricTileId; + +class FabricTile; + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/annotation/openfpga_annotate_routing.cpp b/openfpga/src/annotation/openfpga_annotate_routing.cpp index 6c5327e04..780b1d99d 100644 --- a/openfpga/src/annotation/openfpga_annotate_routing.cpp +++ b/openfpga/src/annotation/openfpga_annotate_routing.cpp @@ -2,10 +2,10 @@ * This file includes functions that are used to annotate routing results * from VPR to OpenFPGA *******************************************************************/ -/* Headers from vtrutil library */ #include "openfpga_annotate_routing.h" #include "annotate_routing.h" +#include "old_traceback.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -134,14 +134,15 @@ void annotate_rr_node_previous_nodes( /* Cache Previous nodes */ RRNodeId prev_node = RRNodeId::INVALID(); - t_trace* tptr = routing_ctx.trace[net_id].head; + t_trace* tptr = TracebackCompat::traceback_from_route_tree( + routing_ctx.route_trees[net_id].value()); + t_trace* head = tptr; while (tptr != nullptr) { RRNodeId rr_node = RRNodeId(tptr->index); /* Find the right previous node */ prev_node = find_previous_node_from_routing_traces( - device_ctx.rr_graph, routing_ctx.trace[net_id].head, prev_node, - rr_node); + device_ctx.rr_graph, head, prev_node, rr_node); /* Only update mapped nodes */ if (prev_node) { @@ -156,6 +157,7 @@ void annotate_rr_node_previous_nodes( /* Move on to the next */ tptr = tptr->next; } + free_traceback(head); } VTR_LOG("Done with %d nodes mapping\n", counter); diff --git a/openfpga/src/annotation/vpr_placement_annotation.cpp b/openfpga/src/annotation/vpr_placement_annotation.cpp index 9d7e73836..4967732b0 100644 --- a/openfpga/src/annotation/vpr_placement_annotation.cpp +++ b/openfpga/src/annotation/vpr_placement_annotation.cpp @@ -32,8 +32,9 @@ void VprPlacementAnnotation::init_mapped_blocks(const DeviceGrid& grids) { for (size_t x = 0; x < grids.width(); ++x) { for (size_t y = 0; y < grids.height(); ++y) { /* Deposit invalid ids and we will fill later */ - blocks_[x][y].resize(grids[x][y].type->capacity, - ClusterBlockId::INVALID()); + blocks_[x][y].resize( + grids.get_physical_type(t_physical_tile_loc(x, y, 0))->capacity, + ClusterBlockId::INVALID()); } } } diff --git a/openfpga/src/base/netlist_manager.h b/openfpga/src/base/netlist_manager.h index 3e895ff3e..8f94e9521 100644 --- a/openfpga/src/base/netlist_manager.h +++ b/openfpga/src/base/netlist_manager.h @@ -39,6 +39,7 @@ class NetlistManager { SUBMODULE_NETLIST, LOGIC_BLOCK_NETLIST, ROUTING_MODULE_NETLIST, + TILE_MODULE_NETLIST, TOP_MODULE_NETLIST, TESTBENCH_NETLIST, NUM_NETLIST_TYPES diff --git a/openfpga/src/base/openfpga_bitstream_command_template.h b/openfpga/src/base/openfpga_bitstream_command_template.h index b11c058cd..bc781dcdc 100644 --- a/openfpga/src/base/openfpga_bitstream_command_template.h +++ b/openfpga/src/base/openfpga_bitstream_command_template.h @@ -200,6 +200,11 @@ ShellCommandId add_write_fabric_bitstream_command_template( "Keep don't care bits in bitstream file; If not enabled, don't care bits " "are converted to logic '0' or '1'"); + /* Add an option '--wl_incremental_order' */ + shell_cmd.add_option( + "wl_decremental_order", false, + "Generate bitstream in WL decremental addressing order if supported"); + /* Add an option '--no_time_stamp' */ shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files"); diff --git a/openfpga/src/base/openfpga_bitstream_template.h b/openfpga/src/base/openfpga_bitstream_template.h index de01d1df9..196d9ef30 100644 --- a/openfpga/src/base/openfpga_bitstream_template.h +++ b/openfpga/src/base/openfpga_bitstream_template.h @@ -91,6 +91,7 @@ int write_fabric_bitstream_template(const T& openfpga_ctx, const Command& cmd, CommandOptionId opt_file_format = cmd.option("format"); CommandOptionId opt_fast_config = cmd.option("fast_configuration"); CommandOptionId opt_keep_dont_care_bits = cmd.option("keep_dont_care_bits"); + CommandOptionId opt_wl_decremental_order = cmd.option("wl_decremental_order"); CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); /* Write fabric bitstream if required */ @@ -127,6 +128,7 @@ int write_fabric_bitstream_template(const T& openfpga_ctx, const Command& cmd, cmd_context.option_value(cmd, opt_file), cmd_context.option_enable(cmd, opt_fast_config), cmd_context.option_enable(cmd, opt_keep_dont_care_bits), + !cmd_context.option_enable(cmd, opt_wl_decremental_order), !cmd_context.option_enable(cmd, opt_no_time_stamp), cmd_context.option_enable(cmd, opt_verbose)); } diff --git a/openfpga/src/base/openfpga_build_fabric_template.h b/openfpga/src/base/openfpga_build_fabric_template.h index a42b51533..39e181b6d 100644 --- a/openfpga/src/base/openfpga_build_fabric_template.h +++ b/openfpga/src/base/openfpga_build_fabric_template.h @@ -6,6 +6,7 @@ #include "build_device_module.h" #include "build_fabric_global_port_info.h" #include "build_fabric_io_location_map.h" +#include "build_fpga_core_wrapper_module.h" #include "command.h" #include "command_context.h" #include "command_exit_codes.h" @@ -14,7 +15,10 @@ #include "fabric_hierarchy_writer.h" #include "fabric_key_writer.h" #include "globals.h" +#include "openfpga_naming.h" #include "read_xml_fabric_key.h" +#include "read_xml_io_name_map.h" +#include "read_xml_tile_config.h" #include "vtr_log.h" #include "vtr_time.h" @@ -65,21 +69,23 @@ void compress_routing_hierarchy_template(T& openfpga_ctx, "Detected %lu unique switch blocks from a total of %d (compression " "rate=%.2f%)\n", openfpga_ctx.device_rr_gsb().get_num_sb_unique_module(), - find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb()), - 100. * - ((float)find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb()) / - (float)openfpga_ctx.device_rr_gsb().get_num_sb_unique_module() - - 1.)); + find_device_rr_gsb_num_sb_modules(openfpga_ctx.device_rr_gsb(), + g_vpr_ctx.device().rr_graph), + 100. * ((float)find_device_rr_gsb_num_sb_modules( + openfpga_ctx.device_rr_gsb(), g_vpr_ctx.device().rr_graph) / + (float)openfpga_ctx.device_rr_gsb().get_num_sb_unique_module() - + 1.)); VTR_LOG( "Detected %lu unique general switch blocks from a total of %d (compression " "rate=%.2f%)\n", openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module(), - find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb()), - 100. * - ((float)find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb()) / - (float)openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module() - - 1.)); + find_device_rr_gsb_num_gsb_modules(openfpga_ctx.device_rr_gsb(), + g_vpr_ctx.device().rr_graph), + 100. * ((float)find_device_rr_gsb_num_gsb_modules( + openfpga_ctx.device_rr_gsb(), g_vpr_ctx.device().rr_graph) / + (float)openfpga_ctx.device_rr_gsb().get_num_gsb_unique_module() - + 1.)); } /******************************************************************** @@ -95,8 +101,31 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, cmd.option("generate_random_fabric_key"); CommandOptionId opt_write_fabric_key = cmd.option("write_fabric_key"); CommandOptionId opt_load_fabric_key = cmd.option("load_fabric_key"); + CommandOptionId opt_group_tile = cmd.option("group_tile"); + CommandOptionId opt_group_config_block = cmd.option("group_config_block"); CommandOptionId opt_verbose = cmd.option("verbose"); + /* Report conflicts with options: + * - group tile does not support duplicate_grid_pin + * - group tile requires compress_routing to be enabled + */ + if (cmd_context.option_enable(cmd, opt_group_tile)) { + if (cmd_context.option_enable(cmd, opt_duplicate_grid_pin)) { + VTR_LOG_ERROR( + "Option '%s' requires options '%s' to be disabled due to a conflict!\n", + cmd.option_name(opt_group_tile).c_str(), + cmd.option_name(opt_duplicate_grid_pin).c_str()); + return CMD_EXEC_FATAL_ERROR; + } + if (!cmd_context.option_enable(cmd, opt_compress_routing)) { + VTR_LOG_ERROR( + "Option '%s' requires options '%s' to be enabled due to a conflict!\n", + cmd.option_name(opt_group_tile).c_str(), + cmd.option_name(opt_compress_routing).c_str()); + return CMD_EXEC_FATAL_ERROR; + } + } + if (true == cmd_context.option_enable(cmd, opt_compress_routing)) { compress_routing_hierarchy_template( openfpga_ctx, cmd_context.option_enable(cmd, opt_verbose)); @@ -122,14 +151,34 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, VTR_LOG("\n"); + /* Build tile-level information: + * - This feature only supports when compress routing is enabled + * - Read the tile organization configuration file + * - Build tile info + */ + TileConfig tile_config; + if (cmd_context.option_enable(cmd, opt_group_tile)) { + if (!cmd_context.option_enable(cmd, opt_compress_routing)) { + VTR_LOG_ERROR( + "Group tile is applicable only when compress routing is enabled!\n"); + return CMD_EXEC_FATAL_ERROR; + } + curr_status = read_xml_tile_config( + cmd_context.option_value(cmd, opt_group_tile).c_str(), tile_config); + if (CMD_EXEC_SUCCESS != curr_status) { + return CMD_EXEC_FATAL_ERROR; + } + } + curr_status = build_device_module_graph( openfpga_ctx.mutable_module_graph(), openfpga_ctx.mutable_decoder_lib(), openfpga_ctx.mutable_blwl_shift_register_banks(), - const_cast(openfpga_ctx), g_vpr_ctx.device(), - cmd_context.option_enable(cmd, opt_frame_view), + openfpga_ctx.mutable_fabric_tile(), const_cast(openfpga_ctx), + g_vpr_ctx.device(), cmd_context.option_enable(cmd, opt_frame_view), cmd_context.option_enable(cmd, opt_compress_routing), cmd_context.option_enable(cmd, opt_duplicate_grid_pin), - predefined_fabric_key, + predefined_fabric_key, tile_config, + cmd_context.option_enable(cmd, opt_group_config_block), cmd_context.option_enable(cmd, opt_gen_random_fabric_key), cmd_context.option_enable(cmd, opt_verbose)); @@ -141,7 +190,8 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, /* Build I/O location map */ openfpga_ctx.mutable_io_location_map() = build_fabric_io_location_map( - openfpga_ctx.module_graph(), g_vpr_ctx.device().grid); + openfpga_ctx.module_graph(), g_vpr_ctx.device().grid, + cmd_context.option_enable(cmd, opt_group_tile)); /* Build fabric global port information */ openfpga_ctx.mutable_fabric_global_port_info() = @@ -154,11 +204,11 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, std::string fkey_fname = cmd_context.option_value(cmd, opt_write_fabric_key); VTR_ASSERT(false == fkey_fname.empty()); - curr_status = - write_fabric_key_to_xml_file(openfpga_ctx.module_graph(), fkey_fname, - openfpga_ctx.arch().config_protocol, - openfpga_ctx.blwl_shift_register_banks(), - cmd_context.option_enable(cmd, opt_verbose)); + curr_status = write_fabric_key_to_xml_file( + openfpga_ctx.module_graph(), fkey_fname, + openfpga_ctx.arch().config_protocol, + openfpga_ctx.blwl_shift_register_banks(), false, + cmd_context.option_enable(cmd, opt_verbose)); /* If there is any error, final status cannot be overwritten by a success * flag */ if (CMD_EXEC_SUCCESS != curr_status) { @@ -169,6 +219,32 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, return final_status; } +/******************************************************************** + * Write fabric key of the module graph for FPGA device to a file + *******************************************************************/ +template +int write_fabric_key_template(const T& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { + CommandOptionId opt_verbose = cmd.option("verbose"); + CommandOptionId opt_include_module_keys = cmd.option("include_module_keys"); + + /* Check the option '--file' is enabled or not + * Actually, it must be enabled as the shell interface will check + * before reaching this fuction + */ + CommandOptionId opt_file = cmd.option("file"); + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); + VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty()); + + /* Write fabric key to a file */ + return write_fabric_key_to_xml_file( + openfpga_ctx.module_graph(), cmd_context.option_value(cmd, opt_file), + openfpga_ctx.arch().config_protocol, + openfpga_ctx.blwl_shift_register_banks(), + cmd_context.option_enable(cmd, opt_include_module_keys), + cmd_context.option_enable(cmd, opt_verbose)); +} + /******************************************************************** * Write hierarchy of the module graph for FPGA device to a file *******************************************************************/ @@ -231,6 +307,35 @@ int write_fabric_io_info_template(const T& openfpga_ctx, const Command& cmd, cmd_context.option_enable(cmd, opt_verbose)); } +/******************************************************************** + * Add fpga_core module to the module graph + *******************************************************************/ +template +int add_fpga_core_to_fabric_template(T& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { + CommandOptionId opt_frame_view = cmd.option("frame_view"); + bool frame_view = cmd_context.option_enable(cmd, opt_frame_view); + CommandOptionId opt_verbose = cmd.option("verbose"); + bool verbose_output = cmd_context.option_enable(cmd, opt_verbose); + + CommandOptionId opt_inst_name = cmd.option("instance_name"); + std::string core_inst_name = generate_fpga_core_instance_name(); + if (true == cmd_context.option_enable(cmd, opt_inst_name)) { + core_inst_name = cmd_context.option_value(cmd, opt_inst_name); + } + + /* Handle I/O naming rules if defined */ + CommandOptionId opt_io_naming = cmd.option("io_naming"); + if (true == cmd_context.option_enable(cmd, opt_io_naming)) { + read_xml_io_name_map(cmd_context.option_value(cmd, opt_io_naming).c_str(), + openfpga_ctx.mutable_io_name_map()); + } + + return add_fpga_core_to_device_module_graph( + openfpga_ctx.mutable_module_graph(), openfpga_ctx.io_name_map(), + core_inst_name, frame_view, verbose_output); +} + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index 9455ed916..9473ecc65 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -10,7 +10,9 @@ #include "device_rr_gsb.h" #include "fabric_bitstream.h" #include "fabric_global_port_info.h" +#include "fabric_tile.h" #include "io_location_map.h" +#include "io_name_map.h" #include "memory_bank_shift_register_banks.h" #include "module_manager.h" #include "mux_library.h" @@ -104,6 +106,8 @@ class OpenfpgaContext : public Context { const openfpga::IoLocationMap& io_location_map() const { return io_location_map_; } + const openfpga::IoNameMap& io_name_map() const { return io_name_map_; } + const openfpga::FabricTile& fabric_tile() const { return fabric_tile_; } const openfpga::FabricGlobalPortInfo& fabric_global_port_info() const { return fabric_global_port_info_; } @@ -162,6 +166,8 @@ class OpenfpgaContext : public Context { openfpga::IoLocationMap& mutable_io_location_map() { return io_location_map_; } + openfpga::IoNameMap& mutable_io_name_map() { return io_name_map_; } + openfpga::FabricTile& mutable_fabric_tile() { return fabric_tile_; } openfpga::FabricGlobalPortInfo& mutable_fabric_global_port_info() { return fabric_global_port_info_; } @@ -216,6 +222,8 @@ class OpenfpgaContext : public Context { /* Fabric module graph */ openfpga::ModuleManager module_graph_; openfpga::IoLocationMap io_location_map_; + openfpga::IoNameMap io_name_map_; + openfpga::FabricTile fabric_tile_; openfpga::FabricGlobalPortInfo fabric_global_port_info_; /* Bitstream database */ diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 38dabf0e8..1623df96f 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -225,12 +225,18 @@ std::string generate_segment_wire_mid_output_name( /********************************************************************* * Generate the module name for a memory sub-circuit + * If this is a module just to feed through memory lines, use a special name ********************************************************************/ std::string generate_memory_module_name(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const CircuitModelId& sram_model, - const std::string& postfix) { - return std::string(circuit_lib.model_name(circuit_model) + "_" + + const std::string& postfix, + const bool& feedthrough_memory) { + std::string mid_name; + if (feedthrough_memory) { + mid_name = "feedthrough_"; + } + return std::string(circuit_lib.model_name(circuit_model) + "_" + mid_name + circuit_lib.model_name(sram_model) + postfix); } @@ -497,6 +503,40 @@ std::string generate_switch_block_module_name( std::string("_")); } +/********************************************************************* + * Generate the module name for a tile module with a given coordinate + *********************************************************************/ +std::string generate_tile_module_name(const vtr::Point& tile_coord) { + return std::string("tile_" + std::to_string(tile_coord.x()) + "__" + + std::to_string(tile_coord.y()) + "_"); +} + +/********************************************************************* + * Generate the port name for a tile. Note that use the index to make the tile + *port name unique! + *********************************************************************/ +std::string generate_tile_module_port_name(const std::string& prefix, + const std::string& port_name) { + return prefix + std::string("_") + port_name; +} + +/********************************************************************* + * Generate the netlist name of a grid block + **********************************************************************/ +std::string generate_tile_module_netlist_name(const std::string& block_name, + const std::string& postfix) { + return block_name + postfix; +} + +/********************************************************************* + * Generate the module name of a physical memory module + **********************************************************************/ +std::string generate_physical_memory_module_name(const std::string& prefix, + const size_t& mem_size) { + return prefix + std::string("_config_group_mem_size") + + std::to_string(mem_size); +} + /********************************************************************* * Generate the module name for a connection block with a given coordinate *********************************************************************/ @@ -709,6 +749,26 @@ std::string generate_sram_port_name( std::string port_name; switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: + /* Two types of ports are available: + * (1) BL indicates the mem port + * (2) BLB indicates the inverted mem port + * + * mem mem_inv + * [0] [0] + * | | + * v v + * +----------------+ + * | Virtual Mem | + * +----------------+ + */ + if (CIRCUIT_MODEL_PORT_BL == port_type) { + port_name = std::string(MEMORY_FEEDTHROUGH_DATA_IN_PORT_NAME); + } else { + VTR_ASSERT(CIRCUIT_MODEL_PORT_BLB == port_type); + port_name = std::string(MEMORY_FEEDTHROUGH_DATA_IN_INV_PORT_NAME); + } + break; case CONFIG_MEM_SCAN_CHAIN: /* Two types of ports are available: * (1) Head of a chain of Configuration-chain Flip-Flops (CCFFs), enabled @@ -1040,8 +1100,12 @@ std::string generate_sb_mux_instance_name(const std::string& prefix, std::string generate_sb_memory_instance_name(const std::string& prefix, const e_side& sb_side, const size_t& track_id, - const std::string& postfix) { + const std::string& postfix, + const bool& feedthrough_memory) { std::string instance_name(prefix); + if (feedthrough_memory) { + instance_name = std::string("feedthrough_") + instance_name; + } instance_name += SideManager(sb_side).to_string(); instance_name += std::string("_track_") + std::to_string(track_id); instance_name += postfix; @@ -1078,8 +1142,12 @@ std::string generate_cb_mux_instance_name(const std::string& prefix, std::string generate_cb_memory_instance_name(const std::string& prefix, const e_side& cb_side, const size_t& pin_id, - const std::string& postfix) { + const std::string& postfix, + const bool& feedthrough_memory) { std::string instance_name(prefix); + if (feedthrough_memory) { + instance_name = std::string("feedthrough_") + instance_name; + } instance_name += SideManager(cb_side).to_string(); instance_name += std::string("_ipin_") + std::to_string(pin_id); @@ -1134,8 +1202,10 @@ std::string generate_pb_mux_instance_name(const std::string& prefix, ********************************************************************/ std::string generate_pb_memory_instance_name(const std::string& prefix, t_pb_graph_pin* pb_graph_pin, - const std::string& postfix) { - std::string instance_name(prefix); + const std::string& postfix, + const bool& feedthrough_memory) { + std::string mid_name = feedthrough_memory ? "virtual_" : ""; + std::string instance_name(mid_name + prefix); instance_name += std::string(pb_graph_pin->parent_node->pb_type->name); if (IN_PORT == pb_graph_pin->port->type) { @@ -1399,6 +1469,22 @@ std::string generate_fpga_top_module_name() { return std::string(FPGA_TOP_MODULE_NAME); } +/********************************************************************* + * Generate the module name for the fpga core module + * We give a fixed name here, because it is independent from benchmark file + ********************************************************************/ +std::string generate_fpga_core_module_name() { + return std::string(FPGA_CORE_MODULE_NAME); +} + +/********************************************************************* + * Generate the module name for the fpga core module + * We give a fixed name here, because it is independent from benchmark file + ********************************************************************/ +std::string generate_fpga_core_instance_name() { + return std::string(FPGA_CORE_INSTANCE_NAME); +} + /********************************************************************* * Generate the netlist name for the top-level module * The top-level module is actually the FPGA fabric @@ -1408,6 +1494,15 @@ std::string generate_fpga_top_netlist_name(const std::string& postfix) { return std::string(FPGA_TOP_MODULE_NAME + postfix); } +/********************************************************************* + * Generate the netlist name for the top-level module + * The top-level module is actually the FPGA fabric + * We give a fixed name here, because it is independent from benchmark file + ********************************************************************/ +std::string generate_fpga_core_netlist_name(const std::string& postfix) { + return std::string(FPGA_CORE_MODULE_NAME + postfix); +} + /********************************************************************* * Generate the module name for a constant generator * either VDD or GND, depending on the input argument diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index 8e6fb631a..4a1d35e8e 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -68,7 +68,8 @@ std::string generate_segment_wire_mid_output_name( std::string generate_memory_module_name(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const CircuitModelId& sram_model, - const std::string& postfix); + const std::string& postfix, + const bool& feedthrough_memory = false); std::string generate_routing_block_netlist_name(const std::string& prefix, const size_t& block_id, @@ -110,33 +111,42 @@ std::string generate_switch_block_module_name( std::string generate_connection_block_module_name( const t_rr_type& cb_type, const vtr::Point& coordinate); +std::string generate_tile_module_name(const vtr::Point& tile_coord); + +std::string generate_tile_module_port_name(const std::string& prefix, + const std::string& port_name); + +std::string generate_tile_module_netlist_name(const std::string& block_name, + const std::string& postfix); + +std::string generate_physical_memory_module_name(const std::string& prefix, + const size_t& mem_size); + std::string generate_sb_mux_instance_name(const std::string& prefix, const e_side& sb_side, const size_t& track_id, const std::string& postfix); -std::string generate_sb_memory_instance_name(const std::string& prefix, - const e_side& sb_side, - const size_t& track_id, - const std::string& postfix); +std::string generate_sb_memory_instance_name( + const std::string& prefix, const e_side& sb_side, const size_t& track_id, + const std::string& postfix, const bool& feedthrough_memory = false); std::string generate_cb_mux_instance_name(const std::string& prefix, const e_side& cb_side, const size_t& pin_id, const std::string& postfix); -std::string generate_cb_memory_instance_name(const std::string& prefix, - const e_side& cb_side, - const size_t& pin_id, - const std::string& postfix); +std::string generate_cb_memory_instance_name( + const std::string& prefix, const e_side& cb_side, const size_t& pin_id, + const std::string& postfix, const bool& feedthrough_memory = false); std::string generate_pb_mux_instance_name(const std::string& prefix, t_pb_graph_pin* pb_graph_pin, const std::string& postfix); -std::string generate_pb_memory_instance_name(const std::string& prefix, - t_pb_graph_pin* pb_graph_pin, - const std::string& postfix); +std::string generate_pb_memory_instance_name( + const std::string& prefix, t_pb_graph_pin* pb_graph_pin, + const std::string& postfix, const bool& feedthrough_memory = false); std::string generate_grid_port_name(const size_t& width, const size_t& height, const int& subtile_index, @@ -258,8 +268,14 @@ std::string generate_fpga_global_io_port_name( std::string generate_fpga_top_module_name(); +std::string generate_fpga_core_module_name(); + +std::string generate_fpga_core_instance_name(); + std::string generate_fpga_top_netlist_name(const std::string& postfix); +std::string generate_fpga_core_netlist_name(const std::string& postfix); + std::string generate_const_value_module_name(const size_t& const_val); std::string generate_const_value_module_output_port_name( diff --git a/openfpga/src/base/openfpga_pb_pin_fixup.cpp b/openfpga/src/base/openfpga_pb_pin_fixup.cpp index 0e55f8f9d..e17a22183 100644 --- a/openfpga/src/base/openfpga_pb_pin_fixup.cpp +++ b/openfpga/src/base/openfpga_pb_pin_fixup.cpp @@ -34,12 +34,13 @@ namespace openfpga { static void update_cluster_pin_with_post_routing_results( const DeviceContext& device_ctx, const ClusteringContext& clustering_ctx, const VprRoutingAnnotation& vpr_routing_annotation, - VprClusteringAnnotation& vpr_clustering_annotation, + VprClusteringAnnotation& vpr_clustering_annotation, const size_t& layer, const vtr::Point& grid_coord, const ClusterBlockId& blk_id, const e_side& border_side, const size_t& z, const bool& verbose) { /* Handle each pin */ auto logical_block = clustering_ctx.clb_nlist.block_type(blk_id); - auto physical_tile = device_ctx.grid[grid_coord.x()][grid_coord.y()].type; + auto physical_tile = device_ctx.grid.get_physical_type( + t_physical_tile_loc(grid_coord.x(), grid_coord.y(), layer)); for (int j = 0; j < logical_block->pb_type->num_pins; j++) { /* Get the ptc num for the pin in rr_graph, we need t consider the z offset @@ -85,7 +86,8 @@ static void update_cluster_pin_with_post_routing_results( /* Find the net mapped to this pin in routing results */ const RRNodeId& rr_node = device_ctx.rr_graph.node_lookup().find_node( - grid_coord.x(), grid_coord.y(), rr_node_type, physical_pin, pin_side); + layer, grid_coord.x(), grid_coord.y(), rr_node_type, physical_pin, + pin_side); if (false == device_ctx.rr_graph.valid_node(rr_node)) { continue; } @@ -191,16 +193,21 @@ void update_pb_pin_with_post_routing_results( * post-routing clustering result sync-up */ vpr_clustering_annotation.clear_net_remapping(); + size_t layer = 0; /* Update the core logic (center blocks of the FPGA) */ for (size_t x = 1; x < device_ctx.grid.width() - 1; ++x) { for (size_t y = 1; y < device_ctx.grid.height() - 1; ++y) { + t_physical_tile_type_ptr phy_tile = + device_ctx.grid.get_physical_type(t_physical_tile_loc(x, y, layer)); /* Bypass the EMPTY tiles */ - if (true == is_empty_type(device_ctx.grid[x][y].type)) { + if (true == is_empty_type(phy_tile)) { continue; } /* Get the mapped blocks to this grid */ - for (const ClusterBlockId& cluster_blk_id : - placement_ctx.grid_blocks[x][y].blocks) { + for (int isubtile = 0; isubtile < phy_tile->capacity; ++isubtile) { + ClusterBlockId cluster_blk_id = + placement_ctx.grid_blocks.block_at_location( + {(int)x, (int)y, (int)isubtile, (int)layer}); /* Skip invalid ids */ if (ClusterBlockId::INVALID() == cluster_blk_id) { continue; @@ -210,8 +217,9 @@ void update_pb_pin_with_post_routing_results( vtr::Point grid_coord(x, y); update_cluster_pin_with_post_routing_results( device_ctx, clustering_ctx, vpr_routing_annotation, - vpr_clustering_annotation, grid_coord, cluster_blk_id, NUM_SIDES, - placement_ctx.block_locs[cluster_blk_id].loc.sub_tile, verbose); + vpr_clustering_annotation, layer, grid_coord, cluster_blk_id, + NUM_SIDES, placement_ctx.block_locs[cluster_blk_id].loc.sub_tile, + verbose); } } } @@ -222,14 +230,18 @@ void update_pb_pin_with_post_routing_results( for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { for (const vtr::Point& io_coord : io_coordinates[io_side]) { + t_physical_tile_type_ptr phy_tile_type = + device_ctx.grid.get_physical_type( + t_physical_tile_loc(io_coord.x(), io_coord.y(), layer)); /* Bypass EMPTY grid */ - if (true == - is_empty_type(device_ctx.grid[io_coord.x()][io_coord.y()].type)) { + if (true == is_empty_type(phy_tile_type)) { continue; } /* Get the mapped blocks to this grid */ - for (const ClusterBlockId& cluster_blk_id : - placement_ctx.grid_blocks[io_coord.x()][io_coord.y()].blocks) { + for (int isubtile = 0; isubtile < phy_tile_type->capacity; ++isubtile) { + ClusterBlockId cluster_blk_id = + placement_ctx.grid_blocks.block_at_location( + {(int)io_coord.x(), (int)io_coord.y(), (int)isubtile, (int)layer}); /* Skip invalid ids */ if (ClusterBlockId::INVALID() == cluster_blk_id) { continue; @@ -237,7 +249,7 @@ void update_pb_pin_with_post_routing_results( /* Update on I/O grid */ update_cluster_pin_with_post_routing_results( device_ctx, clustering_ctx, vpr_routing_annotation, - vpr_clustering_annotation, io_coord, cluster_blk_id, io_side, + vpr_clustering_annotation, layer, io_coord, cluster_blk_id, io_side, placement_ctx.block_locs[cluster_blk_id].loc.sub_tile, verbose); } } diff --git a/openfpga/src/base/openfpga_sdc_template.h b/openfpga/src/base/openfpga_sdc_template.h index fe3a25be6..64ac33d9e 100644 --- a/openfpga/src/base/openfpga_sdc_template.h +++ b/openfpga/src/base/openfpga_sdc_template.h @@ -96,11 +96,12 @@ int write_pnr_sdc_template(const T& openfpga_ctx, const Command& cmd, /* Execute only when sdc is enabled */ if (true == options.generate_sdc_pnr()) { - print_pnr_sdc( + return print_pnr_sdc( options, g_vpr_ctx.device(), openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.device_rr_gsb(), openfpga_ctx.module_graph(), - openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib, - openfpga_ctx.fabric_global_port_info(), openfpga_ctx.simulation_setting(), + openfpga_ctx.fabric_tile(), openfpga_ctx.device_rr_gsb(), + openfpga_ctx.module_graph(), openfpga_ctx.mux_lib(), + openfpga_ctx.arch().circuit_lib, openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.simulation_setting(), openfpga_ctx.flow_manager().compress_routing()); } diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index abe17dfeb..55b0ae52f 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -405,6 +405,20 @@ ShellCommandId add_build_fabric_command_template( "write_fabric_key", false, "output current fabric key to a file"); shell_cmd.set_option_require_value(opt_write_fkey, openfpga::OPT_STRING); + /* Add an option '--group_tile' */ + CommandOptionId opt_group_tile = shell_cmd.add_option( + "group_tile", false, + "group programmable blocks and routing blocks into tiles. This helps to " + "reduce the number of blocks at top-level"); + shell_cmd.set_option_require_value(opt_group_tile, openfpga::OPT_STRING); + + /* Add an option '--group_config_block' */ + shell_cmd.add_option("group_config_block", false, + "group configuration memory blocks under CLB/SB/CB " + "blocks etc. This helps to " + "reduce optimize the density of configuration memory " + "through physical design"); + /* Add an option '--generate_random_fabric_key' */ shell_cmd.add_option("generate_random_fabric_key", false, "Create a random fabric key which will shuffle the " @@ -692,6 +706,86 @@ ShellCommandId add_route_clock_rr_graph_command_template( return shell_cmd_id; } +/******************************************************************** + * - Add a command to Shell environment: add_fpga_core_to_fabric + * - Add associated options + * - Add command dependency + *******************************************************************/ +template +ShellCommandId add_add_fpga_core_to_fabric_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("add_fpga_core_to_fabric"); + + /* Add an option '--io_naming'*/ + CommandOptionId opt_io_naming = shell_cmd.add_option( + "io_naming", false, "specify the file path to the I/O naming rules"); + shell_cmd.set_option_require_value(opt_io_naming, openfpga::OPT_STRING); + + /* Add an option '--instance_name'*/ + CommandOptionId opt_inst_name = shell_cmd.add_option( + "instance_name", false, "specify the instance of fpga_core under fpga_top"); + shell_cmd.set_option_require_value(opt_inst_name, openfpga::OPT_STRING); + + /* Add an option '--verbose' */ + shell_cmd.add_option( + "frame_view", false, + "Build only frame view of the fabric (nets are skipped)"); + /* Add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "Show verbose outputs"); + + /* Add command 'pb_pin_fixup' to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, + "Add fpga_core as an intermediate layer to FPGA fabric. After this " + "command, the fpga_top will remain the top-level module while there is a " + "new module fpga_core under it. Under fpga_core, there will be the " + "detailed building blocks", + hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, + add_fpga_core_to_fabric_template); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + +/******************************************************************** + * - Add a command to Shell environment: write_fabric_key + * - Add associated options + * - Add command dependency + *******************************************************************/ +template +ShellCommandId add_write_fabric_key_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("write_fabric_key"); + /* Add an option '--file' in short '-f'*/ + CommandOptionId opt_file = + shell_cmd.add_option("file", true, "file path to the fabric key XML"); + shell_cmd.set_option_short_name(opt_file, "f"); + shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); + + /* Add an option '--include_module_keys'*/ + shell_cmd.add_option("include_module_keys", false, + "Include module-level keys"); + shell_cmd.add_option("verbose", false, "Show verbose outputs"); + + /* Add command to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "write fabric key of the FPGA fabric to file", hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_const_execute_function(shell_cmd_id, + write_fabric_key_template); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + template void add_setup_command_templates(openfpga::Shell& shell, const bool& hidden = false) { @@ -859,6 +953,7 @@ void add_setup_command_templates(openfpga::Shell& shell, lut_tt_fixup_dependent_cmds.push_back(vpr_cmd_id); add_lut_truth_table_fixup_command_template( shell, openfpga_setup_cmd_class, lut_tt_fixup_dependent_cmds, hidden); + /******************************** * Command 'build_fabric' */ @@ -869,6 +964,27 @@ void add_setup_command_templates(openfpga::Shell& shell, ShellCommandId build_fabric_cmd_id = add_build_fabric_command_template( shell, openfpga_setup_cmd_class, build_fabric_dependent_cmds, hidden); + /******************************** + * Command 'add_fpga_core_to_fabric' + */ + /* The command should NOT be executed before + * 'build_fabric' */ + std::vector add_fpga_core_to_fabric_dependent_cmds; + add_fpga_core_to_fabric_dependent_cmds.push_back(build_fabric_cmd_id); + add_add_fpga_core_to_fabric_command_template( + shell, openfpga_setup_cmd_class, add_fpga_core_to_fabric_dependent_cmds, + hidden); + + /******************************** + * Command 'write_fabric_key' + */ + /* The 'write_fabric_key' command should NOT be executed before + * 'build_fabric' */ + std::vector write_fabric_key_dependent_cmds; + write_fabric_key_dependent_cmds.push_back(build_fabric_cmd_id); + add_write_fabric_key_command_template( + shell, openfpga_setup_cmd_class, write_fabric_key_dependent_cmds, hidden); + /******************************** * Command 'write_fabric_hierarchy' */ diff --git a/openfpga/src/base/openfpga_verilog_command_template.h b/openfpga/src/base/openfpga_verilog_command_template.h index 266afc6d8..fa40faff9 100644 --- a/openfpga/src/base/openfpga_verilog_command_template.h +++ b/openfpga/src/base/openfpga_verilog_command_template.h @@ -92,6 +92,13 @@ ShellCommandId add_write_full_testbench_command_template( shell_cmd.set_option_short_name(output_opt, "f"); shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); + /* add an option '--dut_module'*/ + CommandOptionId dut_module_opt = shell_cmd.add_option( + "dut_module", false, + "specify the module name of DUT to be used in the testbench. Can be either " + "fpga_top or fpga_core. By default, it is fpga_top."); + shell_cmd.set_option_require_value(dut_module_opt, openfpga::OPT_STRING); + /* add an option '--bitstream'*/ CommandOptionId bitstream_opt = shell_cmd.add_option( "bitstream", true, "specify the bitstream to be loaded in the testbench"); @@ -196,6 +203,13 @@ ShellCommandId add_write_preconfigured_fabric_wrapper_command_template( "specify the file path to the fabric hdl netlist"); shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING); + /* add an option '--dut_module'*/ + CommandOptionId dut_module_opt = shell_cmd.add_option( + "dut_module", false, + "specify the module name of DUT to be used in the testbench. Can be either " + "fpga_top or fpga_core. By default, it is fpga_top."); + shell_cmd.set_option_require_value(dut_module_opt, openfpga::OPT_STRING); + /* add an option '--pin_constraints_file in short '-pcf' */ CommandOptionId pcf_opt = shell_cmd.add_option("pin_constraints_file", false, @@ -251,6 +265,82 @@ ShellCommandId add_write_preconfigured_fabric_wrapper_command_template( return shell_cmd_id; } +/******************************************************************** + * - add a command to shell environment: write mock fpga wrapper + * - add associated options + * - add command dependency + *******************************************************************/ +template +ShellCommandId add_write_mock_fpga_wrapper_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("write_mock_fpga_wrapper"); + + /* add an option '--file' in short '-f'*/ + CommandOptionId output_opt = shell_cmd.add_option( + "file", true, "specify the output directory for hdl netlists"); + shell_cmd.set_option_short_name(output_opt, "f"); + shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING); + + /* add an option '--pin_constraints_file in short '-pcf' */ + CommandOptionId pcf_opt = + shell_cmd.add_option("pin_constraints_file", false, + "specify the file path to the pin constraints"); + shell_cmd.set_option_short_name(pcf_opt, "pcf"); + shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING); + + /* add an option '--top_module'*/ + CommandOptionId top_module_opt = + shell_cmd.add_option("top_module", false, + "specify the top-level module name to be used in the " + "wrapper, which matters the I/O names. Can be either " + "fpga_top or fpga_core. By default, it is fpga_top."); + shell_cmd.set_option_require_value(top_module_opt, openfpga::OPT_STRING); + + /* add an option '--bus_group_file in short '-bgf' */ + CommandOptionId bgf_opt = shell_cmd.add_option( + "bus_group_file", false, "specify the file path to the group pins to bus"); + shell_cmd.set_option_short_name(bgf_opt, "bgf"); + shell_cmd.set_option_require_value(bgf_opt, openfpga::OPT_STRING); + + /* Add an option '--use_relative_path' */ + shell_cmd.add_option( + "use_relative_path", false, + "Force to use relative path in netlists when including other netlists"); + + /* add an option '--explicit_port_mapping' */ + shell_cmd.add_option("explicit_port_mapping", false, + "use explicit port mapping in verilog netlists"); + + /* Add an option '--default_net_type' */ + CommandOptionId default_net_type_opt = shell_cmd.add_option( + "default_net_type", false, + "Set the default net type for Verilog netlists. Default value is 'none'"); + shell_cmd.set_option_require_value(default_net_type_opt, + openfpga::OPT_STRING); + + /* Add an option '--no_time_stamp' */ + shell_cmd.add_option("no_time_stamp", false, + "Do not print a time stamp in the output files"); + + /* add an option '--verbose' */ + shell_cmd.add_option("verbose", false, "enable verbose output"); + + /* add command to the shell */ + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, + "generate a wrapper of a mock fpga fabric mapped with applications", + hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_execute_function(shell_cmd_id, + write_mock_fpga_wrapper_template); + + /* add command dependency to the shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + /******************************************************************** * - Add a command to Shell environment: write preconfigured testbench * - Add associated options @@ -435,6 +525,17 @@ void add_verilog_command_templates(openfpga::Shell& shell, shell, openfpga_verilog_cmd_class, preconfig_wrapper_dependent_cmds, hidden); + /******************************** + * Command 'write_mock_fpga_wrapper' + */ + /* The command 'write_mock_fpga_wrapper' should NOT be executed + * before 'build_fabric' */ + std::vector write_mock_fpga_wrapper_dependent_cmds; + write_mock_fpga_wrapper_dependent_cmds.push_back(build_fabric_cmd_id); + add_write_mock_fpga_wrapper_command_template( + shell, openfpga_verilog_cmd_class, write_mock_fpga_wrapper_dependent_cmds, + hidden); + /******************************** * Command 'write_preconfigured_testbench' */ diff --git a/openfpga/src/base/openfpga_verilog_template.h b/openfpga/src/base/openfpga_verilog_template.h index 3f042ddcc..32cb09ee0 100644 --- a/openfpga/src/base/openfpga_verilog_template.h +++ b/openfpga/src/base/openfpga_verilog_template.h @@ -12,6 +12,7 @@ #include "read_xml_bus_group.h" #include "read_xml_pin_constraints.h" #include "verilog_api.h" +#include "verilog_mock_fpga_wrapper.h" #include "vtr_log.h" #include "vtr_time.h" @@ -56,16 +57,13 @@ int write_fabric_verilog_template(T& openfpga_ctx, const Command& cmd, options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); options.set_compress_routing(openfpga_ctx.flow_manager().compress_routing()); - fpga_fabric_verilog(openfpga_ctx.mutable_module_graph(), - openfpga_ctx.mutable_verilog_netlists(), - openfpga_ctx.blwl_shift_register_banks(), - openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), - openfpga_ctx.decoder_lib(), g_vpr_ctx.device(), - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.device_rr_gsb(), options); - - /* TODO: should identify the error code from internal function execution */ - return CMD_EXEC_SUCCESS; + return fpga_fabric_verilog( + openfpga_ctx.mutable_module_graph(), + openfpga_ctx.mutable_verilog_netlists(), + openfpga_ctx.blwl_shift_register_banks(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.mux_lib(), openfpga_ctx.decoder_lib(), g_vpr_ctx.device(), + openfpga_ctx.vpr_device_annotation(), openfpga_ctx.device_rr_gsb(), + openfpga_ctx.fabric_tile(), options); } /******************************************************************** @@ -76,6 +74,7 @@ int write_full_testbench_template(const T& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_bitstream = cmd.option("bitstream"); + CommandOptionId opt_dut_module = cmd.option("dut_module"); CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_bgf = cmd.option("bus_group_file"); @@ -115,6 +114,10 @@ int write_full_testbench_template(const T& openfpga_ctx, const Command& cmd, cmd_context.option_value(cmd, opt_default_net_type)); } + if (true == cmd_context.option_enable(cmd, opt_dut_module)) { + options.set_dut_module(cmd_context.option_value(cmd, opt_dut_module)); + } + /* If pin constraints are enabled by command options, read the file */ PinConstraints pin_constraints; if (true == cmd_context.option_enable(cmd, opt_pcf)) { @@ -134,7 +137,8 @@ int write_full_testbench_template(const T& openfpga_ctx, const Command& cmd, openfpga_ctx.fabric_bitstream(), openfpga_ctx.blwl_shift_register_banks(), g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group, cmd_context.option_value(cmd, opt_bitstream), - openfpga_ctx.io_location_map(), openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.io_location_map(), openfpga_ctx.io_name_map(), + openfpga_ctx.fabric_global_port_info(), openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib, openfpga_ctx.simulation_setting(), openfpga_ctx.arch().config_protocol, options); @@ -149,6 +153,7 @@ int write_preconfigured_fabric_wrapper_template( const T& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_dut_module = cmd.option("dut_module"); CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_bgf = cmd.option("bus_group_file"); @@ -175,6 +180,10 @@ int write_preconfigured_fabric_wrapper_template( cmd_context.option_enable(cmd, opt_include_signal_init)); options.set_print_formal_verification_top_netlist(true); + if (true == cmd_context.option_enable(cmd, opt_dut_module)) { + options.set_dut_module(cmd_context.option_value(cmd, opt_dut_module)); + } + if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { options.set_default_net_type( cmd_context.option_value(cmd, opt_default_net_type)); @@ -202,11 +211,72 @@ int write_preconfigured_fabric_wrapper_template( return fpga_verilog_preconfigured_fabric_wrapper( openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(), g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group, - openfpga_ctx.io_location_map(), openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.io_location_map(), openfpga_ctx.io_name_map(), + openfpga_ctx.fabric_global_port_info(), openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib, openfpga_ctx.arch().config_protocol, options); } +/******************************************************************** + * A wrapper function to call the mock fpga wrapper generator of + *FPGA-Verilog + *******************************************************************/ +template +int write_mock_fpga_wrapper_template(const T& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { + CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_top_module = cmd.option("top_module"); + CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); + CommandOptionId opt_bgf = cmd.option("bus_group_file"); + CommandOptionId opt_explicit_port_mapping = + cmd.option("explicit_port_mapping"); + CommandOptionId opt_use_relative_path = cmd.option("use_relative_path"); + CommandOptionId opt_default_net_type = cmd.option("default_net_type"); + CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp"); + CommandOptionId opt_verbose = cmd.option("verbose"); + + /* This is an intermediate data structure which is designed to modularize the + * FPGA-Verilog Keep it independent from any other outside data structures + */ + VerilogTestbenchOption options; + options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir)); + options.set_explicit_port_mapping( + cmd_context.option_enable(cmd, opt_explicit_port_mapping)); + options.set_use_relative_path( + cmd_context.option_enable(cmd, opt_use_relative_path)); + options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp)); + options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); + + if (true == cmd_context.option_enable(cmd, opt_top_module)) { + options.set_dut_module(cmd_context.option_value(cmd, opt_top_module)); + } + + if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { + options.set_default_net_type( + cmd_context.option_value(cmd, opt_default_net_type)); + } + + /* If pin constraints are enabled by command options, read the file */ + PinConstraints pin_constraints; + if (true == cmd_context.option_enable(cmd, opt_pcf)) { + pin_constraints = + read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str()); + } + + /* If bug group file are enabled by command options, read the file */ + BusGroup bus_group; + if (true == cmd_context.option_enable(cmd, opt_bgf)) { + bus_group = + read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str()); + } + + return fpga_verilog_mock_fpga_wrapper( + openfpga_ctx.module_graph(), g_vpr_ctx.atom(), g_vpr_ctx.placement(), + pin_constraints, bus_group, openfpga_ctx.io_location_map(), + openfpga_ctx.io_name_map(), openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.vpr_netlist_annotation(), options); +} + /******************************************************************** * A wrapper function to call the preconfigured testbench generator of *FPGA-Verilog diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp index 97ba9e219..5279c9fc7 100644 --- a/openfpga/src/fabric/build_device_module.cpp +++ b/openfpga/src/fabric/build_device_module.cpp @@ -12,14 +12,17 @@ #include "build_decoder_modules.h" #include "build_device_module.h" #include "build_essential_modules.h" +#include "build_fabric_tile.h" #include "build_grid_modules.h" #include "build_lut_modules.h" #include "build_memory_modules.h" #include "build_mux_modules.h" #include "build_routing_modules.h" +#include "build_tile_modules.h" #include "build_top_module.h" #include "build_wire_modules.h" #include "command_exit_codes.h" +#include "openfpga_naming.h" /* begin namespace openfpga */ namespace openfpga { @@ -30,10 +33,11 @@ namespace openfpga { *******************************************************************/ int build_device_module_graph( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, FabricTile& fabric_tile, const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, const bool& frame_view, const bool& compress_routing, const bool& duplicate_grid_pin, const FabricKey& fabric_key, + const TileConfig& tile_config, const bool& group_config_block, const bool& generate_random_fabric_key, const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build fabric module graph"); @@ -74,28 +78,52 @@ int build_device_module_graph( /* Build memory modules */ build_memory_modules(module_manager, decoder_lib, openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol.type()); + openfpga_ctx.arch().config_protocol.type(), + group_config_block, verbose); /* Build grid and programmable block modules */ - build_grid_modules(module_manager, decoder_lib, vpr_device_ctx, - openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), - openfpga_ctx.arch().config_protocol.type(), sram_model, - duplicate_grid_pin, verbose); + status = build_grid_modules( + module_manager, decoder_lib, vpr_device_ctx, + openfpga_ctx.vpr_device_annotation(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.mux_lib(), openfpga_ctx.arch().config_protocol.type(), + sram_model, duplicate_grid_pin, group_config_block, verbose); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } if (true == compress_routing) { - build_unique_routing_modules( - module_manager, decoder_lib, vpr_device_ctx, - openfpga_ctx.vpr_device_annotation(), openfpga_ctx.device_rr_gsb(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol.type(), sram_model, verbose); + build_unique_routing_modules(module_manager, decoder_lib, vpr_device_ctx, + openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.device_rr_gsb(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol.type(), + sram_model, group_config_block, verbose); } else { VTR_ASSERT_SAFE(false == compress_routing); - build_flatten_routing_modules( - module_manager, decoder_lib, vpr_device_ctx, - openfpga_ctx.vpr_device_annotation(), openfpga_ctx.device_rr_gsb(), - openfpga_ctx.arch().circuit_lib, - openfpga_ctx.arch().config_protocol.type(), sram_model, verbose); + build_flatten_routing_modules(module_manager, decoder_lib, vpr_device_ctx, + openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.device_rr_gsb(), + openfpga_ctx.arch().circuit_lib, + openfpga_ctx.arch().config_protocol.type(), + sram_model, group_config_block, verbose); + } + + /* Build tile modules if defined */ + if (tile_config.is_valid()) { + /* Build detailed tile-level information */ + status = build_fabric_tile(fabric_tile, tile_config, vpr_device_ctx.grid, + vpr_device_ctx.rr_graph, + openfpga_ctx.device_rr_gsb(), verbose); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + /* Build the modules */ + build_tile_modules( + module_manager, decoder_lib, openfpga_ctx.fabric_tile(), + vpr_device_ctx.grid, openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.device_rr_gsb(), vpr_device_ctx.rr_graph, + openfpga_ctx.arch().circuit_lib, sram_model, + openfpga_ctx.arch().config_protocol.type(), frame_view, verbose); } /* Build FPGA fabric top-level module */ @@ -106,8 +134,8 @@ int build_device_module_graph( openfpga_ctx.arch().tile_annotations, vpr_device_ctx.rr_graph, openfpga_ctx.device_rr_gsb(), openfpga_ctx.tile_direct(), openfpga_ctx.arch().arch_direct, openfpga_ctx.arch().config_protocol, - sram_model, frame_view, compress_routing, duplicate_grid_pin, fabric_key, - generate_random_fabric_key); + sram_model, fabric_tile, frame_view, compress_routing, duplicate_grid_pin, + fabric_key, generate_random_fabric_key, group_config_block, verbose); if (CMD_EXEC_FATAL_ERROR == status) { return status; diff --git a/openfpga/src/fabric/build_device_module.h b/openfpga/src/fabric/build_device_module.h index 11a28f1f3..fb4178cc8 100644 --- a/openfpga/src/fabric/build_device_module.h +++ b/openfpga/src/fabric/build_device_module.h @@ -5,7 +5,10 @@ * Include header files that are required by function declaration *******************************************************************/ #include "fabric_key.h" +#include "fabric_tile.h" +#include "io_name_map.h" #include "openfpga_context.h" +#include "tile_config.h" #include "vpr_context.h" /******************************************************************** @@ -17,10 +20,11 @@ namespace openfpga { int build_device_module_graph( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - MemoryBankShiftRegisterBanks& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, FabricTile& fabric_tile, const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, const bool& frame_view, const bool& compress_routing, const bool& duplicate_grid_pin, const FabricKey& fabric_key, + const TileConfig& tile_config, const bool& group_config_block, const bool& generate_random_fabric_key, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fabric_io_location_map.cpp b/openfpga/src/fabric/build_fabric_io_location_map.cpp index 710ce4e5d..88097f976 100644 --- a/openfpga/src/fabric/build_fabric_io_location_map.cpp +++ b/openfpga/src/fabric/build_fabric_io_location_map.cpp @@ -31,8 +31,9 @@ namespace openfpga { *io_children() list of top-level module. Here we just build a fast lookup from *(x, y, z) coordinate to the actual indices *******************************************************************/ -IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, - const DeviceGrid& grids) { +static IoLocationMap build_fabric_fine_grained_io_location_map( + const ModuleManager& module_manager, const DeviceGrid& grids, + const size_t& layer) { vtr::ScopedStartFinishTimer timer( "Create I/O location mapping for top module"); @@ -50,15 +51,18 @@ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, ModuleId child = module_manager.io_children(top_module)[ichild]; vtr::Point coord = module_manager.io_child_coordinates(top_module)[ichild]; + t_physical_tile_loc phy_tile_loc(coord.x(), coord.y(), layer); + t_physical_tile_type_ptr phy_tile_type = + grids.get_physical_type(phy_tile_loc); /* Bypass EMPTY grid */ - if (true == is_empty_type(grids[coord.x()][coord.y()].type)) { + if (true == is_empty_type(phy_tile_type)) { continue; } /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[coord.x()][coord.y()].width_offset) || - (0 < grids[coord.x()][coord.y()].height_offset)) { + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { continue; } @@ -69,32 +73,43 @@ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, /* MUST DO: register in io location mapping! * I/O location mapping is a critical look-up for testbench generators */ - if (size_t(grids[coord.x()][coord.y()].type->capacity) != + if (size_t(phy_tile_type->capacity) != module_manager.io_children(child).size()) { VTR_LOG("%s[%ld][%ld] capacity: %d while io_child number is %d", - grids[coord.x()][coord.y()].type->name, coord.x(), coord.y(), - grids[coord.x()][coord.y()].type->capacity, + phy_tile_type->name, coord.x(), coord.y(), + phy_tile_type->capacity, module_manager.io_children(child).size()); } - VTR_ASSERT(size_t(grids[coord.x()][coord.y()].type->capacity) == + VTR_ASSERT(size_t(phy_tile_type->capacity) == module_manager.io_children(child).size()); for (size_t isubchild = 0; isubchild < module_manager.io_children(child).size(); ++isubchild) { + /* Note that we should use the subchild module when checking the GPIO + * ports. The child module is actually the grid-level I/O module, while + * the subchild module is the subtile inside grid-level I/O modules. Note + * that grid-level I/O module contains all the GPIO ports while the + * subtile may have part of it. For example, a grid I/O module may have 24 + * GPINs and 12 GPOUTs, while the first subtile only have 4 GPINs, and the + * second subtile only have 3 GPOUTs. Therefore, to accurately build the + * I/O location map downto subtile level, we need to check the subchild + * module here. + */ + ModuleId subchild = module_manager.io_children(child)[isubchild]; vtr::Point subchild_coord = module_manager.io_child_coordinates(child)[isubchild]; for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) { for (const ModulePortId& gpio_port_id : - module_manager.module_port_ids_by_type(child, + module_manager.module_port_ids_by_type(subchild, module_io_port_type)) { /* Only care mappable I/O */ if (false == - module_manager.port_is_mappable_io(child, gpio_port_id)) { + module_manager.port_is_mappable_io(subchild, gpio_port_id)) { continue; } const BasicPort& gpio_port = - module_manager.module_port(child, gpio_port_id); + module_manager.module_port(subchild, gpio_port_id); auto curr_io_index = io_counter.find(gpio_port.get_name()); /* Index always start from zero */ @@ -131,4 +146,147 @@ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, return io_location_map; } +/******************************************************************** + * Find all the GPIO ports in the tile modules + * and cache their port/pin index in the top-level module + * + * .. note:: The I/O sequence(indexing) is already determined in the + *io_children() list of top-level module. Here we just build a fast lookup from + *(x, y, z) coordinate to the actual indices + *******************************************************************/ +static IoLocationMap build_fabric_tiled_io_location_map( + const ModuleManager& module_manager, const DeviceGrid& grids, + const size_t& layer) { + vtr::ScopedStartFinishTimer timer( + "Create I/O location mapping for top module"); + + IoLocationMap io_location_map; + + std::map io_counter; + + std::string top_module_name = generate_fpga_top_module_name(); + ModuleId top_module = module_manager.find_module(top_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + + /* Walk through the I/O child list */ + for (size_t ichild = 0; + ichild < module_manager.io_children(top_module).size(); ++ichild) { + ModuleId child = module_manager.io_children(top_module)[ichild]; + vtr::Point coord = + module_manager.io_child_coordinates(top_module)[ichild]; + t_physical_tile_loc phy_tile_loc(coord.x(), coord.y(), layer); + t_physical_tile_type_ptr phy_tile_type = + grids.get_physical_type(phy_tile_loc); + + /* Bypass EMPTY grid */ + if (true == is_empty_type(phy_tile_type)) { + continue; + } + + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { + continue; + } + + VTR_ASSERT_SAFE(true == module_manager.valid_module_id(child)); + + /* Find all the GPIO ports in the grid module */ + + /* MUST DO: register in io location mapping! + * I/O location mapping is a critical look-up for testbench generators + */ + for (ModuleId tile_child : module_manager.io_children(child)) { + /* Note that we should use the subchild of the subchild module when + * checking the GPIO ports. The child module is the tile module while the + * subchild module is actually the grid-level I/O module, while the + * subchild module is the subtile inside grid-level I/O modules. Note that + * grid-level I/O module contains all the GPIO ports while the subtile may + * have part of it. For example, a grid I/O module may have 24 GPINs and + * 12 GPOUTs, while the first subtile only have 4 GPINs, and the second + * subtile only have 3 GPOUTs. Therefore, to accurately build the I/O + * location map downto subtile level, we need to check the subchild module + * here. + */ + if (size_t(phy_tile_type->capacity) != + module_manager.io_children(tile_child).size()) { + VTR_LOG("%s[%ld][%ld] capacity: %d while io_child number is %d", + phy_tile_type->name, coord.x(), coord.y(), + phy_tile_type->capacity, + module_manager.io_children(tile_child).size()); + } + VTR_ASSERT(size_t(phy_tile_type->capacity) == + module_manager.io_children(tile_child).size()); + for (size_t isubchild = 0; + isubchild < module_manager.io_children(tile_child).size(); + ++isubchild) { + ModuleId subchild = module_manager.io_children(tile_child)[isubchild]; + vtr::Point subchild_coord = + module_manager.io_child_coordinates(tile_child)[isubchild]; + + for (const ModuleManager::e_module_port_type& module_io_port_type : + MODULE_IO_PORT_TYPES) { + for (const ModulePortId& gpio_port_id : + module_manager.module_port_ids_by_type(subchild, + module_io_port_type)) { + /* Only care mappable I/O */ + if (false == + module_manager.port_is_mappable_io(subchild, gpio_port_id)) { + continue; + } + const BasicPort& gpio_port = + module_manager.module_port(subchild, gpio_port_id); + + auto curr_io_index = io_counter.find(gpio_port.get_name()); + /* Index always start from zero */ + if (curr_io_index == io_counter.end()) { + io_counter[gpio_port.get_name()] = 0; + } + /* This is a dirty hack! */ + io_location_map.set_io_index( + coord.x(), coord.y(), subchild_coord.x(), gpio_port.get_name(), + io_counter[gpio_port.get_name()]); + io_counter[gpio_port.get_name()]++; + } + } + } + } + } + + /* Check all the GPIO ports in the top-level module has been mapped */ + for (const ModuleManager::e_module_port_type& module_io_port_type : + MODULE_IO_PORT_TYPES) { + for (const ModulePortId& gpio_port_id : + module_manager.module_port_ids_by_type(top_module, + module_io_port_type)) { + /* Only care mappable I/O */ + if (false == + module_manager.port_is_mappable_io(top_module, gpio_port_id)) { + continue; + } + + const BasicPort& gpio_port = + module_manager.module_port(top_module, gpio_port_id); + VTR_ASSERT(io_counter[gpio_port.get_name()] == gpio_port.get_width()); + } + } + + return io_location_map; +} + +/******************************************************************** + * Top-level function, if tile modules are built under the top-level module + * The data to access for I/O location is different than the fine-grained grid + *modules + * FIXME: Think about a unified way for the two kinds of fabrics!!! + *******************************************************************/ +IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, + const DeviceGrid& grids, + const bool& tiled_fabric) { + if (tiled_fabric) { + return build_fabric_tiled_io_location_map(module_manager, grids, 0); + } + return build_fabric_fine_grained_io_location_map(module_manager, grids, 0); +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fabric_io_location_map.h b/openfpga/src/fabric/build_fabric_io_location_map.h index d84060390..200637e0b 100644 --- a/openfpga/src/fabric/build_fabric_io_location_map.h +++ b/openfpga/src/fabric/build_fabric_io_location_map.h @@ -19,7 +19,8 @@ namespace openfpga { IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager, - const DeviceGrid& grids); + const DeviceGrid& grids, + const bool& tiled_fabric); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fabric_tile.cpp b/openfpga/src/fabric/build_fabric_tile.cpp new file mode 100644 index 000000000..a1e5f9460 --- /dev/null +++ b/openfpga/src/fabric/build_fabric_tile.cpp @@ -0,0 +1,175 @@ +/******************************************************************** + * This file includes functions that are used to build the location + * map information for the top-level module of the FPGA fabric + * It helps OpenFPGA to link the I/O port index in top-level module + * to the VPR I/O mapping results + *******************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from vpr library */ +#include "build_fabric_tile.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Build tiles by following the top-level style. + * - The programmble block, e.g., clb, is placed on the top-left corner + * - The connection blocks and switch block are placed on the right and bottom + *sides + *******************************************************************/ +static int build_fabric_tile_style_top_left(FabricTile& fabric_tile, + const DeviceGrid& grids, + const size_t& layer, + const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, + const bool& verbose) { + int status_code = CMD_EXEC_SUCCESS; + + /* Walk through all the device rr_gsb and create tile one by one */ + for (size_t ix = 0; ix < grids.width(); ++ix) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + t_physical_tile_loc tile_loc(ix, iy, layer); + t_physical_tile_type_ptr phy_tile_type = + grids.get_physical_type(tile_loc); + bool skip_add_pb = false; + vtr::Point curr_tile_coord(ix, iy); + vtr::Point curr_gsb_coord(ix, iy - 1); + FabricTileId curr_tile_id = FabricTileId::INVALID(); + /* For EMPTY grid, routing blocks may still be required if there is a gsb + */ + if (true == is_empty_type(phy_tile_type)) { + skip_add_pb = true; + if (!device_rr_gsb.is_gsb_exist(rr_graph, curr_gsb_coord)) { + VTR_LOGV(verbose, "Skip tile[%lu][%lu] as it is empty\n", + curr_tile_coord.x(), curr_tile_coord.y()); + continue; + } + /* Need to create a new tile here */ + VTR_LOGV(verbose, + "Create tile[%lu][%lu] which only has routing but not a " + "programmable block\n", + curr_tile_coord.x(), curr_tile_coord.y()); + curr_tile_id = fabric_tile.create_tile(curr_tile_coord); + } else if ((0 < grids.get_width_offset(tile_loc)) || + (0 < grids.get_height_offset(tile_loc))) { + /* Skip width, height > 1 tiles (mostly heterogeneous blocks) */ + /* Find the root of this grid, the instance id should be valid. + * We just copy it here + */ + vtr::Point root_tile_coord( + ix - grids.get_width_offset(tile_loc), + iy - grids.get_height_offset(tile_loc)); + skip_add_pb = true; + VTR_LOGV(verbose, + "Tile[%lu][%lu] contains a heterogeneous block which is " + "rooted from tile[%lu][%lu]\n", + curr_tile_coord.x(), curr_tile_coord.y(), root_tile_coord.x(), + root_tile_coord.y()); + curr_tile_id = fabric_tile.find_tile(root_tile_coord); + /* Update the coordinates of the pb in tiles */ + size_t root_pb_idx_in_curr_tile = + fabric_tile.find_pb_index_in_tile(curr_tile_id, root_tile_coord); + status_code = fabric_tile.set_pb_max_coordinate( + curr_tile_id, root_pb_idx_in_curr_tile, vtr::Point(ix, iy)); + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } else { + /* Need to create a new tile here */ + VTR_LOGV(verbose, "Create a regular tile[%lu][%lu]\n", + curr_tile_coord.x(), curr_tile_coord.y()); + curr_tile_id = fabric_tile.create_tile(curr_tile_coord); + } + + /* Ensure that we have a valid id */ + if (!fabric_tile.valid_tile_id(curr_tile_id)) { + VTR_LOG_ERROR("Failed to get a valid id for tile[%lu][%lu]!\n", ix, iy); + return CMD_EXEC_FATAL_ERROR; + } + + /* Add components: pb, cbx, cby, and sb if exists */ + if (!skip_add_pb) { + fabric_tile.add_pb_coordinate(curr_tile_id, curr_tile_coord, + curr_gsb_coord); + } + /* The gsb coordinate is different than the grid coordinate when the + * top-left style is considered + * + * +----------+ +----------+ + * | Grid | | CBx | + * | [x][y] | | [x][y] | + * +----------+ +----------+ + * +----------+ +----------+ + * | CBy | | SB | + * | [x][y-1] | | [x][y-1] | + * +----------+ +----------+ + * + */ + if (!device_rr_gsb.is_gsb_exist(rr_graph, curr_gsb_coord)) { + continue; + } + const RRGSB& curr_rr_gsb = device_rr_gsb.get_gsb(curr_gsb_coord); + for (t_rr_type cb_type : {CHANX, CHANY}) { + if (curr_rr_gsb.is_cb_exist(cb_type)) { + fabric_tile.add_cb_coordinate(curr_tile_id, cb_type, + curr_rr_gsb.get_sb_coordinate()); + } + } + if (curr_rr_gsb.is_sb_exist(rr_graph)) { + fabric_tile.add_sb_coordinate(curr_tile_id, + curr_rr_gsb.get_sb_coordinate()); + } + } + } + + return status_code; +} + +/******************************************************************** + * Build tile-level information for a given FPGA fabric, w.r.t. to configuration + *******************************************************************/ +int build_fabric_tile(FabricTile& fabric_tile, const TileConfig& tile_config, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const bool& verbose) { + vtr::ScopedStartFinishTimer timer( + "Build tile-level information for the FPGA fabric"); + + int status_code = CMD_EXEC_SUCCESS; + + fabric_tile.init(vtr::Point(grids.width(), grids.height())); + + /* Depending on the selected style, follow different approaches */ + if (tile_config.style() == TileConfig::e_style::TOP_LEFT) { + status_code = build_fabric_tile_style_top_left( + fabric_tile, grids, 0, rr_graph, device_rr_gsb, verbose); + } else { + /* Error out for styles that are not supported yet! */ + VTR_LOG_ERROR("Tile style '%s' is not supported yet!\n", + tile_config.style_to_string().c_str()); + status_code = CMD_EXEC_FATAL_ERROR; + } + + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Build unique tiles to compress the number of tile modules to be built in + * later steps */ + status_code = fabric_tile.build_unique_tiles(grids, device_rr_gsb, verbose); + VTR_LOGV(verbose, "Extracted %lu uniques tiles from the FPGA fabric\n", + fabric_tile.unique_tiles().size()); + + return status_code; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fabric_tile.h b/openfpga/src/fabric/build_fabric_tile.h new file mode 100644 index 000000000..b2d21c9a0 --- /dev/null +++ b/openfpga/src/fabric/build_fabric_tile.h @@ -0,0 +1,28 @@ +#ifndef BUILD_FABRIC_TILE_H +#define BUILD_FABRIC_TILE_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ + +#include + +#include "device_grid.h" +#include "device_rr_gsb.h" +#include "fabric_tile.h" +#include "tile_config.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int build_fabric_tile(FabricTile& fabric_tile, const TileConfig& tile_config, + const DeviceGrid& grids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const bool& verbose); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp b/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp new file mode 100644 index 000000000..d8af89dc5 --- /dev/null +++ b/openfpga/src/fabric/build_fpga_core_wrapper_module.cpp @@ -0,0 +1,390 @@ +/******************************************************************** + * This file includes the main function to build module graphs + * for the FPGA fabric + *******************************************************************/ + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpgashell library */ +#include "build_fpga_core_wrapper_module.h" +#include "command_exit_codes.h" +#include "openfpga_naming.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Add ports to top module based on I/O naming rules: + * - Add ports which has been defined in the naming rules + * - Add ports from the core module, which does not appear in the naming rules + *******************************************************************/ +static int create_fpga_top_module_ports_using_naming_rules( + ModuleManager& module_manager, const ModuleId& wrapper_module, + const ModuleId& core_module, const IoNameMap& io_naming, + const bool& verbose) { + for (BasicPort top_port : io_naming.fpga_top_ports()) { + /* For dummy port, just add it. Port type should be defined from io naming + * rules */ + if (io_naming.fpga_top_port_is_dummy(top_port)) { + ModuleManager::e_module_port_type port_type = + ModuleManager::e_module_port_type::MODULE_INOUT_PORT; + if (IoNameMap::e_dummy_port_direction::INPUT == + io_naming.fpga_top_dummy_port_direction(top_port)) { + port_type = ModuleManager::e_module_port_type::MODULE_INPUT_PORT; + } else if (IoNameMap::e_dummy_port_direction::OUTPUT == + io_naming.fpga_top_dummy_port_direction(top_port)) { + port_type = ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT; + } else if (IoNameMap::e_dummy_port_direction::INOUT == + io_naming.fpga_top_dummy_port_direction(top_port)) { + port_type = ModuleManager::e_module_port_type::MODULE_INOUT_PORT; + } else { + VTR_LOG_ERROR( + "fpga_top dummy port '%s' has an invalid direction. Expect " + "[input|output|inout]!\n", + top_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + module_manager.add_port(wrapper_module, top_port, port_type); + VTR_LOGV(verbose, + "Add dummy port '%s' to fpga_top by following naming rules\n", + top_port.to_verilog_string().c_str()); + continue; /* Finish for this port addition */ + } + /* Get the port type which should be same as the fpga_core port */ + BasicPort core_port = io_naming.fpga_core_port(top_port); + if (!core_port.is_valid()) { + VTR_LOG_ERROR("fpga_top port '%s' is not mapped to any fpga_core port!\n", + top_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + ModulePortId core_port_id = + module_manager.find_module_port(core_module, core_port.get_name()); + if (!module_manager.valid_module_port_id(core_module, core_port_id)) { + VTR_LOG_ERROR( + "fpga_top port '%s' is mapped to an invalid fpga_core port '%s'!\n", + top_port.to_verilog_string().c_str(), + core_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + ModuleManager::e_module_port_type top_port_type = + module_manager.port_type(core_module, core_port_id); + module_manager.add_port(wrapper_module, top_port, top_port_type); + VTR_LOGV(verbose, + "Add port '%s' to fpga_top (correspond to '%s' of fpga_core) by " + "following naming rules\n", + top_port.to_verilog_string().c_str(), + core_port.to_verilog_string().c_str()); + } + /* Now walk through the ports of fpga_core, if port which is not mapped to + * fpga_top should be added */ + for (ModulePortId core_port_id : module_manager.module_ports(core_module)) { + BasicPort core_port = module_manager.module_port(core_module, core_port_id); + BasicPort top_port = io_naming.fpga_top_port(core_port); + if (top_port.is_valid()) { + continue; /* Port has been added in the previous loop, skip now */ + } + /* Throw fatal error if part of the core port is mapped while other part is + * not mapped. This is not allowed! */ + IoNameMap::e_port_mapping_status mapping_status = + io_naming.fpga_core_port_mapping_status(core_port, true); + if (mapping_status == IoNameMap::e_port_mapping_status::FULL) { + continue; + } + if (mapping_status == IoNameMap::e_port_mapping_status::PARTIAL) { + VTR_LOG_ERROR( + "fpga_core port '%s' is partially mapped to fpga_top, which is not " + "allowed. Please cover the full-sized port in naming rules!\n", + core_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + if (mapping_status == IoNameMap::e_port_mapping_status::OVERLAPPED) { + VTR_LOG_ERROR( + "fpga_core port '%s' is overlapped mapped to fpga_top, which is not " + "allowed. Please cover the full-sized port in naming rules!\n", + core_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + VTR_ASSERT(mapping_status == IoNameMap::e_port_mapping_status::NONE); + + /* Add the port now */ + ModuleManager::e_module_port_type top_port_type = + module_manager.port_type(core_module, core_port_id); + module_manager.add_port(wrapper_module, core_port, top_port_type); + VTR_LOG( + "Add port '%s' to fpga_top in the same name as the port of " + "fpga_core, since naming rules do not specify\n", + core_port.to_verilog_string().c_str()); + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Add nets between top module and core module based on I/O naming rules: + * - Dummy ports do not need any nets + * - For ports which are defined in the naming rules, create dedicated + *connections + * - For ports of the core module, which does not appear in the naming rules, + *create direct connections + *******************************************************************/ +static int create_fpga_top_module_nets_using_naming_rules( + ModuleManager& module_manager, const ModuleId& wrapper_module, + const ModuleId& core_module, const IoNameMap& io_naming, + const bool& verbose) { + for (BasicPort top_port : io_naming.fpga_top_ports()) { + if (io_naming.fpga_top_port_is_dummy(top_port)) { + VTR_LOGV("Skip nets for dummy port '%s' at top module\n", + top_port.to_verilog_string().c_str()); + continue; + } + /* Collect port-level information */ + ModulePortId top_port_id = + module_manager.find_module_port(wrapper_module, top_port.get_name()); + if (!module_manager.valid_module_port_id(wrapper_module, top_port_id)) { + VTR_LOG_ERROR("fpga_top port '%s' is not found at top module!\n", + top_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + BasicPort core_port = io_naming.fpga_core_port(top_port); + if (!core_port.is_valid()) { + VTR_LOG_ERROR("fpga_top port '%s' is not mapped to any fpga_core port!\n", + top_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + ModulePortId core_port_id = + module_manager.find_module_port(core_module, core_port.get_name()); + if (!module_manager.valid_module_port_id(core_module, core_port_id)) { + VTR_LOG_ERROR( + "fpga_top port '%s' is mapped to an invalid fpga_core port '%s'!\n", + top_port.to_verilog_string().c_str(), + core_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + ModuleManager::e_module_port_type top_port_type = + module_manager.port_type(core_module, core_port_id); + + /* Create net for each pin-to-pin connection */ + if (top_port.get_width() != core_port.get_width()) { + VTR_LOG_ERROR( + "fpga_top port '%s' does not match the width of fpga_core port '%s'!\n", + top_port.to_verilog_string().c_str(), + core_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + for (size_t ipin = 0; ipin < top_port.pins().size(); ++ipin) { + ModuleNetId new_net = module_manager.create_module_net(wrapper_module); + if (top_port_type != + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT) { + module_manager.add_module_net_source(wrapper_module, new_net, + wrapper_module, 0, top_port_id, + top_port.pins()[ipin]); + module_manager.add_module_net_sink(wrapper_module, new_net, core_module, + 0, core_port_id, + core_port.pins()[ipin]); + } else { + VTR_ASSERT_SAFE(top_port_type == + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT); + module_manager.add_module_net_source(wrapper_module, new_net, + core_module, 0, core_port_id, + core_port.pins()[ipin]); + module_manager.add_module_net_sink(wrapper_module, new_net, + wrapper_module, 0, top_port_id, + top_port.pins()[ipin]); + } + BasicPort top_pin(top_port.get_name(), top_port.pins()[ipin], + top_port.pins()[ipin]); + BasicPort core_pin(core_port.get_name(), core_port.pins()[ipin], + core_port.pins()[ipin]); + VTR_LOGV( + verbose, + "Add nets to connect between fpga_top '%s' and fpga_core '%s' by " + "following naming rules\n", + top_pin.to_verilog_string().c_str(), + core_pin.to_verilog_string().c_str()); + } + } + /* Now walk through the ports of fpga_core, if port which is not mapped to + * fpga_top, nets should be added */ + for (ModulePortId core_port_id : module_manager.module_ports(core_module)) { + BasicPort core_port = module_manager.module_port(core_module, core_port_id); + BasicPort top_port = io_naming.fpga_top_port(core_port); + if (top_port.is_valid()) { + continue; /* Port has been added in the previous loop, skip now */ + } + /* Throw fatal error if part of the core port is mapped while other part is + * not mapped. This is not allowed! */ + IoNameMap::e_port_mapping_status mapping_status = + io_naming.fpga_core_port_mapping_status(core_port); + if (mapping_status == IoNameMap::e_port_mapping_status::FULL) { + continue; + } + if (mapping_status == IoNameMap::e_port_mapping_status::PARTIAL) { + VTR_LOG_ERROR( + "fpga_core port '%s' is partially mapped to fpga_top, which is not " + "allowed. Please cover the full-sized port in naming rules!\n", + core_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + if (mapping_status == IoNameMap::e_port_mapping_status::OVERLAPPED) { + VTR_LOG_ERROR( + "fpga_core port '%s' is overlapped mapped to fpga_top, which is not " + "allowed. Please cover the full-sized port in naming rules!\n", + core_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + VTR_ASSERT(mapping_status == IoNameMap::e_port_mapping_status::NONE); + ModuleManager::e_module_port_type top_port_type = + module_manager.port_type(core_module, core_port_id); + /* Collect port-level information */ + ModulePortId top_port_id = + module_manager.find_module_port(wrapper_module, core_port.get_name()); + top_port = module_manager.module_port( + wrapper_module, top_port_id); /* Note: overwrite the top port */ + if (!module_manager.valid_module_port_id(wrapper_module, top_port_id)) { + VTR_LOG_ERROR("fpga_top port '%s' is not found at top module!\n", + top_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Create net for each pin-to-pin connection */ + if (top_port.get_width() != core_port.get_width()) { + VTR_LOG_ERROR( + "fpga_top port '%s' does not match the width of fpga_core port '%s'!\n", + top_port.to_verilog_string().c_str(), + core_port.to_verilog_string().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + for (size_t ipin = 0; ipin < core_port.pins().size(); ++ipin) { + ModuleNetId new_net = module_manager.create_module_net(wrapper_module); + if (top_port_type != + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT) { + module_manager.add_module_net_source(wrapper_module, new_net, + wrapper_module, 0, top_port_id, + top_port.pins()[ipin]); + module_manager.add_module_net_sink(wrapper_module, new_net, core_module, + 0, core_port_id, + core_port.pins()[ipin]); + } else { + VTR_ASSERT_SAFE(top_port_type == + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT); + module_manager.add_module_net_source(wrapper_module, new_net, + core_module, 0, core_port_id, + core_port.pins()[ipin]); + module_manager.add_module_net_sink(wrapper_module, new_net, + wrapper_module, 0, top_port_id, + top_port.pins()[ipin]); + } + BasicPort core_pin(top_port.get_name(), core_port.pins()[ipin], + core_port.pins()[ipin]); + VTR_LOGV( + verbose, + "Add nets to connect fpga_top '%s' in the same name as the port of " + "fpga_core, since naming rules do not specify\n", + core_pin.to_verilog_string().c_str()); + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Create a custom fpga_top module by applying naming rules + *******************************************************************/ +static int create_fpga_top_module_using_naming_rules( + ModuleManager& module_manager, ModuleId& wrapper_module, + const ModuleId& core_module, const std::string& top_module_name, + const IoNameMap& io_naming, const std::string& instance_name, + const bool& add_nets, const bool& verbose) { + /* Create a new module with the given name */ + wrapper_module = module_manager.add_module(top_module_name); + if (!wrapper_module) { + return CMD_EXEC_FATAL_ERROR; + } + /* Add the existing module as an instance */ + module_manager.add_child_module(wrapper_module, core_module, false); + module_manager.set_child_instance_name(wrapper_module, core_module, 0, + instance_name); + + /* Add ports */ + if (CMD_EXEC_SUCCESS != + create_fpga_top_module_ports_using_naming_rules( + module_manager, wrapper_module, core_module, io_naming, verbose)) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Add nets */ + if (add_nets) { + if (CMD_EXEC_SUCCESS != + create_fpga_top_module_nets_using_naming_rules( + module_manager, wrapper_module, core_module, io_naming, verbose)) { + return CMD_EXEC_FATAL_ERROR; + } + } + + /* TODO: Update the fabric global ports */ + + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * The main function to be called for adding the fpga_core wrapper to a FPGA + *fabric + * - Rename existing fpga_top to fpga_core + * - Create a wrapper module 'fpga_top' on the fpga_core + *******************************************************************/ +int add_fpga_core_to_device_module_graph(ModuleManager& module_manager, + const IoNameMap& io_naming, + const std::string& core_inst_name, + const bool& frame_view, + const bool& verbose) { + int status = CMD_EXEC_SUCCESS; + + /* Execute the module graph api */ + std::string top_module_name = generate_fpga_top_module_name(); + ModuleId top_module = module_manager.find_module(top_module_name); + if (!module_manager.valid_module_id(top_module)) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Rename existing top module to fpga_core */ + std::string core_module_name = generate_fpga_core_module_name(); + module_manager.set_module_name(top_module, core_module_name); + VTR_LOGV(verbose, "Rename current top-level module '%s' to '%s'\n", + top_module_name.c_str(), core_module_name.c_str()); + + /* Create a wrapper module under the existing fpga_top + * - if there are no io naming rules, just use the default API to create a + * wrapper + * - if there are io naming rules, use dedicated function to handle + */ + ModuleId new_top_module; + if (io_naming.empty()) { + new_top_module = module_manager.create_wrapper_module( + top_module, top_module_name, core_inst_name, !frame_view); + } else { + status = create_fpga_top_module_using_naming_rules( + module_manager, new_top_module, top_module, top_module_name, io_naming, + core_inst_name, !frame_view, verbose); + if (CMD_EXEC_SUCCESS != status) { + return CMD_EXEC_FATAL_ERROR; + } + } + if (!module_manager.valid_module_id(new_top_module)) { + VTR_LOGV_ERROR(verbose, + "Failed to create a wrapper module '%s' on top of '%s'!\n", + top_module_name.c_str(), core_module_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + + VTR_LOGV(verbose, "Created a wrapper module '%s' on top of '%s'\n", + top_module_name.c_str(), core_module_name.c_str()); + + /* Now fpga_core should be the only configurable child under the top-level + * module */ + module_manager.add_configurable_child( + new_top_module, top_module, 0, ModuleManager::e_config_child_type::UNIFIED); + + return status; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fpga_core_wrapper_module.h b/openfpga/src/fabric/build_fpga_core_wrapper_module.h new file mode 100644 index 000000000..3520f6d8b --- /dev/null +++ b/openfpga/src/fabric/build_fpga_core_wrapper_module.h @@ -0,0 +1,27 @@ +#ifndef BUILD_FPGA_CORE_WRAPPER_MODULE_H +#define BUILD_FPGA_CORE_WRAPPER_MODULE_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "io_name_map.h" +#include "module_manager.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int add_fpga_core_to_device_module_graph(ModuleManager& module_manager, + const IoNameMap& io_naming, + const std::string& core_inst_name, + const bool& frame_view, + const bool& verbose); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp b/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp index 451500c0e..77f4024db 100644 --- a/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp +++ b/openfpga/src/fabric/build_grid_module_duplicated_pins.cpp @@ -151,6 +151,7 @@ void add_grid_module_duplicated_pb_type_ports( static void add_grid_module_net_connect_duplicated_pb_graph_pin( ModuleManager& module_manager, const ModuleId& grid_module, const ModuleId& child_module, const size_t& child_instance, + const size_t& child_inst_subtile_index, const VprDeviceAnnotation& vpr_device_annotation, t_physical_tile_type_ptr grid_type_descriptor, t_pb_graph_pin* pb_graph_pin, const e_side& border_side, const e_pin2pin_interc_type& pin2pin_interc_type) { @@ -169,15 +170,18 @@ static void add_grid_module_net_connect_duplicated_pb_graph_pin( grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; } - /* num_pins/capacity = the number of pins that each type_descriptor has. - * Capacity defines the number of type_descriptors in each grid - * so the pin index at grid level = pin_index_in_type_descriptor - * + type_descriptor_index_in_capacity * - * num_pins_per_type_descriptor + /* Note that each grid may contain a number of sub tiles, each type of which + * may a different capacity and number of pins We need to find the start pin + * index for a given z offset (instance id), denotes the index of the first + * pin regarding the current instance. The variable 'pin_count_in_cluster' + * represent the pin index in the context of current instance only. With the + * information above, we can then calculate the absolute pin index at + * grid-level (considering all the sub tiles). */ - size_t grid_pin_index = pb_graph_pin->pin_count_in_cluster + - child_instance * grid_type_descriptor->num_pins / - grid_type_descriptor->capacity; + size_t grid_pin_index = + pb_graph_pin->pin_count_in_cluster + + vpr_device_annotation.physical_tile_z_to_start_pin_index( + grid_type_descriptor, child_inst_subtile_index); int pin_width = grid_type_descriptor->pin_width_offset[grid_pin_index]; int pin_height = grid_type_descriptor->pin_height_offset[grid_pin_index]; @@ -292,49 +296,48 @@ static void add_grid_module_net_connect_duplicated_pb_graph_pin( void add_grid_module_nets_connect_duplicated_pb_type_ports( ModuleManager& module_manager, const ModuleId& grid_module, const ModuleId& child_module, const size_t& child_instance, - const VprDeviceAnnotation& vpr_device_annotation, + const t_sub_tile& sub_tile, const VprDeviceAnnotation& vpr_device_annotation, t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { /* Ensure that we have a valid grid_type_descriptor */ VTR_ASSERT(false == is_empty_type(grid_type_descriptor)); /* FIXME: Currently support only 1 equivalent site! Should clarify this * limitation in documentation! */ - for (const t_sub_tile& sub_tile : grid_type_descriptor->sub_tiles) { - t_logical_block_type_ptr lb_type = sub_tile.equivalent_sites[0]; - t_pb_graph_node* top_pb_graph_node = lb_type->pb_graph_head; - VTR_ASSERT(nullptr != top_pb_graph_node); + t_logical_block_type_ptr lb_type = sub_tile.equivalent_sites[0]; + t_pb_graph_node* top_pb_graph_node = lb_type->pb_graph_head; + VTR_ASSERT(nullptr != top_pb_graph_node); + size_t child_inst_subtile_index = sub_tile.capacity.low + child_instance; - for (int iport = 0; iport < top_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; - ++ipin) { - add_grid_module_net_connect_pb_graph_pin( - module_manager, grid_module, child_module, child_instance, - vpr_device_annotation, grid_type_descriptor, - &(top_pb_graph_node->input_pins[iport][ipin]), border_side, - INPUT2INPUT_INTERC); - } + for (int iport = 0; iport < top_pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->input_pins[iport][ipin]), border_side, + INPUT2INPUT_INTERC); } + } - for (int iport = 0; iport < top_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; - ++ipin) { - add_grid_module_net_connect_duplicated_pb_graph_pin( - module_manager, grid_module, child_module, child_instance, - vpr_device_annotation, grid_type_descriptor, - &(top_pb_graph_node->output_pins[iport][ipin]), border_side, - OUTPUT2OUTPUT_INTERC); - } + for (int iport = 0; iport < top_pb_graph_node->num_output_ports; ++iport) { + for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; + ++ipin) { + add_grid_module_net_connect_duplicated_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->output_pins[iport][ipin]), border_side, + OUTPUT2OUTPUT_INTERC); } + } - for (int iport = 0; iport < top_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; - ++ipin) { - add_grid_module_net_connect_pb_graph_pin( - module_manager, grid_module, child_module, child_instance, - vpr_device_annotation, grid_type_descriptor, - &(top_pb_graph_node->clock_pins[iport][ipin]), border_side, - INPUT2INPUT_INTERC); - } + for (int iport = 0; iport < top_pb_graph_node->num_clock_ports; ++iport) { + for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->clock_pins[iport][ipin]), border_side, + INPUT2INPUT_INTERC); } } } diff --git a/openfpga/src/fabric/build_grid_module_duplicated_pins.h b/openfpga/src/fabric/build_grid_module_duplicated_pins.h index 82067f2d0..66e1a5634 100644 --- a/openfpga/src/fabric/build_grid_module_duplicated_pins.h +++ b/openfpga/src/fabric/build_grid_module_duplicated_pins.h @@ -24,7 +24,7 @@ void add_grid_module_duplicated_pb_type_ports( void add_grid_module_nets_connect_duplicated_pb_type_ports( ModuleManager& module_manager, const ModuleId& grid_module, const ModuleId& child_module, const size_t& child_instance, - const VprDeviceAnnotation& vpr_device_annotation, + const t_sub_tile& sub_tile, const VprDeviceAnnotation& vpr_device_annotation, t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_grid_module_utils.cpp b/openfpga/src/fabric/build_grid_module_utils.cpp index 5a5f2c76e..c79262805 100644 --- a/openfpga/src/fabric/build_grid_module_utils.cpp +++ b/openfpga/src/fabric/build_grid_module_utils.cpp @@ -43,6 +43,7 @@ std::vector find_grid_module_pin_sides( void add_grid_module_net_connect_pb_graph_pin( ModuleManager& module_manager, const ModuleId& grid_module, const ModuleId& child_module, const size_t& child_instance, + const size_t& child_inst_subtile_index, const VprDeviceAnnotation& vpr_device_annotation, t_physical_tile_type_ptr grid_type_descriptor, t_pb_graph_pin* pb_graph_pin, const e_side& border_side, const e_pin2pin_interc_type& pin2pin_interc_type) { @@ -69,7 +70,7 @@ void add_grid_module_net_connect_pb_graph_pin( size_t grid_pin_index = pb_graph_pin->pin_count_in_cluster + vpr_device_annotation.physical_tile_z_to_start_pin_index( - grid_type_descriptor, child_instance); + grid_type_descriptor, child_inst_subtile_index); int pin_height = grid_type_descriptor->pin_height_offset[grid_pin_index]; int pin_width = grid_type_descriptor->pin_width_offset[grid_pin_index]; for (const e_side& side : grid_pin_sides) { diff --git a/openfpga/src/fabric/build_grid_module_utils.h b/openfpga/src/fabric/build_grid_module_utils.h index d93fc43ee..c1f0549dd 100644 --- a/openfpga/src/fabric/build_grid_module_utils.h +++ b/openfpga/src/fabric/build_grid_module_utils.h @@ -23,6 +23,7 @@ std::vector find_grid_module_pin_sides( void add_grid_module_net_connect_pb_graph_pin( ModuleManager& module_manager, const ModuleId& grid_module, const ModuleId& child_module, const size_t& child_instance, + const size_t& child_inst_subtile_index, const VprDeviceAnnotation& vpr_device_annotation, t_physical_tile_type_ptr grid_type_descriptor, t_pb_graph_pin* pb_graph_pin, const e_side& border_side, diff --git a/openfpga/src/fabric/build_grid_modules.cpp b/openfpga/src/fabric/build_grid_modules.cpp index 6773273f7..bf8ca86ac 100644 --- a/openfpga/src/fabric/build_grid_modules.cpp +++ b/openfpga/src/fabric/build_grid_modules.cpp @@ -6,6 +6,7 @@ #include /* Headers from vtrutil library */ +#include "command_exit_codes.h" #include "vtr_assert.h" #include "vtr_geometry.h" #include "vtr_log.h" @@ -15,6 +16,7 @@ #include "build_grid_module_duplicated_pins.h" #include "build_grid_module_utils.h" #include "build_grid_modules.h" +#include "build_memory_modules.h" #include "circuit_library_utils.h" #include "module_manager_utils.h" #include "openfpga_interconnect_types.h" @@ -108,50 +110,49 @@ static void add_grid_module_pb_type_ports( static void add_grid_module_nets_connect_pb_type_ports( ModuleManager& module_manager, const ModuleId& grid_module, const ModuleId& child_module, const size_t& child_instance, - const VprDeviceAnnotation& vpr_device_annotation, + const t_sub_tile& sub_tile, const VprDeviceAnnotation& vpr_device_annotation, t_physical_tile_type_ptr grid_type_descriptor, const e_side& border_side) { /* Ensure that we have a valid grid_type_descriptor */ VTR_ASSERT(nullptr != grid_type_descriptor); /* FIXME: Currently support only 1 equivalent site! Should clarify this * limitation in documentation! */ - for (const t_sub_tile& sub_tile : grid_type_descriptor->sub_tiles) { - VTR_ASSERT(sub_tile.equivalent_sites.size() == 1); - t_logical_block_type_ptr lb_type = sub_tile.equivalent_sites[0]; - t_pb_graph_node* top_pb_graph_node = lb_type->pb_graph_head; - VTR_ASSERT(nullptr != top_pb_graph_node); + VTR_ASSERT(sub_tile.equivalent_sites.size() == 1); + t_logical_block_type_ptr lb_type = sub_tile.equivalent_sites[0]; + t_pb_graph_node* top_pb_graph_node = lb_type->pb_graph_head; + VTR_ASSERT(nullptr != top_pb_graph_node); + size_t child_inst_subtile_index = sub_tile.capacity.low + child_instance; - for (int iport = 0; iport < top_pb_graph_node->num_input_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; - ++ipin) { - add_grid_module_net_connect_pb_graph_pin( - module_manager, grid_module, child_module, child_instance, - vpr_device_annotation, grid_type_descriptor, - &(top_pb_graph_node->input_pins[iport][ipin]), border_side, - INPUT2INPUT_INTERC); - } + for (int iport = 0; iport < top_pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < top_pb_graph_node->num_input_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->input_pins[iport][ipin]), border_side, + INPUT2INPUT_INTERC); } + } - for (int iport = 0; iport < top_pb_graph_node->num_output_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; - ++ipin) { - add_grid_module_net_connect_pb_graph_pin( - module_manager, grid_module, child_module, child_instance, - vpr_device_annotation, grid_type_descriptor, - &(top_pb_graph_node->output_pins[iport][ipin]), border_side, - OUTPUT2OUTPUT_INTERC); - } + for (int iport = 0; iport < top_pb_graph_node->num_output_ports; ++iport) { + for (int ipin = 0; ipin < top_pb_graph_node->num_output_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->output_pins[iport][ipin]), border_side, + OUTPUT2OUTPUT_INTERC); } + } - for (int iport = 0; iport < top_pb_graph_node->num_clock_ports; ++iport) { - for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; - ++ipin) { - add_grid_module_net_connect_pb_graph_pin( - module_manager, grid_module, child_module, child_instance, - vpr_device_annotation, grid_type_descriptor, - &(top_pb_graph_node->clock_pins[iport][ipin]), border_side, - INPUT2INPUT_INTERC); - } + for (int iport = 0; iport < top_pb_graph_node->num_clock_ports; ++iport) { + for (int ipin = 0; ipin < top_pb_graph_node->num_clock_pins[iport]; + ++ipin) { + add_grid_module_net_connect_pb_graph_pin( + module_manager, grid_module, child_module, child_instance, + child_inst_subtile_index, vpr_device_annotation, grid_type_descriptor, + &(top_pb_graph_node->clock_pins[iport][ipin]), border_side, + INPUT2INPUT_INTERC); } } } @@ -266,7 +267,7 @@ static void build_primitive_block_module( const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, t_pb_graph_node* primitive_pb_graph_node, - const bool& verbose) { + const bool& group_config_block, const bool& verbose) { /* Ensure a valid pb_graph_node */ VTR_ASSERT(nullptr != primitive_pb_graph_node); @@ -278,7 +279,8 @@ static void build_primitive_block_module( std::string primitive_module_name = generate_physical_block_module_name(primitive_pb_graph_node->pb_type); - VTR_LOGV(verbose, "Building module '%s'...", primitive_module_name.c_str()); + VTR_LOGV(verbose, "Building primitive module '%s'...\n", + primitive_module_name.c_str()); /* Create a module of the primitive LUT and register it to module manager */ ModuleId primitive_module = module_manager.add_module(primitive_module_name); @@ -311,11 +313,13 @@ static void build_primitive_block_module( } /* Regular (independent) SRAM ports */ + e_config_protocol_type mem_module_type = + group_config_block ? CONFIG_MEM_FEEDTHROUGH : sram_orgz_type; size_t num_config_bits = - find_circuit_num_config_bits(sram_orgz_type, circuit_lib, primitive_model); + find_circuit_num_config_bits(mem_module_type, circuit_lib, primitive_model); if (0 < num_config_bits) { add_sram_ports_to_module_manager(module_manager, primitive_module, - circuit_lib, sram_model, sram_orgz_type, + circuit_lib, sram_model, mem_module_type, num_config_bits); } @@ -334,9 +338,9 @@ static void build_primitive_block_module( circuit_lib, primitive_pb_graph_node->pb_type, device_annotation); /* Add the associated memory module as a child of primitive module */ - std::string memory_module_name = - generate_memory_module_name(circuit_lib, primitive_model, sram_model, - std::string(MEMORY_MODULE_POSTFIX)); + std::string memory_module_name = generate_memory_module_name( + circuit_lib, primitive_model, sram_model, + std::string(MEMORY_MODULE_POSTFIX), group_config_block); ModuleId memory_module = module_manager.find_module(memory_module_name); /* If there is no memory module required, we can skip the assocated net @@ -356,18 +360,41 @@ static void build_primitive_block_module( module_manager, primitive_module, logic_module, logic_instance_id, memory_module, memory_instance_id, circuit_lib, primitive_model); /* Record memory-related information */ - module_manager.add_configurable_child(primitive_module, memory_module, - memory_instance_id); + size_t config_child_id = module_manager.num_configurable_children( + primitive_module, ModuleManager::e_config_child_type::LOGICAL); + module_manager.add_configurable_child( + primitive_module, memory_module, memory_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); + /* For logical memory, define the physical memory here */ + if (group_config_block) { + std::string physical_memory_module_name = + generate_memory_module_name(circuit_lib, primitive_model, sram_model, + std::string(MEMORY_MODULE_POSTFIX), false); + ModuleId physical_memory_module = + module_manager.find_module(physical_memory_module_name); + VTR_LOGV(verbose, + "Mapping feedthrough memory module '%s' to physical memory " + "module '%s'...\n", + memory_module_name.c_str(), physical_memory_module_name.c_str()); + VTR_ASSERT(module_manager.valid_module_id(physical_memory_module)); + module_manager.set_logical2physical_configurable_child( + primitive_module, config_child_id, physical_memory_module); + module_manager.set_logical2physical_configurable_child_instance_name( + primitive_module, config_child_id, physical_memory_module_name); + } } /* Add all the nets to connect configuration ports from memory module to * primitive modules This is a one-shot addition that covers all the memory * modules in this primitive module! */ - if (0 < module_manager.configurable_children(primitive_module).size()) { - add_module_nets_memory_config_bus(module_manager, decoder_lib, - primitive_module, sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + if (0 < module_manager.num_configurable_children( + primitive_module, ModuleManager::e_config_child_type::LOGICAL)) { + add_module_nets_memory_config_bus( + module_manager, decoder_lib, primitive_module, mem_module_type, + circuit_lib.design_tech_type(sram_model), + ModuleManager::e_config_child_type::LOGICAL); } /* Add global ports to the pb_module: @@ -505,7 +532,7 @@ static void add_module_pb_graph_pin_interc( std::vector& memory_modules, std::vector& memory_instances, const VprDeviceAnnotation& device_annotation, const CircuitLibrary& circuit_lib, t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode) { + t_mode* physical_mode, const bool& group_config_block, const bool& verbose) { /* Find the number of fan-in and detailed interconnection information * related to the destination pb_graph_pin */ @@ -629,6 +656,11 @@ static void add_module_pb_graph_pin_interc( std::string mux_mem_module_name = generate_mux_subckt_name(circuit_lib, interc_circuit_model, fan_in, std::string(MEMORY_MODULE_POSTFIX)); + if (group_config_block) { + mux_mem_module_name = generate_mux_subckt_name( + circuit_lib, interc_circuit_model, fan_in, + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + } ModuleId mux_mem_module = module_manager.find_module(mux_mem_module_name); VTR_ASSERT(true == module_manager.valid_module_id(mux_mem_module)); size_t mux_mem_instance = @@ -639,12 +671,38 @@ static void add_module_pb_graph_pin_interc( * generation to modules */ std::string mux_mem_instance_name = generate_pb_memory_instance_name( - GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); + GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string(""), + group_config_block); module_manager.set_child_instance_name( pb_module, mux_mem_module, mux_mem_instance, mux_mem_instance_name); /* Add this MUX as a configurable child to the pb_module */ - module_manager.add_configurable_child(pb_module, mux_mem_module, - mux_mem_instance); + size_t config_child_id = module_manager.num_configurable_children( + pb_module, ModuleManager::e_config_child_type::LOGICAL); + module_manager.add_configurable_child( + pb_module, mux_mem_module, mux_mem_instance, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); + if (group_config_block) { + std::string phy_mem_module_name = + generate_mux_subckt_name(circuit_lib, interc_circuit_model, fan_in, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId phy_mem_module = + module_manager.find_module(phy_mem_module_name); + VTR_ASSERT(module_manager.valid_module_id(phy_mem_module)); + VTR_LOGV(verbose, + "Mapping feedthrough memory module '%s' to physical memory " + "module '%s'...\n", + mux_mem_module_name.c_str(), phy_mem_module_name.c_str()); + module_manager.set_logical2physical_configurable_child( + pb_module, config_child_id, phy_mem_module); + std::string phy_mux_mem_instance_name = + generate_pb_memory_instance_name( + GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string(""), false); + module_manager.set_logical2physical_configurable_child_instance_name( + pb_module, config_child_id, phy_mux_mem_instance_name); + VTR_LOGV(verbose, "Now use a feedthrough memory for '%s'\n", + phy_mem_module_name.c_str()); + } /* Add nets to connect SRAM ports of the MUX to the SRAM port of memory * module */ @@ -733,7 +791,8 @@ static void add_module_pb_graph_port_interc( std::vector& memory_modules, std::vector& memory_instances, const VprDeviceAnnotation& device_annotation, const CircuitLibrary& circuit_lib, t_pb_graph_node* des_pb_graph_node, - const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode) { + const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode, + const bool& group_config_block, const bool& verbose) { switch (pb_port_type) { case CIRCUIT_PB_PORT_INPUT: { for (int iport = 0; iport < des_pb_graph_node->num_input_ports; ++iport) { @@ -743,7 +802,8 @@ static void add_module_pb_graph_port_interc( add_module_pb_graph_pin_interc( module_manager, pb_module, memory_modules, memory_instances, device_annotation, circuit_lib, - &(des_pb_graph_node->input_pins[iport][ipin]), physical_mode); + &(des_pb_graph_node->input_pins[iport][ipin]), physical_mode, + group_config_block, verbose); } } break; @@ -756,7 +816,8 @@ static void add_module_pb_graph_port_interc( add_module_pb_graph_pin_interc( module_manager, pb_module, memory_modules, memory_instances, device_annotation, circuit_lib, - &(des_pb_graph_node->output_pins[iport][ipin]), physical_mode); + &(des_pb_graph_node->output_pins[iport][ipin]), physical_mode, + group_config_block, verbose); } } break; @@ -768,7 +829,8 @@ static void add_module_pb_graph_port_interc( add_module_pb_graph_pin_interc( module_manager, pb_module, memory_modules, memory_instances, device_annotation, circuit_lib, - &(des_pb_graph_node->clock_pins[iport][ipin]), physical_mode); + &(des_pb_graph_node->clock_pins[iport][ipin]), physical_mode, + group_config_block, verbose); } } break; @@ -815,7 +877,8 @@ static void add_module_pb_graph_interc( std::vector& memory_modules, std::vector& memory_instances, const VprDeviceAnnotation& device_annotation, const CircuitLibrary& circuit_lib, t_pb_graph_node* physical_pb_graph_node, - const int& physical_mode_index) { + const int& physical_mode_index, const bool& group_config_block, + const bool& verbose) { /* Check cur_pb_graph_node*/ VTR_ASSERT(nullptr != physical_pb_graph_node); @@ -831,10 +894,10 @@ static void add_module_pb_graph_interc( * | * input_pins, edges, output_pins */ - add_module_pb_graph_port_interc(module_manager, pb_module, memory_modules, - memory_instances, device_annotation, - circuit_lib, physical_pb_graph_node, - CIRCUIT_PB_PORT_OUTPUT, physical_mode); + add_module_pb_graph_port_interc( + module_manager, pb_module, memory_modules, memory_instances, + device_annotation, circuit_lib, physical_pb_graph_node, + CIRCUIT_PB_PORT_OUTPUT, physical_mode, group_config_block, verbose); /* We check input_pins of child_pb_graph_node and its the input_edges * Built the interconnections between inputs of cur_pb_graph_node and inputs @@ -857,16 +920,16 @@ static void add_module_pb_graph_interc( &(physical_pb_graph_node ->child_pb_graph_nodes[physical_mode_index][child][inst]); /* For each child_pb_graph_node input pins*/ - add_module_pb_graph_port_interc(module_manager, pb_module, memory_modules, - memory_instances, device_annotation, - circuit_lib, child_pb_graph_node, - CIRCUIT_PB_PORT_INPUT, physical_mode); + add_module_pb_graph_port_interc( + module_manager, pb_module, memory_modules, memory_instances, + device_annotation, circuit_lib, child_pb_graph_node, + CIRCUIT_PB_PORT_INPUT, physical_mode, group_config_block, verbose); /* For each child_pb_graph_node clock pins*/ - add_module_pb_graph_port_interc(module_manager, pb_module, memory_modules, - memory_instances, device_annotation, - circuit_lib, child_pb_graph_node, - CIRCUIT_PB_PORT_CLOCK, physical_mode); + add_module_pb_graph_port_interc( + module_manager, pb_module, memory_modules, memory_instances, + device_annotation, circuit_lib, child_pb_graph_node, + CIRCUIT_PB_PORT_CLOCK, physical_mode, group_config_block, verbose); } } } @@ -893,7 +956,7 @@ static void rec_build_logical_tile_modules( const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, t_pb_graph_node* physical_pb_graph_node, - const bool& verbose) { + const bool& group_config_block, const bool& verbose) { /* Check cur_pb_graph_node*/ VTR_ASSERT(nullptr != physical_pb_graph_node); @@ -914,7 +977,7 @@ static void rec_build_logical_tile_modules( sram_orgz_type, sram_model, &(physical_pb_graph_node ->child_pb_graph_nodes[physical_mode->index][ipb][0]), - verbose); + group_config_block, verbose); } } @@ -922,7 +985,8 @@ static void rec_build_logical_tile_modules( if (true == is_primitive_pb_type(physical_pb_type)) { build_primitive_block_module(module_manager, decoder_lib, device_annotation, circuit_lib, sram_orgz_type, sram_model, - physical_pb_graph_node, verbose); + physical_pb_graph_node, group_config_block, + verbose); /* Finish for primitive node, return */ return; } @@ -931,7 +995,7 @@ static void rec_build_logical_tile_modules( std::string pb_module_name = generate_physical_block_module_name(physical_pb_type); - VTR_LOGV(verbose, "Building module '%s'...", pb_module_name.c_str()); + VTR_LOGV(verbose, "Building module '%s'...\n", pb_module_name.c_str()); /* Register the Verilog module in module manager */ ModuleId pb_module = module_manager.add_module(pb_module_name); @@ -950,6 +1014,9 @@ static void rec_build_logical_tile_modules( std::vector memory_modules; std::vector memory_instances; + e_config_protocol_type mem_module_type = + group_config_block ? CONFIG_MEM_FEEDTHROUGH : sram_orgz_type; + /* Add all the child Verilog modules as instances */ for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) { /* Get the name and module id for this child pb_type */ @@ -987,14 +1054,19 @@ static void rec_build_logical_tile_modules( module_manager.set_child_instance_name( pb_module, child_pb_module, child_instance_id, child_pb_instance_name); + VTR_LOGV(verbose, "Building instance '%s'\n", + child_pb_instance_name.c_str()); + /* Identify if this sub module includes configuration bits, * we will update the memory module and instance list */ if (0 < find_module_num_config_bits(module_manager, child_pb_module, circuit_lib, sram_model, - sram_orgz_type)) { - module_manager.add_configurable_child(pb_module, child_pb_module, - child_instance_id); + mem_module_type)) { + module_manager.add_configurable_child( + pb_module, child_pb_module, child_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); } } } @@ -1002,9 +1074,11 @@ static void rec_build_logical_tile_modules( /* Add modules and nets for programmable/non-programmable interconnections * inside the Verilog module */ + VTR_LOGV(verbose, "Building local interconnecting modules\n"); add_module_pb_graph_interc(module_manager, pb_module, memory_modules, memory_instances, device_annotation, circuit_lib, - physical_pb_graph_node, physical_mode->index); + physical_pb_graph_node, physical_mode->index, + group_config_block, verbose); /* Add global ports to the pb_module: * This is a much easier job after adding sub modules (instances), @@ -1040,10 +1114,11 @@ static void rec_build_logical_tile_modules( */ size_t module_num_config_bits = find_module_num_config_bits_from_child_modules( - module_manager, pb_module, circuit_lib, sram_model, sram_orgz_type); + module_manager, pb_module, circuit_lib, sram_model, mem_module_type, + ModuleManager::e_config_child_type::LOGICAL); if (0 < module_num_config_bits) { add_sram_ports_to_module_manager(module_manager, pb_module, circuit_lib, - sram_model, sram_orgz_type, + sram_model, mem_module_type, module_num_config_bits); } @@ -1051,10 +1126,12 @@ static void rec_build_logical_tile_modules( * This is a one-shot addition that covers all the memory modules in this pb * module! */ - if (0 < module_manager.configurable_children(pb_module).size()) { - add_module_nets_memory_config_bus(module_manager, decoder_lib, pb_module, - sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + if (0 < module_manager.num_configurable_children( + pb_module, ModuleManager::e_config_child_type::LOGICAL)) { + add_module_nets_memory_config_bus( + module_manager, decoder_lib, pb_module, mem_module_type, + circuit_lib.design_tech_type(sram_model), + ModuleManager::e_config_child_type::LOGICAL); } VTR_LOGV(verbose, "Done\n"); @@ -1068,14 +1145,15 @@ static void rec_build_logical_tile_modules( * The param 'border_side' is required, which is specify which side of fabric * the I/O block locates at. *****************************************************************************/ -static void build_physical_tile_module( +static int build_physical_tile_module( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const VprDeviceAnnotation& vpr_device_annotation, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, t_physical_tile_type_ptr phy_block_type, const e_side& border_side, const bool& duplicate_grid_pin, - const bool& verbose) { + const bool& group_config_block, const bool& verbose) { + int status = CMD_EXEC_SUCCESS; /* Create a Module for the top-level physical block, and add to module manager */ std::string grid_module_name = generate_grid_block_module_name( @@ -1094,7 +1172,8 @@ static void build_physical_tile_module( * it as a mode under a */ for (const t_sub_tile& sub_tile : phy_block_type->sub_tiles) { - for (int iz = 0; iz < sub_tile.capacity.total(); ++iz) { + for (int iz = sub_tile.capacity.low; iz < sub_tile.capacity.high + 1; + ++iz) { VTR_ASSERT(1 == sub_tile.equivalent_sites.size()); t_logical_block_type_ptr lb_type = sub_tile.equivalent_sites[0]; /* Bypass empty pb_graph */ @@ -1124,15 +1203,29 @@ static void build_physical_tile_module( /* Identify if this sub module includes configuration bits, * we will update the memory module and instance list */ - if (0 < find_module_num_config_bits(module_manager, pb_module, - circuit_lib, sram_model, - sram_orgz_type)) { - module_manager.add_configurable_child(grid_module, pb_module, - pb_instance_id); + if (0 < find_module_num_config_bits( + module_manager, pb_module, circuit_lib, sram_model, + group_config_block ? CONFIG_MEM_FEEDTHROUGH : sram_orgz_type)) { + /* Only add logical configurable children here. Since we will add a + * physical memory block at this level */ + module_manager.add_configurable_child( + grid_module, pb_module, pb_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); } } } + /* TODO: Add a physical memory block */ + if (group_config_block) { + status = add_physical_memory_module(module_manager, decoder_lib, + grid_module, circuit_lib, + sram_orgz_type, sram_model, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + /* Add grid ports(pins) to the module */ if (false == duplicate_grid_pin) { /* Default way to add these ports by following the definition in pb_types */ @@ -1154,7 +1247,7 @@ static void build_physical_tile_module( for (const size_t& child_instance : module_manager.child_module_instances(grid_module, pb_module)) { add_grid_module_nets_connect_pb_type_ports( - module_manager, grid_module, pb_module, child_instance, + module_manager, grid_module, pb_module, child_instance, sub_tile, vpr_device_annotation, phy_block_type, border_side); } } @@ -1180,7 +1273,7 @@ static void build_physical_tile_module( for (const size_t& child_instance : module_manager.child_module_instances(grid_module, pb_module)) { add_grid_module_nets_connect_duplicated_pb_type_ports( - module_manager, grid_module, pb_module, child_instance, + module_manager, grid_module, pb_module, child_instance, sub_tile, vpr_device_annotation, phy_block_type, border_side); } } @@ -1218,9 +1311,13 @@ static void build_physical_tile_module( * we just need to find all the I/O ports from the child modules and build a * list of it */ + ModuleManager::e_config_child_type config_child_type = + group_config_block ? ModuleManager::e_config_child_type::PHYSICAL + : ModuleManager::e_config_child_type::LOGICAL; size_t module_num_config_bits = find_module_num_config_bits_from_child_modules( - module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type); + module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type, + config_child_type); if (0 < module_num_config_bits) { add_pb_sram_ports_to_module_manager(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type, @@ -1231,13 +1328,16 @@ static void build_physical_tile_module( * This is a one-shot addition that covers all the memory modules in this pb * module! */ - if (0 < module_manager.configurable_children(grid_module).size()) { + if (0 < module_manager.num_configurable_children(grid_module, + config_child_type)) { add_pb_module_nets_memory_config_bus( module_manager, decoder_lib, grid_module, sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + circuit_lib.design_tech_type(sram_model), config_child_type); } VTR_LOGV(verbose, "Done\n"); + + return status; } /***************************************************************************** @@ -1253,18 +1353,18 @@ static void build_physical_tile_module( * - Only one module for each CLB (FILL_TYPE) * - Only one module for each heterogeneous block ****************************************************************************/ -void build_grid_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const bool& duplicate_grid_pin, const bool& verbose) { +int build_grid_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const bool& duplicate_grid_pin, + const bool& group_config_block, const bool& verbose) { /* Start time count */ vtr::ScopedStartFinishTimer timer("Build grid modules"); + int status = CMD_EXEC_SUCCESS; + /* Enumerate the types of logical tiles, and build a module for each * Build modules for all the pb_types/pb_graph_nodes * use a Depth-First Search Algorithm to print the sub-modules @@ -1284,7 +1384,8 @@ void build_grid_modules(ModuleManager& module_manager, } rec_build_logical_tile_modules( module_manager, decoder_lib, device_annotation, circuit_lib, mux_lib, - sram_orgz_type, sram_model, logical_tile.pb_graph_head, verbose); + sram_orgz_type, sram_model, logical_tile.pb_graph_head, + group_config_block, verbose); } VTR_LOG("Done\n"); @@ -1311,20 +1412,28 @@ void build_grid_modules(ModuleManager& module_manager, std::set io_type_sides = find_physical_io_tile_located_sides(device_ctx.grid, &physical_tile); for (const e_side& io_type_side : io_type_sides) { - build_physical_tile_module(module_manager, decoder_lib, - device_annotation, circuit_lib, - sram_orgz_type, sram_model, &physical_tile, - io_type_side, duplicate_grid_pin, verbose); + status = build_physical_tile_module( + module_manager, decoder_lib, device_annotation, circuit_lib, + sram_orgz_type, sram_model, &physical_tile, io_type_side, + duplicate_grid_pin, group_config_block, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } } } else { /* For CLB and heterogenenous blocks */ - build_physical_tile_module(module_manager, decoder_lib, device_annotation, - circuit_lib, sram_orgz_type, sram_model, - &physical_tile, NUM_SIDES, duplicate_grid_pin, - verbose); + status = build_physical_tile_module( + module_manager, decoder_lib, device_annotation, circuit_lib, + sram_orgz_type, sram_model, &physical_tile, NUM_SIDES, + duplicate_grid_pin, group_config_block, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } } } VTR_LOG("Done\n"); + + return status; } } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_grid_modules.h b/openfpga/src/fabric/build_grid_modules.h index 61c0963c3..d83cc3ac3 100644 --- a/openfpga/src/fabric/build_grid_modules.h +++ b/openfpga/src/fabric/build_grid_modules.h @@ -17,15 +17,13 @@ /* begin namespace openfpga */ namespace openfpga { -void build_grid_modules(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, - const bool& duplicate_grid_pin, const bool& verbose); +int build_grid_modules( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, const bool& duplicate_grid_pin, + const bool& group_config_block, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index 9ce406ca6..80899a04c 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -3,15 +3,18 @@ * the memories that are affiliated to multiplexers and other programmable * circuit models, such as IOPADs, LUTs, etc. ********************************************************************/ +#include "build_memory_modules.h" + #include #include +#include #include -/* Headers from vtrutil library */ #include "build_decoder_modules.h" -#include "build_memory_modules.h" #include "circuit_library_utils.h" +#include "command_exit_codes.h" #include "decoder_library_utils.h" +#include "memory_utils.h" #include "module_manager.h" #include "module_manager_utils.h" #include "mux_graph.h" @@ -173,7 +176,11 @@ static void add_module_nets_to_cmos_memory_config_chain_module( const CircuitLibrary& circuit_lib, const CircuitPortId& model_input_port, const CircuitPortId& model_output_port) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::LOGICAL) + .size(); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -193,28 +200,30 @@ static void add_module_nets_to_cmos_memory_config_chain_module( /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, + ModuleManager::e_config_child_type::LOGICAL)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, + ModuleManager::e_config_child_type::LOGICAL)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } @@ -248,9 +257,15 @@ static void add_module_nets_to_cmos_memory_config_chain_module( /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); ModuleId net_src_module_id = - module_manager.configurable_children(parent_module).back(); + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::LOGICAL) + .back(); size_t net_src_instance_id = - module_manager.configurable_child_instances(parent_module).back(); + module_manager + .configurable_child_instances(parent_module, + ModuleManager::e_config_child_type::LOGICAL) + .back(); ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); @@ -310,7 +325,11 @@ static void add_module_nets_to_cmos_memory_scan_chain_module( const CircuitLibrary& circuit_lib, const CircuitPortId& model_input_port, const CircuitPortId& model_output_port) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::LOGICAL) + .size(); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -330,28 +349,30 @@ static void add_module_nets_to_cmos_memory_scan_chain_module( /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, + ModuleManager::e_config_child_type::LOGICAL)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, + ModuleManager::e_config_child_type::LOGICAL)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::LOGICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } @@ -404,7 +425,8 @@ static void build_memory_flatten_module(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const std::string& module_name, const CircuitModelId& sram_model, - const size_t& num_mems) { + const size_t& num_mems, + const bool& verbose) { /* Get the global ports required by the SRAM */ std::vector global_port_types; global_port_types.push_back(CIRCUIT_MODEL_PORT_CLOCK); @@ -433,6 +455,7 @@ static void build_memory_flatten_module(ModuleManager& module_manager, VTR_ASSERT(2 == sram_output_ports.size()); /* Create a module and add to the module manager */ + VTR_LOGV(verbose, "Building memory module '%s'\n", module_name.c_str()); ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -479,8 +502,9 @@ static void build_memory_flatten_module(ModuleManager& module_manager, size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_mem_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_mem_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Build module nets */ /* Wire inputs of parent module to inputs of child modules */ @@ -530,7 +554,8 @@ static void build_memory_chain_module(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const std::string& module_name, const CircuitModelId& sram_model, - const size_t& num_mems) { + const size_t& num_mems, + const bool& verbose) { /* Get the input ports from the SRAM */ std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); @@ -546,6 +571,7 @@ static void build_memory_chain_module(ModuleManager& module_manager, (3 == sram_output_ports.size())); /* Create a module and add to the module manager */ + VTR_LOGV(verbose, "Building memory module '%s'\n", module_name.c_str()); ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -612,8 +638,9 @@ static void build_memory_chain_module(ModuleManager& module_manager, size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_mem_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_mem_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Build module nets to wire outputs of sram modules to outputs of memory * module */ @@ -689,7 +716,8 @@ static void build_frame_memory_module(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const std::string& module_name, const CircuitModelId& sram_model, - const size_t& num_mems) { + const size_t& num_mems, + const bool& verbose) { /* Get the global ports required by the SRAM */ std::vector global_port_types; global_port_types.push_back(CIRCUIT_MODEL_PORT_CLOCK); @@ -732,6 +760,7 @@ static void build_frame_memory_module(ModuleManager& module_manager, VTR_ASSERT(0 == sram_blb_ports.size()); /* Create a module and add to the module manager */ + VTR_LOGV(verbose, "Building memory module '%s'\n", module_name.c_str()); ModuleId mem_module = module_manager.add_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -829,8 +858,9 @@ static void build_frame_memory_module(ModuleManager& module_manager, size_t sram_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Wire data_in port to SRAM BL port */ ModulePortId sram_bl_port = module_manager.find_module_port( @@ -890,7 +920,8 @@ static void build_frame_memory_module(ModuleManager& module_manager, add_module_global_ports_from_child_modules(module_manager, mem_module); /* Add the decoder as the last configurable children */ - module_manager.add_configurable_child(mem_module, decoder_module, 0); + module_manager.add_configurable_child( + mem_module, decoder_module, 0, ModuleManager::e_config_child_type::UNIFIED); } /********************************************************************* @@ -909,21 +940,21 @@ static void build_memory_module(ModuleManager& module_manager, const e_config_protocol_type& sram_orgz_type, const std::string& module_name, const CircuitModelId& sram_model, - const size_t& num_mems) { + const size_t& num_mems, const bool& verbose) { switch (sram_orgz_type) { case CONFIG_MEM_STANDALONE: case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: build_memory_flatten_module(module_manager, circuit_lib, module_name, - sram_model, num_mems); + sram_model, num_mems, verbose); break; case CONFIG_MEM_SCAN_CHAIN: build_memory_chain_module(module_manager, circuit_lib, module_name, - sram_model, num_mems); + sram_model, num_mems, verbose); break; case CONFIG_MEM_FRAME_BASED: build_frame_memory_module(module_manager, arch_decoder_lib, circuit_lib, - module_name, sram_model, num_mems); + module_name, sram_model, num_mems, verbose); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -932,6 +963,84 @@ static void build_memory_module(ModuleManager& module_manager, } } +/********************************************************************* + * Generate Verilog modules for the feedthrough memories that are used + * by a circuit model + * mem_out mem_outb + * | | + * v v + * +------------------------------------+ + * | | + * | | + * | | + * +------------------------------------+ + * | | + * | mem_in | mem_inb + * v v + * +------------------------------------+ + * | Multiplexer Configuration port | + * + ********************************************************************/ +static int build_feedthrough_memory_module(ModuleManager& module_manager, + const std::string& module_name, + const size_t& num_mems, + const bool& verbose) { + /* Create a module and add to the module manager */ + VTR_LOGV(verbose, "Building feedthrough memory module '%s'\n", + module_name.c_str()); + ModuleId mem_module = module_manager.add_module(module_name); + if (!module_manager.valid_module_id(mem_module)) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Label module usage */ + module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG); + + /* Add module ports */ + /* Input: memory inputs */ + BasicPort in_port(std::string(MEMORY_FEEDTHROUGH_DATA_IN_PORT_NAME), + num_mems); + ModulePortId mem_in_port = module_manager.add_port( + mem_module, in_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort inb_port(std::string(MEMORY_FEEDTHROUGH_DATA_IN_INV_PORT_NAME), + num_mems); + ModulePortId mem_inb_port = module_manager.add_port( + mem_module, inb_port, ModuleManager::MODULE_INPUT_PORT); + + /* Add each output port */ + BasicPort out_port(std::string(CONFIGURABLE_MEMORY_DATA_OUT_NAME), num_mems); + ModulePortId mem_out_port = module_manager.add_port( + mem_module, out_port, ModuleManager::MODULE_OUTPUT_PORT); + BasicPort outb_port(std::string(CONFIGURABLE_MEMORY_INVERTED_DATA_OUT_NAME), + num_mems); + ModulePortId mem_outb_port = module_manager.add_port( + mem_module, outb_port, ModuleManager::MODULE_OUTPUT_PORT); + + /* Build feedthrough nets */ + for (size_t pin_id = 0; pin_id < in_port.pins().size(); ++pin_id) { + ModuleNetId net = module_manager.create_module_net(mem_module); + if (!module_manager.valid_module_net_id(mem_module, net)) { + return CMD_EXEC_FATAL_ERROR; + } + module_manager.add_module_net_source(mem_module, net, mem_module, 0, + mem_in_port, in_port.pins()[pin_id]); + module_manager.add_module_net_sink(mem_module, net, mem_module, 0, + mem_out_port, out_port.pins()[pin_id]); + } + for (size_t pin_id = 0; pin_id < inb_port.pins().size(); ++pin_id) { + ModuleNetId net = module_manager.create_module_net(mem_module); + if (!module_manager.valid_module_net_id(mem_module, net)) { + return CMD_EXEC_FATAL_ERROR; + } + module_manager.add_module_net_source(mem_module, net, mem_module, 0, + mem_inb_port, inb_port.pins()[pin_id]); + module_manager.add_module_net_sink(mem_module, net, mem_module, 0, + mem_outb_port, outb_port.pins()[pin_id]); + } + + return CMD_EXEC_SUCCESS; +} + /********************************************************************* * Generate Verilog modules for the memories that are used * by multiplexers @@ -949,7 +1058,7 @@ static void build_mux_memory_module( ModuleManager& module_manager, DecoderLibrary& arch_decoder_lib, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& mux_model, - const MuxGraph& mux_graph) { + const MuxGraph& mux_graph, const bool& verbose) { /* Find the actual number of configuration bits, based on the mux graph * Due to the use of local decoders inside mux, this may be */ @@ -973,7 +1082,7 @@ static void build_mux_memory_module( build_memory_module(module_manager, arch_decoder_lib, circuit_lib, sram_orgz_type, module_name, sram_models[0], - num_config_bits); + num_config_bits, verbose); break; } case CIRCUIT_MODEL_DESIGN_RRAM: @@ -990,6 +1099,61 @@ static void build_mux_memory_module( } } +/********************************************************************* + * Generate Verilog modules for the feedthrough memories that are used + * by multiplexers + * SRAM ports as feedthrough (driven by physical memory blocks) + * | | | | + * v v ... v v + * +----------------+ + * | Memory Module | + * +----------------+ + * | | ... | | + * v v v v SRAM ports of multiplexer + * +---------------------+ + * in--->| Multiplexer Module |---> out + * +---------------------+ + ********************************************************************/ +static int build_mux_feedthrough_memory_module( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, const CircuitModelId& mux_model, + const MuxGraph& mux_graph, const bool& verbose) { + int status = CMD_EXEC_SUCCESS; + /* Find the actual number of configuration bits, based on the mux graph + * Due to the use of local decoders inside mux, this may be + */ + size_t num_config_bits = + find_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type); + /* Multiplexers built with different technology is in different organization + */ + switch (circuit_lib.design_tech_type(mux_model)) { + case CIRCUIT_MODEL_DESIGN_CMOS: { + /* Generate module name */ + std::string module_name = generate_mux_subckt_name( + circuit_lib, mux_model, + find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()), + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + + status = build_feedthrough_memory_module(module_manager, module_name, + num_config_bits, verbose); + break; + } + case CIRCUIT_MODEL_DESIGN_RRAM: + /* We do not need a memory submodule for RRAM MUX, + * RRAM are embedded in the datapath + * TODO: generate local encoders for RRAM-based multiplexers here!!! + */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid design technology of multiplexer '%s'\n", + circuit_lib.model_name(mux_model).c_str()); + exit(1); + } + return status; +} + /********************************************************************* * Build modules for * the memories that are affiliated to multiplexers and other programmable @@ -1005,12 +1169,17 @@ static void build_mux_memory_module( * memory modules. * Take another example, the memory circuit can implement the scan-chain or * memory-bank organization for the memories. + * If we need feedthrough memory blocks, build the memory modules which contain + *only feedthrough wires ********************************************************************/ -void build_memory_modules(ModuleManager& module_manager, - DecoderLibrary& arch_decoder_lib, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type) { +int build_memory_modules(ModuleManager& module_manager, + DecoderLibrary& arch_decoder_lib, + const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const bool& require_feedthrough_memory, + const bool& verbose) { + int status = CMD_EXEC_SUCCESS; vtr::ScopedStartFinishTimer timer("Build memory modules"); /* Create the memory circuits for the multiplexer */ @@ -1026,7 +1195,16 @@ void build_memory_modules(ModuleManager& module_manager, } /* Create a Verilog module for the memories used by the multiplexer */ build_mux_memory_module(module_manager, arch_decoder_lib, circuit_lib, - sram_orgz_type, mux_model, mux_graph); + sram_orgz_type, mux_model, mux_graph, verbose); + /* Create feedthrough memory module */ + if (require_feedthrough_memory) { + status = build_mux_feedthrough_memory_module(module_manager, circuit_lib, + sram_orgz_type, mux_model, + mux_graph, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } } /* Create the memory circuits for non-MUX circuit models. @@ -1062,8 +1240,381 @@ void build_memory_modules(ModuleManager& module_manager, /* Create a Verilog module for the memories used by the circuit model */ build_memory_module(module_manager, arch_decoder_lib, circuit_lib, - sram_orgz_type, module_name, sram_models[0], num_mems); + sram_orgz_type, module_name, sram_models[0], num_mems, + verbose); + /* Create feedthrough memory module */ + if (require_feedthrough_memory) { + module_name = + generate_memory_module_name(circuit_lib, model, sram_models[0], + std::string(MEMORY_MODULE_POSTFIX), true); + status = build_feedthrough_memory_module(module_manager, module_name, + num_mems, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + } + return status; +} + +/********************************************************************* + * Add module nets to connect an output port of a configuration-chain + * memory module to an output port of its child module + * Restriction: this function is really designed for memory modules + * 1. It assumes that output port name of child module is the same as memory + *module + * 2. It assumes exact pin-to-pin mapping: + * j-th pin of output port of the i-th child module is wired to the j + i*W + *-th pin of output port of the memory module, where W is the size of port + * 3. It assumes fixed port name for output ports + ********************************************************************/ +static void add_module_output_nets_to_memory_group_module( + ModuleManager& module_manager, const ModuleId& mem_module, + const std::string& mem_module_output_name, const ModuleId& child_module, + const size_t& output_pin_start_index, const size_t& child_instance) { + /* Wire inputs of parent module to inputs of child modules */ + ModulePortId src_port_id = + module_manager.find_module_port(child_module, mem_module_output_name); + ModulePortId sink_port_id = + module_manager.find_module_port(mem_module, mem_module_output_name); + for (size_t pin_id = 0; + pin_id < + module_manager.module_port(child_module, src_port_id).pins().size(); + ++pin_id) { + ModuleNetId net = module_manager.create_module_net(mem_module); + /* Source pin is shifted by the number of memories */ + size_t src_pin_id = + module_manager.module_port(child_module, src_port_id).pins()[pin_id]; + /* Source node of the input net is the input of memory module */ + module_manager.add_module_net_source( + mem_module, net, child_module, child_instance, src_port_id, src_pin_id); + /* Sink node of the input net is the input of sram module */ + size_t sink_pin_id = + output_pin_start_index + + module_manager.module_port(mem_module, sink_port_id).pins()[pin_id]; + module_manager.add_module_net_sink(mem_module, net, mem_module, 0, + sink_port_id, sink_pin_id); } } +/********************************************************************* + * Build a grouped memory module based on existing memory modules + * - Create the module + * - Add dedicated instance + * - Add ports + * - Add nets + ********************************************************************/ +int build_memory_group_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, const std::string& module_name, + const CircuitModelId& sram_model, const std::vector& child_modules, + const std::vector& child_instance_names, const size_t& num_mems, + const bool& verbose) { + VTR_LOGV(verbose, "Building memory group module '%s'...\n", + module_name.c_str()); + ModuleId mem_module = module_manager.add_module(module_name); + if (!module_manager.valid_module_id(mem_module)) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Label module usage */ + module_manager.set_module_usage(mem_module, + ModuleManager::MODULE_CONFIG_GROUP); + + /* Add output ports */ + std::string out_port_name = generate_configurable_memory_data_out_name(); + BasicPort out_port(out_port_name, num_mems); + module_manager.add_port(mem_module, out_port, + ModuleManager::MODULE_OUTPUT_PORT); + + std::string outb_port_name = + generate_configurable_memory_inverted_data_out_name(); + BasicPort outb_port(outb_port_name, num_mems); + module_manager.add_port(mem_module, outb_port, + ModuleManager::MODULE_OUTPUT_PORT); + + /* Identify the duplicated instance name: This mainly comes from the grid + * modules, which contains multi-instanced blocks. Therefore, we just count + * the duplicated instance names and name each of them with a unique index, + * e.g., mem_lut -> mem_lut_0, mem_lut_1 etc. The only exception is for the + * uinque instance name, we keep the original instance name */ + std::vector unique_child_instance_names; + unique_child_instance_names.reserve(child_instance_names.size()); + std::map unique_child_instance_name_count; + for (std::string curr_inst_name : child_instance_names) { + auto result = unique_child_instance_name_count.find(curr_inst_name); + if (result == unique_child_instance_name_count.end()) { + unique_child_instance_name_count[curr_inst_name] = 1; + } else { + unique_child_instance_name_count[curr_inst_name]++; + } + } + std::map unique_child_instance_name_scoreboard; + for (std::string curr_inst_name : child_instance_names) { + if (1 == unique_child_instance_name_count[curr_inst_name]) { + unique_child_instance_names.push_back(curr_inst_name); + unique_child_instance_name_scoreboard[curr_inst_name] = 1; + continue; + } + auto result = unique_child_instance_name_scoreboard.find(curr_inst_name); + if (result == unique_child_instance_name_scoreboard.end()) { + unique_child_instance_name_scoreboard[curr_inst_name] = 0; + unique_child_instance_names.push_back(curr_inst_name); + } else { + unique_child_instance_name_scoreboard[curr_inst_name]++; + unique_child_instance_names.push_back(generate_instance_name( + curr_inst_name, unique_child_instance_name_scoreboard[curr_inst_name])); + } + } + VTR_ASSERT(unique_child_instance_names.size() == child_instance_names.size()); + + /* Add nets between child module outputs and memory modules */ + size_t mem_out_pin_start_index = 0; + size_t mem_outb_pin_start_index = 0; + for (size_t ichild = 0; ichild < child_modules.size(); ++ichild) { + ModuleId child_module = child_modules[ichild]; + size_t child_instance = + module_manager.num_instance(mem_module, child_module); + module_manager.add_child_module(mem_module, child_module, false); + module_manager.set_child_instance_name(mem_module, child_module, + child_instance, + unique_child_instance_names[ichild]); + module_manager.add_configurable_child( + mem_module, child_module, child_instance, + ModuleManager::e_config_child_type::UNIFIED); + /* Wire outputs of child module to outputs of parent module */ + ModulePortId child_out_port_id = + module_manager.find_module_port(child_module, out_port_name); + if (module_manager.valid_module_port_id(child_module, child_out_port_id)) { + add_module_output_nets_to_memory_group_module( + module_manager, mem_module, out_port_name, child_module, + mem_out_pin_start_index, child_instance); + /* Update pin counter */ + mem_out_pin_start_index += + module_manager.module_port(child_module, child_out_port_id).get_width(); + } + ModulePortId child_outb_port_id = + module_manager.find_module_port(child_module, outb_port_name); + if (module_manager.valid_module_port_id(child_module, child_outb_port_id)) { + add_module_output_nets_to_memory_group_module( + module_manager, mem_module, outb_port_name, child_module, + mem_outb_pin_start_index, child_instance); + /* Update pin counter */ + mem_outb_pin_start_index += + module_manager.module_port(child_module, child_outb_port_id) + .get_width(); + } + } + + /* Add global ports to the pb_module: + * This is a much easier job after adding sub modules (instances), + * we just need to find all the global ports from the child modules and build + * a list of it + */ + add_module_global_ports_from_child_modules(module_manager, mem_module); + + /* Count GPIO ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it + */ + add_module_gpio_ports_from_child_modules(module_manager, mem_module); + + /* Count shared SRAM ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it + */ + size_t module_num_shared_config_bits = + find_module_num_shared_config_bits_from_child_modules(module_manager, + mem_module); + if (0 < module_num_shared_config_bits) { + add_reserved_sram_ports_to_module_manager(module_manager, mem_module, + module_num_shared_config_bits); + } + + /* Count SRAM ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it + */ + ModuleManager::e_config_child_type config_child_type = + ModuleManager::e_config_child_type::PHYSICAL; + size_t module_num_config_bits = + find_module_num_config_bits_from_child_modules( + module_manager, mem_module, circuit_lib, sram_model, sram_orgz_type, + config_child_type); + if (0 < module_num_config_bits) { + add_sram_ports_to_module_manager(module_manager, mem_module, circuit_lib, + sram_model, sram_orgz_type, + module_num_config_bits); + } + + /* Add module nets to connect memory cells inside + * This is a one-shot addition that covers all the memory modules in this pb + * module! + */ + if (0 < + module_manager.num_configurable_children(mem_module, config_child_type)) { + add_module_nets_memory_config_bus( + module_manager, decoder_lib, mem_module, sram_orgz_type, + circuit_lib.design_tech_type(sram_model), config_child_type); + } + + return CMD_EXEC_SUCCESS; +} + +/***************************************************************************** + * This function creates a physical memory module and add it the current module + * The following tasks will be accomplished: + * - Traverse all the logical configurable children in the module tree, starting + *from the current module + * - Build a list of the leaf logical configurable children and count the total + *memory sizes, the memory size for each physical memory submodule. Note that + *the physical memory submodule should be cached already in each leaf logical + *configurable children + * - Get the physical memory module required by each leaf logical configurable + *child + * - Create a dedicated module name for the physical memory (check if already + *exists, if yes, skip creating a new module) + * - Instanciate the module + * - Built nets. Note that only the output ports of the physical memory block is + *required, since they should drive the dedicated memory ports of logical + *configurable children + *****************************************************************************/ +int add_physical_memory_module(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& curr_module, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, + const bool& verbose) { + int status = CMD_EXEC_SUCCESS; + + std::vector required_phy_mem_modules; + std::vector required_phy_mem_instance_names; + status = rec_find_physical_memory_children( + static_cast(module_manager), curr_module, + required_phy_mem_modules, required_phy_mem_instance_names, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + + size_t module_num_config_bits = + find_module_num_config_bits_from_child_modules( + module_manager, curr_module, circuit_lib, sram_model, + CONFIG_MEM_FEEDTHROUGH, ModuleManager::e_config_child_type::LOGICAL); + /* No need to build a memory when there are no configuration bits required */ + if (module_num_config_bits == 0) { + return CMD_EXEC_SUCCESS; + } + std::string phy_mem_module_name = generate_physical_memory_module_name( + module_manager.module_name(curr_module), module_num_config_bits); + VTR_LOGV(verbose, "Adding memory group module '%s' as a child to '%s'...\n", + phy_mem_module_name.c_str(), + module_manager.module_name(curr_module).c_str()); + ModuleId phy_mem_module = module_manager.find_module(phy_mem_module_name); + if (!module_manager.valid_module_id(phy_mem_module)) { + status = build_memory_group_module( + module_manager, decoder_lib, circuit_lib, sram_orgz_type, + phy_mem_module_name, sram_model, required_phy_mem_modules, + required_phy_mem_instance_names, module_num_config_bits, verbose); + } + if (status != CMD_EXEC_SUCCESS) { + VTR_LOG_ERROR("Failed to create the physical memory module '%s'!\n", + phy_mem_module_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + phy_mem_module = module_manager.find_module(phy_mem_module_name); + if (!module_manager.valid_module_id(phy_mem_module)) { + VTR_LOG_ERROR("Failed to create the physical memory module '%s'!\n", + phy_mem_module_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Add the physical memory module to the current module */ + size_t phy_mem_instance = + module_manager.num_instance(curr_module, phy_mem_module); + module_manager.add_child_module(curr_module, phy_mem_module, false); + /* TODO: Give a more meaningful instance name? */ + module_manager.set_child_instance_name(curr_module, phy_mem_module, + phy_mem_instance, phy_mem_module_name); + + /* Register in the physical configurable children list */ + module_manager.add_configurable_child( + curr_module, phy_mem_module, phy_mem_instance, + ModuleManager::e_config_child_type::PHYSICAL); + + /* Build nets between the data output of the physical memory module and the + * outputs of the logical configurable children */ + std::map curr_mem_pin_index; + curr_mem_pin_index[CIRCUIT_MODEL_PORT_BL] = 0; + curr_mem_pin_index[CIRCUIT_MODEL_PORT_BLB] = 0; + std::map mem2mem_port_map; + mem2mem_port_map[CIRCUIT_MODEL_PORT_BL] = + std::string(CONFIGURABLE_MEMORY_DATA_OUT_NAME); + mem2mem_port_map[CIRCUIT_MODEL_PORT_BLB] = + std::string(CONFIGURABLE_MEMORY_INVERTED_DATA_OUT_NAME); + for (size_t ichild = 0; + ichild < module_manager + .configurable_children( + curr_module, ModuleManager::e_config_child_type::LOGICAL) + .size(); + ++ichild) { + ModuleId des_module = module_manager.configurable_children( + curr_module, ModuleManager::e_config_child_type::LOGICAL)[ichild]; + size_t des_instance = module_manager.configurable_child_instances( + curr_module, ModuleManager::e_config_child_type::LOGICAL)[ichild]; + + for (e_circuit_model_port_type port_type : + {CIRCUIT_MODEL_PORT_BL, CIRCUIT_MODEL_PORT_BLB}) { + std::string src_port_name = mem2mem_port_map[port_type]; + std::string des_port_name = + generate_sram_port_name(CONFIG_MEM_FEEDTHROUGH, port_type); + /* Try to find these ports in the module manager */ + ModulePortId src_port_id = + module_manager.find_module_port(phy_mem_module, src_port_name); + if (!module_manager.valid_module_port_id(phy_mem_module, src_port_id)) { + return CMD_EXEC_FATAL_ERROR; + } + BasicPort src_port = + module_manager.module_port(phy_mem_module, src_port_id); + + ModulePortId des_port_id = + module_manager.find_module_port(des_module, des_port_name); + if (!module_manager.valid_module_port_id(des_module, des_port_id)) { + return CMD_EXEC_FATAL_ERROR; + } + BasicPort des_port = module_manager.module_port(des_module, des_port_id); + /* Build nets */ + for (size_t ipin = 0; ipin < des_port.pins().size(); ++ipin) { + VTR_LOGV( + verbose, "Building net '%s[%lu].%s[%lu]' -> '%s[%lu].%s[%lu]\n", + module_manager.module_name(phy_mem_module).c_str(), phy_mem_instance, + src_port.get_name().c_str(), curr_mem_pin_index[port_type], + module_manager.module_name(des_module).c_str(), des_instance, + des_port.get_name().c_str(), des_port.pins()[ipin]); + /* Create a net and add source and sink to it */ + ModuleNetId net = create_module_source_pin_net( + module_manager, curr_module, phy_mem_module, phy_mem_instance, + src_port_id, src_port.pins()[curr_mem_pin_index[port_type]]); + if (!module_manager.valid_module_net_id(curr_module, net)) { + return CMD_EXEC_FATAL_ERROR; + } + /* Add net sink */ + module_manager.add_module_net_sink(curr_module, net, des_module, + des_instance, des_port_id, + des_port.pins()[ipin]); + curr_mem_pin_index[port_type]++; + } + } + } + VTR_ASSERT(curr_mem_pin_index[CIRCUIT_MODEL_PORT_BL] == + module_num_config_bits); + VTR_ASSERT(curr_mem_pin_index[CIRCUIT_MODEL_PORT_BLB] == + module_num_config_bits); + + return status; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_memory_modules.h b/openfpga/src/fabric/build_memory_modules.h index 5eeaf25e8..b79fd4b90 100644 --- a/openfpga/src/fabric/build_memory_modules.h +++ b/openfpga/src/fabric/build_memory_modules.h @@ -22,11 +22,29 @@ std::vector add_module_output_nets_to_chain_mem_modules( const CircuitPortId& circuit_port, const ModuleId& child_module, const size_t& child_index, const size_t& child_instance); -void build_memory_modules(ModuleManager& module_manager, - DecoderLibrary& arch_decoder_lib, - const MuxLibrary& mux_lib, - const CircuitLibrary& circuit_lib, - const e_config_protocol_type& sram_orgz_type); +int build_memory_modules(ModuleManager& module_manager, + DecoderLibrary& arch_decoder_lib, + const MuxLibrary& mux_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const bool& require_feedthrough_memory, + const bool& verbose); + +int build_memory_group_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, const std::string& module_name, + const CircuitModelId& sram_model, const std::vector& child_modules, + const std::vector& child_instance_names, const size_t& num_mems, + const bool& verbose); + +int add_physical_memory_module(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& curr_module, + const CircuitLibrary& circuit_lib, + const e_config_protocol_type& sram_orgz_type, + const CircuitModelId& sram_model, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_routing_module_utils.cpp b/openfpga/src/fabric/build_routing_module_utils.cpp index 9ecef274d..e1f3db9ad 100644 --- a/openfpga/src/fabric/build_routing_module_utils.cpp +++ b/openfpga/src/fabric/build_routing_module_utils.cpp @@ -77,8 +77,9 @@ std::string generate_sb_module_grid_port_name( int pin_id = rr_graph.node_pin_num(rr_node); e_side pin_side = get_rr_graph_single_node_side(rr_graph, rr_node); t_physical_tile_type_ptr physical_tile = - vpr_device_grid[rr_graph.node_xlow(rr_node)][rr_graph.node_ylow(rr_node)] - .type; + vpr_device_grid.get_physical_type(t_physical_tile_loc( + rr_graph.node_xlow(rr_node), rr_graph.node_ylow(rr_node), + rr_graph.node_layer(rr_node))); int pin_width_offset = physical_tile->pin_width_offset[pin_id]; int pin_height_offset = physical_tile->pin_height_offset[pin_id]; BasicPort pin_info = @@ -112,8 +113,9 @@ std::string generate_cb_module_grid_port_name( int pin_id = rr_graph.node_pin_num(rr_node); e_side pin_side = get_rr_graph_single_node_side(rr_graph, rr_node); t_physical_tile_type_ptr physical_tile = - vpr_device_grid[rr_graph.node_xlow(rr_node)][rr_graph.node_ylow(rr_node)] - .type; + vpr_device_grid.get_physical_type(t_physical_tile_loc( + rr_graph.node_xlow(rr_node), rr_graph.node_ylow(rr_node), + rr_graph.node_layer(rr_node))); int pin_width_offset = physical_tile->pin_width_offset[pin_id]; int pin_height_offset = physical_tile->pin_height_offset[pin_id]; BasicPort pin_info = diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index f57ccce29..1f12774c5 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -14,6 +14,7 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ +#include "build_memory_modules.h" #include "build_module_graph_utils.h" #include "build_routing_module_utils.h" #include "build_routing_modules.h" @@ -108,7 +109,8 @@ static void build_switch_block_mux_module( const CircuitLibrary& circuit_lib, const e_side& chan_side, const size_t& chan_node_id, const RRNodeId& cur_rr_node, const std::vector& driver_rr_nodes, const RRSwitchId& switch_index, - const std::map& input_port_to_module_nets) { + const std::map& input_port_to_module_nets, + const bool& group_config_block) { /* Check current rr_node is CHANX or CHANY*/ VTR_ASSERT((CHANX == rr_graph.node_type(cur_rr_node)) || (CHANY == rr_graph.node_type(cur_rr_node))); @@ -214,6 +216,11 @@ static void build_switch_block_mux_module( std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); + if (group_config_block) { + mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + } ModuleId mem_module = module_manager.find_module(mem_module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -224,7 +231,8 @@ static void build_switch_block_mux_module( * modules */ std::string mem_instance_name = generate_sb_memory_instance_name( - SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, std::string("")); + SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, std::string(""), + group_config_block); module_manager.set_child_instance_name(sb_module, mem_module, mem_instance_id, mem_instance_name); @@ -234,7 +242,28 @@ static void build_switch_block_mux_module( module_manager, sb_module, mux_module, mux_instance_id, mem_module, mem_instance_id, circuit_lib, mux_model); /* Update memory and instance list */ - module_manager.add_configurable_child(sb_module, mem_module, mem_instance_id); + size_t config_child_id = module_manager.num_configurable_children( + sb_module, ModuleManager::e_config_child_type::LOGICAL); + module_manager.add_configurable_child( + sb_module, mem_module, mem_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); + /* For logical memory, define the physical memory here */ + if (group_config_block) { + std::string physical_mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId physical_mem_module = + module_manager.find_module(physical_mem_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(physical_mem_module)); + module_manager.set_logical2physical_configurable_child( + sb_module, config_child_id, physical_mem_module); + std::string physical_mem_instance_name = generate_sb_memory_instance_name( + SWITCH_BLOCK_MEM_INSTANCE_PREFIX, chan_side, chan_node_id, + std::string(""), false); + module_manager.set_logical2physical_configurable_child_instance_name( + sb_module, config_child_id, physical_mem_instance_name); + } } /********************************************************************* @@ -248,7 +277,8 @@ static void build_switch_block_interc_modules( const RRGraphView& rr_graph, const RRGSB& rr_gsb, const CircuitLibrary& circuit_lib, const e_side& chan_side, const size_t& chan_node_id, - const std::map& input_port_to_module_nets) { + const std::map& input_port_to_module_nets, + const bool& group_config_block) { std::vector driver_rr_nodes; /* Get the node */ @@ -284,7 +314,7 @@ static void build_switch_block_interc_modules( build_switch_block_mux_module( module_manager, sb_module, device_annotation, grids, rr_graph, rr_gsb, circuit_lib, chan_side, chan_node_id, cur_rr_node, driver_rr_nodes, - driver_switches[0], input_port_to_module_nets); + driver_switches[0], input_port_to_module_nets, group_config_block); } /*Nothing should be done else*/ } @@ -354,7 +384,8 @@ static void build_switch_block_module( const VprDeviceAnnotation& device_annotation, const DeviceGrid& grids, const RRGraphView& rr_graph, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const RRGSB& rr_gsb, const bool& verbose) { + const CircuitModelId& sram_model, const RRGSB& rr_gsb, + const bool& group_config_block, const bool& verbose) { /* Create a Module of Switch Block and add to module manager */ vtr::Point gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); ModuleId sb_module = module_manager.add_module( @@ -456,11 +487,18 @@ static void build_switch_block_module( build_switch_block_interc_modules( module_manager, sb_module, device_annotation, grids, rr_graph, rr_gsb, circuit_lib, side_manager.get_side(), itrack, - input_port_to_module_nets); + input_port_to_module_nets, group_config_block); } } } + /* Build a physical memory block */ + if (group_config_block) { + add_physical_memory_module(module_manager, decoder_lib, sb_module, + circuit_lib, sram_orgz_type, sram_model, + verbose); + } + /* Add global ports to the pb_module: * This is a much easier job after adding sub modules (instances), * we just need to find all the global ports from the child modules and build @@ -486,9 +524,13 @@ static void build_switch_block_module( * we just need to find all the I/O ports from the child modules and build a * list of it */ + ModuleManager::e_config_child_type config_child_type = + group_config_block ? ModuleManager::e_config_child_type::PHYSICAL + : ModuleManager::e_config_child_type::LOGICAL; size_t module_num_config_bits = find_module_num_config_bits_from_child_modules( - module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type); + module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type, + config_child_type); if (0 < module_num_config_bits) { add_pb_sram_ports_to_module_manager(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type, @@ -499,10 +541,11 @@ static void build_switch_block_module( * primitive modules This is a one-shot addition that covers all the memory * modules in this primitive module! */ - if (0 < module_manager.configurable_children(sb_module).size()) { + if (0 < + module_manager.num_configurable_children(sb_module, config_child_type)) { add_pb_module_nets_memory_config_bus( module_manager, decoder_lib, sb_module, sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + circuit_lib.design_tech_type(sram_model), config_child_type); } VTR_LOGV(verbose, "Done\n"); @@ -586,7 +629,8 @@ static void build_connection_block_mux_module( const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, const CircuitLibrary& circuit_lib, const e_side& cb_ipin_side, const size_t& ipin_index, - const std::map& input_port_to_module_nets) { + const std::map& input_port_to_module_nets, + const bool& group_config_block) { const RRNodeId& cur_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); /* Check current rr_node is an input pin of a CLB */ VTR_ASSERT(IPIN == rr_graph.node_type(cur_rr_node)); @@ -697,6 +741,11 @@ static void build_connection_block_mux_module( std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX)); + if (group_config_block) { + mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + } ModuleId mem_module = module_manager.find_module(mem_module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -711,7 +760,7 @@ static void build_connection_block_mux_module( CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, get_rr_graph_single_node_side( rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, ipin_index)), - ipin_index, std::string("")); + ipin_index, std::string(""), group_config_block); module_manager.set_child_instance_name(cb_module, mem_module, mem_instance_id, mem_instance_name); @@ -721,7 +770,30 @@ static void build_connection_block_mux_module( module_manager, cb_module, mux_module, mux_instance_id, mem_module, mem_instance_id, circuit_lib, mux_model); /* Update memory and instance list */ - module_manager.add_configurable_child(cb_module, mem_module, mem_instance_id); + size_t config_child_id = module_manager.num_configurable_children( + cb_module, ModuleManager::e_config_child_type::LOGICAL); + module_manager.add_configurable_child( + cb_module, mem_module, mem_instance_id, + group_config_block ? ModuleManager::e_config_child_type::LOGICAL + : ModuleManager::e_config_child_type::UNIFIED); + /* For logical memory, define the physical memory here */ + if (group_config_block) { + std::string physical_mem_module_name = + generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_MODULE_POSTFIX)); + ModuleId physical_mem_module = + module_manager.find_module(physical_mem_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(physical_mem_module)); + module_manager.set_logical2physical_configurable_child( + cb_module, config_child_id, physical_mem_module); + std::string physical_mem_instance_name = generate_cb_memory_instance_name( + CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, ipin_index)), + ipin_index, std::string(""), false); + module_manager.set_logical2physical_configurable_child_instance_name( + cb_module, config_child_id, physical_mem_instance_name); + } } /******************************************************************** @@ -737,7 +809,8 @@ static void build_connection_block_interc_modules( const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type, const CircuitLibrary& circuit_lib, const e_side& cb_ipin_side, const size_t& ipin_index, - const std::map& input_port_to_module_nets) { + const std::map& input_port_to_module_nets, + const bool& group_config_block) { std::vector driver_rr_edges = rr_gsb.get_ipin_node_in_edges(rr_graph, cb_ipin_side, ipin_index); @@ -753,8 +826,8 @@ static void build_connection_block_interc_modules( /* Print the multiplexer, fan_in >= 2 */ build_connection_block_mux_module( module_manager, cb_module, device_annotation, grids, rr_graph, rr_gsb, - cb_type, circuit_lib, cb_ipin_side, ipin_index, - input_port_to_module_nets); + cb_type, circuit_lib, cb_ipin_side, ipin_index, input_port_to_module_nets, + group_config_block); } /*Nothing should be done else*/ } @@ -819,7 +892,8 @@ static void build_connection_block_module( const RRGraphView& rr_graph, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, const RRGSB& rr_gsb, - const t_rr_type& cb_type, const bool& verbose) { + const t_rr_type& cb_type, const bool& group_config_block, + const bool& verbose) { /* Create the netlist */ vtr::Point gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)); @@ -941,10 +1015,18 @@ static void build_connection_block_module( ++inode) { build_connection_block_interc_modules( module_manager, cb_module, device_annotation, grids, rr_graph, rr_gsb, - cb_type, circuit_lib, cb_ipin_side, inode, input_port_to_module_nets); + cb_type, circuit_lib, cb_ipin_side, inode, input_port_to_module_nets, + group_config_block); } } + /* Build a physical memory block */ + if (group_config_block) { + add_physical_memory_module(module_manager, decoder_lib, cb_module, + circuit_lib, sram_orgz_type, sram_model, + verbose); + } + /* Add global ports to the pb_module: * This is a much easier job after adding sub modules (instances), * we just need to find all the global ports from the child modules and build @@ -970,9 +1052,13 @@ static void build_connection_block_module( * we just need to find all the I/O ports from the child modules and build a * list of it */ + ModuleManager::e_config_child_type config_child_type = + group_config_block ? ModuleManager::e_config_child_type::PHYSICAL + : ModuleManager::e_config_child_type::LOGICAL; size_t module_num_config_bits = find_module_num_config_bits_from_child_modules( - module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type); + module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type, + config_child_type); if (0 < module_num_config_bits) { add_pb_sram_ports_to_module_manager(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type, @@ -983,10 +1069,11 @@ static void build_connection_block_module( * primitive modules This is a one-shot addition that covers all the memory * modules in this primitive module! */ - if (0 < module_manager.configurable_children(cb_module).size()) { + if (0 < + module_manager.num_configurable_children(cb_module, config_child_type)) { add_pb_module_nets_memory_config_bus( module_manager, decoder_lib, cb_module, sram_orgz_type, - circuit_lib.design_tech_type(sram_model)); + circuit_lib.design_tech_type(sram_model), config_child_type); } VTR_LOGV(verbose, "Done\n"); @@ -1002,7 +1089,7 @@ static void build_flatten_connection_block_modules( const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, const t_rr_type& cb_type, - const bool& verbose) { + const bool& group_config_block, const bool& verbose) { /* Build unique X-direction connection block modules */ vtr::Point cb_range = device_rr_gsb.get_gsb_range(); @@ -1019,7 +1106,7 @@ static void build_flatten_connection_block_modules( build_connection_block_module( module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, rr_gsb, - cb_type, verbose); + cb_type, group_config_block, verbose); } } } @@ -1038,7 +1125,8 @@ void build_flatten_routing_modules( const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const bool& verbose) { + const CircuitModelId& sram_model, const bool& group_config_block, + const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build routing modules..."); vtr::Point sb_range = device_rr_gsb.get_gsb_range(); @@ -1047,23 +1135,25 @@ void build_flatten_routing_modules( for (size_t ix = 0; ix < sb_range.x(); ++ix) { for (size_t iy = 0; iy < sb_range.y(); ++iy) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(device_ctx.rr_graph)) { continue; } build_switch_block_module(module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, rr_gsb, - verbose); + group_config_block, verbose); } } build_flatten_connection_block_modules( module_manager, decoder_lib, device_ctx, device_annotation, device_rr_gsb, - circuit_lib, sram_orgz_type, sram_model, CHANX, verbose); + circuit_lib, sram_orgz_type, sram_model, CHANX, group_config_block, + verbose); build_flatten_connection_block_modules( module_manager, decoder_lib, device_ctx, device_annotation, device_rr_gsb, - circuit_lib, sram_orgz_type, sram_model, CHANY, verbose); + circuit_lib, sram_orgz_type, sram_model, CHANY, group_config_block, + verbose); } /******************************************************************** @@ -1082,7 +1172,8 @@ void build_unique_routing_modules( const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const bool& verbose) { + const CircuitModelId& sram_model, const bool& group_config_block, + const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build unique routing modules..."); /* Build unique switch block modules */ @@ -1091,7 +1182,7 @@ void build_unique_routing_modules( build_switch_block_module(module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, unique_mirror, - verbose); + group_config_block, verbose); } /* Build unique X-direction connection block modules */ @@ -1102,7 +1193,7 @@ void build_unique_routing_modules( build_connection_block_module( module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, - unique_mirror, CHANX, verbose); + unique_mirror, CHANX, group_config_block, verbose); } /* Build unique X-direction connection block modules */ @@ -1113,7 +1204,7 @@ void build_unique_routing_modules( build_connection_block_module( module_manager, decoder_lib, device_annotation, device_ctx.grid, device_ctx.rr_graph, circuit_lib, sram_orgz_type, sram_model, - unique_mirror, CHANY, verbose); + unique_mirror, CHANY, group_config_block, verbose); } } diff --git a/openfpga/src/fabric/build_routing_modules.h b/openfpga/src/fabric/build_routing_modules.h index 59274bc11..038da3b3e 100644 --- a/openfpga/src/fabric/build_routing_modules.h +++ b/openfpga/src/fabric/build_routing_modules.h @@ -24,14 +24,16 @@ void build_flatten_routing_modules( const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const bool& verbose); + const CircuitModelId& sram_model, const bool& group_config_block, + const bool& verbose); void build_unique_routing_modules( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, - const CircuitModelId& sram_model, const bool& verbose); + const CircuitModelId& sram_model, const bool& group_config_block, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_tile_modules.cpp b/openfpga/src/fabric/build_tile_modules.cpp new file mode 100644 index 000000000..f20215f71 --- /dev/null +++ b/openfpga/src/fabric/build_tile_modules.cpp @@ -0,0 +1,1530 @@ +/******************************************************************** + * This file includes functions that are used to build the location + * map information for the top-level module of the FPGA fabric + * It helps OpenFPGA to link the I/O port index in top-level module + * to the VPR I/O mapping results + *******************************************************************/ +#include "build_tile_modules.h" + +#include +#include + +#include "build_grid_module_utils.h" +#include "build_routing_module_utils.h" +#include "build_top_module_utils.h" +#include "command_exit_codes.h" +#include "module_manager_utils.h" +#include "openfpga_device_grid_utils.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "openfpga_rr_graph_utils.h" +#include "openfpga_side_manager.h" +#include "rr_gsb_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Add module nets to connect a GSB to adjacent grid ports/pins + * as well as connection blocks + * This function will create nets for the following types of connections + * between grid output pins of Switch block and adjacent grids + * In this case, the net source is the grid pin, while the net sink + * is the switch block pin + * + * +------------+ +------------+ + * | | | | + * | Grid | | Grid | + * | [x][y+1] | | [x+1][y+1] | + * | |----+ +----| | + * +------------+ | | +------------+ + * | v v | + * | +------------+ | + * +------>| |<-----+ + * | Switch | + * | Block | + * +------>| [x][y] |<-----+ + * | +------------+ | + * | ^ ^ | + * | | | | + * +------------+ | | +------------+ + * | |----+ +-----| | + * | Grid | | Grid | + * | [x][y] | | [x+1][y] | + * | | | | + * +------------+ +------------+ + * + *******************************************************************/ +static int build_tile_module_port_and_nets_between_sb_and_pb( + ModuleManager& module_manager, const ModuleId& tile_module, + const DeviceGrid& grids, const size_t& layer, + const VprDeviceAnnotation& vpr_device_annotation, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph, + const RRGSB& rr_gsb, const FabricTile& fabric_tile, + const FabricTileId& fabric_tile_id, const std::vector& pb_instances, + const std::vector& sb_instances, const size_t& isb, + const bool& compact_routing_hierarchy, const bool& frame_view, + const bool& verbose) { + /* Skip those Switch blocks that do not exist */ + if (false == rr_gsb.is_sb_exist(rr_graph)) { + return CMD_EXEC_SUCCESS; + } + + size_t sb_instance = sb_instances[isb]; + + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), + rr_gsb.get_sb_y()); + vtr::Point module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); + + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ + if (true == compact_routing_hierarchy) { + vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); + const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord); + module_gsb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_coordinate.set_y(unique_mirror.get_y()); + } + + /* This is the source cb that is added to the top module */ + const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_coordinate); + vtr::Point module_sb_coordinate(module_sb.get_sb_x(), + module_sb.get_sb_y()); + + /* Collect sink-related information */ + std::string sink_sb_module_name = + generate_switch_block_module_name(module_sb_coordinate); + ModuleId sink_sb_module = module_manager.find_module(sink_sb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(sink_sb_module)); + size_t sink_sb_instance = sb_instance; + + /* Connect grid output pins (OPIN) to switch block grid pins */ + for (size_t side = 0; side < module_sb.get_num_sides(); ++side) { + SideManager side_manager(side); + for (size_t inode = 0; + inode < module_sb.get_num_opin_nodes(side_manager.get_side()); + ++inode) { + /* Collect source-related information */ + /* Generate the grid module name by considering if it locates on the + * border */ + vtr::Point grid_coordinate( + rr_graph.node_xlow( + rr_gsb.get_opin_node(side_manager.get_side(), inode)), + rr_graph.node_ylow( + rr_gsb.get_opin_node(side_manager.get_side(), inode))); + std::string src_grid_module_name = + generate_grid_block_module_name_in_top_module( + std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate); + ModuleId src_grid_module = + module_manager.find_module(src_grid_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(src_grid_module)); + size_t src_grid_pin_index = rr_graph.node_pin_num( + rr_gsb.get_opin_node(side_manager.get_side(), inode)); + + t_physical_tile_type_ptr grid_type_descriptor = grids.get_physical_type( + t_physical_tile_loc(grid_coordinate.x(), grid_coordinate.y(), layer)); + size_t src_grid_pin_width = + grid_type_descriptor->pin_width_offset[src_grid_pin_index]; + size_t src_grid_pin_height = + grid_type_descriptor->pin_height_offset[src_grid_pin_index]; + BasicPort src_grid_pin_info = + vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, + src_grid_pin_index); + VTR_ASSERT(true == src_grid_pin_info.is_valid()); + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, src_grid_pin_index); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); + std::string src_grid_port_name = generate_grid_port_name( + src_grid_pin_width, src_grid_pin_height, subtile_index, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)), + src_grid_pin_info); + ModulePortId src_grid_port_id = + module_manager.find_module_port(src_grid_module, src_grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module, + src_grid_port_id)); + BasicPort src_grid_port = + module_manager.module_port(src_grid_module, src_grid_port_id); + + /* Collect sink-related information */ + vtr::Point sink_sb_port_coord( + rr_graph.node_xlow( + module_sb.get_opin_node(side_manager.get_side(), inode)), + rr_graph.node_ylow( + module_sb.get_opin_node(side_manager.get_side(), inode))); + std::string sink_sb_port_name = generate_sb_module_grid_port_name( + side_manager.get_side(), + get_rr_graph_single_node_side( + rr_graph, module_sb.get_opin_node(side_manager.get_side(), inode)), + grids, vpr_device_annotation, rr_graph, + module_sb.get_opin_node(side_manager.get_side(), inode)); + ModulePortId sink_sb_port_id = + module_manager.find_module_port(sink_sb_module, sink_sb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(sink_sb_module, + sink_sb_port_id)); + BasicPort sink_sb_port = + module_manager.module_port(sink_sb_module, sink_sb_port_id); + + /* Check if the grid is inside the tile, if not, create ports */ + if (fabric_tile.pb_in_tile(fabric_tile_id, grid_coordinate)) { + VTR_LOGV(verbose, + "Build intra-tile nets between switch block '%s' and " + "programmable block '%s[%lu][%lu]'\n", + sink_sb_module_name.c_str(), src_grid_module_name.c_str(), + grid_coordinate.x(), grid_coordinate.y()); + if (!frame_view) { + size_t src_grid_instance = + pb_instances[fabric_tile.find_pb_index_in_tile(fabric_tile_id, + grid_coordinate)]; + + /* Source and sink port should match in size */ + VTR_ASSERT(src_grid_port.get_width() == sink_sb_port.get_width()); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < src_grid_port.pins().size(); + ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, src_grid_module, src_grid_instance, + src_grid_port_id, src_grid_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink( + tile_module, net, sink_sb_module, sink_sb_instance, + sink_sb_port_id, sink_sb_port.pins()[pin_id]); + } + } + } else { + /* Create a port on the tile module and create the net if required. + * Create a proper name to avoid naming conflicts */ + src_grid_port.set_name(generate_tile_module_port_name( + generate_switch_block_module_name( + fabric_tile.sb_coordinates(fabric_tile_id)[isb]), + sink_sb_port.get_name())); + ModulePortId src_tile_port_id = module_manager.add_port( + tile_module, src_grid_port, + ModuleManager::e_module_port_type::MODULE_INPUT_PORT); + VTR_LOGV( + verbose, + "Adding ports '%s' to tile as required by the switch block '%s'...\n", + src_grid_port.to_verilog_string().c_str(), + sink_sb_module_name.c_str()); + if (!frame_view) { + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < src_grid_port.pins().size(); + ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, tile_module, 0, src_tile_port_id, + src_grid_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink( + tile_module, net, sink_sb_module, sink_sb_instance, + sink_sb_port_id, sink_sb_port.pins()[pin_id]); + } + } + } + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * This function will create nets for the connections + * between grid input pins and connection blocks + * In this case, the net source is the connection block pin, + * while the net sink is the grid input + * + * +------------+ +------------------+ +------------+ + * | | | | | | + * | Grid |<-----| Connection Block |----->| Grid | + * | [x][y+1] | | Y-direction | | [x+1][y+1] | + * | | | [x][y+1] | | | + * +------------+ +------------------+ +------------+ + * ^ + * | + * +------------+ +------------------+ + * | Connection | | | + * | Block | | Switch Block | + * | X-direction| | [x][y] | + * | [x][y] | | | + * +------------+ +------------------+ + * | + * v + * +------------+ + * | | + * | Grid | + * | [x][y] | + * | | + * +------------+ + * + * + * Relationship between source connection block and its unique module + * Take an example of a CBY + * + * grid_pin name should follow unique module of Grid[x][y+1] + * cb_pin name should follow unique module of CBY[x][y+1] + * + * However, instace id should follow the origin Grid and Connection block + * + * + * +------------+ +------------------+ + * | | | | + * | Grid |<------------| Connection Block | + * | [x][y+1] | | Y-direction | + * | | | [x][y+1] | + * +------------+ +------------------+ + * ^ + * || unique mirror + * +------------+ +------------------+ + * | | | | + * | Grid |<------------| Connection Block | + * | [i][j+1] | | Y-direction | + * | | | [i][j+1] | + * +------------+ +------------------+ + * + *******************************************************************/ +static int build_tile_module_port_and_nets_between_cb_and_pb( + ModuleManager& module_manager, const ModuleId& tile_module, + const DeviceGrid& grids, const size_t& layer, + const VprDeviceAnnotation& vpr_device_annotation, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph, + const RRGSB& rr_gsb, const FabricTile& fabric_tile, + const FabricTileId& fabric_tile_id, const t_rr_type& cb_type, + const std::vector& pb_instances, + const std::map>& cb_instances, + const size_t& icb, const bool& compact_routing_hierarchy, + const bool& frame_view, const bool& verbose) { + size_t cb_instance = cb_instances.at(cb_type)[icb]; + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_cb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + vtr::Point module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); + + /* Skip those Connection blocks that do not exist */ + if (false == rr_gsb.is_cb_exist(cb_type)) { + return CMD_EXEC_SUCCESS; + } + + /* Skip if the cb does not contain any configuration bits! */ + if (true == connection_block_contain_only_routing_tracks(rr_gsb, cb_type)) { + return CMD_EXEC_SUCCESS; + } + + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ + if (true == compact_routing_hierarchy) { + vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, gsb_coord); + module_gsb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_coordinate.set_y(unique_mirror.get_y()); + } + + /* This is the source cb that is added to the top module */ + const RRGSB& module_cb = device_rr_gsb.get_gsb(module_gsb_coordinate); + vtr::Point module_cb_coordinate(module_cb.get_cb_x(cb_type), + module_cb.get_cb_y(cb_type)); + + /* Collect source-related information */ + std::string src_cb_module_name = + generate_connection_block_module_name(cb_type, module_cb_coordinate); + ModuleId src_cb_module = module_manager.find_module(src_cb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(src_cb_module)); + /* Instance id should follow the instance cb coordinate */ + size_t src_cb_instance = cb_instance; + + /* Iterate over the output pins of the Connection Block */ + std::vector cb_ipin_sides = module_cb.get_cb_ipin_sides(cb_type); + for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) { + enum e_side cb_ipin_side = cb_ipin_sides[iside]; + for (size_t inode = 0; inode < module_cb.get_num_ipin_nodes(cb_ipin_side); + ++inode) { + /* Collect source-related information */ + RRNodeId module_ipin_node = module_cb.get_ipin_node(cb_ipin_side, inode); + vtr::Point cb_src_port_coord( + rr_graph.node_xlow(module_ipin_node), + rr_graph.node_ylow(module_ipin_node)); + std::string src_cb_port_name = generate_cb_module_grid_port_name( + cb_ipin_side, grids, vpr_device_annotation, rr_graph, module_ipin_node); + ModulePortId src_cb_port_id = + module_manager.find_module_port(src_cb_module, src_cb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(src_cb_module, + src_cb_port_id)); + BasicPort src_cb_port = + module_manager.module_port(src_cb_module, src_cb_port_id); + + /* Collect sink-related information */ + /* Note that we use the instance cb pin here!!! + * because it has the correct coordinator for the grid!!! + */ + RRNodeId instance_ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode); + vtr::Point grid_coordinate( + rr_graph.node_xlow(instance_ipin_node), + rr_graph.node_ylow(instance_ipin_node)); + std::string sink_grid_module_name = + generate_grid_block_module_name_in_top_module( + std::string(GRID_MODULE_NAME_PREFIX), grids, grid_coordinate); + ModuleId sink_grid_module = + module_manager.find_module(sink_grid_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(sink_grid_module)); + size_t sink_grid_pin_index = rr_graph.node_pin_num(instance_ipin_node); + + t_physical_tile_type_ptr grid_type_descriptor = grids.get_physical_type( + t_physical_tile_loc(grid_coordinate.x(), grid_coordinate.y(), layer)); + size_t sink_grid_pin_width = + grid_type_descriptor->pin_width_offset[sink_grid_pin_index]; + size_t sink_grid_pin_height = + grid_type_descriptor->pin_height_offset[sink_grid_pin_index]; + BasicPort sink_grid_pin_info = + vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, + sink_grid_pin_index); + VTR_ASSERT(true == sink_grid_pin_info.is_valid()); + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, sink_grid_pin_index); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); + std::string sink_grid_port_name = generate_grid_port_name( + sink_grid_pin_width, sink_grid_pin_height, subtile_index, + get_rr_graph_single_node_side( + rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, inode)), + sink_grid_pin_info); + ModulePortId sink_grid_port_id = + module_manager.find_module_port(sink_grid_module, sink_grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + sink_grid_module, sink_grid_port_id)); + BasicPort sink_grid_port = + module_manager.module_port(sink_grid_module, sink_grid_port_id); + + /* Check if the grid is inside the tile, if not, create ports */ + if (fabric_tile.pb_in_tile(fabric_tile_id, grid_coordinate)) { + if (!frame_view) { + size_t sink_grid_instance = + pb_instances[fabric_tile.find_pb_index_in_tile(fabric_tile_id, + grid_coordinate)]; + + /* Source and sink port should match in size */ + VTR_ASSERT(src_cb_port.get_width() == sink_grid_port.get_width()); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < src_cb_port.pins().size(); + ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, src_cb_module, src_cb_instance, + src_cb_port_id, src_cb_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink( + tile_module, net, sink_grid_module, sink_grid_instance, + sink_grid_port_id, sink_grid_port.pins()[pin_id]); + } + } + } else { + /* Create a port on the tile module and create the net if required. + * FIXME: Create a proper name to avoid naming conflicts */ + const RRGSB& cb_inst_rr_gsb = device_rr_gsb.get_gsb( + fabric_tile.cb_coordinates(fabric_tile_id, cb_type)[icb]); + std::string cb_instance_name_in_tile = + generate_connection_block_module_name( + cb_type, cb_inst_rr_gsb.get_cb_coordinate(cb_type)); + src_cb_port.set_name(generate_tile_module_port_name( + cb_instance_name_in_tile, src_cb_port.get_name())); + ModulePortId sink_tile_port_id = module_manager.add_port( + tile_module, src_cb_port, + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT); + VTR_LOGV(verbose, + "Adding ports '%s' to tile as required by the connection " + "block '%s'...\n", + src_cb_port.to_verilog_string().c_str(), + src_cb_module_name.c_str()); + if (!frame_view) { + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < src_cb_port.pins().size(); + ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, src_cb_module, src_cb_instance, + src_cb_port_id, src_cb_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink(tile_module, net, tile_module, 0, + sink_tile_port_id, + src_cb_port.pins()[pin_id]); + } + } + } + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * This function will create nets for the connections + * between connection block and switch block pins + * Two cases should be considered: + * a. The switch block pin denotes an input of a routing track + * The net source is an output of a routing track of connection block + * while the net sink is an input of a routing track of switch block + * b. The switch block pin denotes an output of a routing track + * The net source is an output of routing track of switch block + * while the net sink is an input of a routing track of connection block + * + * +------------+ +------------------+ +------------+ + * | | | | | | + * | Grid | | Connection Block | | Grid | + * | [x][y+1] | | Y-direction | | [x+1][y+1] | + * | | | [x][y+1] | | | + * +------------+ +------------------+ +------------+ + * | ^ + * v | + * +------------+ +------------------+ +------------+ + * | Connection |----->| |----->| Connection | + * | Block | | Switch Block | | Block | + * | X-direction|<-----| [x][y] |<-----| X-direction| + * | [x][y] | | | | [x+1][y] | + * +------------+ +------------------+ +------------+ + * | ^ + * v | + * +------------+ +------------------+ +------------+ + * | | | | | | + * | Grid | | Connection Block | | Grid | + * | [x][y] | | Y-direction | | [x][y+1] | + * | | | [x][y] | | | + * +------------+ +------------------+ +------------+ + * + * Here, to achieve the purpose, we can simply iterate over the + * four sides of switch block and make connections to adjancent + * connection blocks + * + *******************************************************************/ +static int build_tile_module_port_and_nets_between_sb_and_cb( + ModuleManager& module_manager, const ModuleId& tile_module, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph, + const RRGSB& rr_gsb, const FabricTile& fabric_tile, + const FabricTileId& fabric_tile_id, + const std::map>& cb_instances, + const std::vector& sb_instances, const size_t& isb, + const bool& compact_routing_hierarchy, const bool& frame_view, + const bool& verbose) { + size_t sb_instance = sb_instances[isb]; + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), + rr_gsb.get_sb_y()); + vtr::Point module_gsb_sb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); + + /* Skip those Switch blocks that do not exist */ + if (false == rr_gsb.is_sb_exist(rr_graph)) { + return CMD_EXEC_SUCCESS; + } + + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ + if (true == compact_routing_hierarchy) { + vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); + const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord); + module_gsb_sb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_sb_coordinate.set_y(unique_mirror.get_y()); + } + + /* This is the source cb that is added to the top module */ + const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_sb_coordinate); + vtr::Point module_sb_coordinate(module_sb.get_sb_x(), + module_sb.get_sb_y()); + std::string sb_module_name = + generate_switch_block_module_name(module_sb_coordinate); + ModuleId sb_module_id = module_manager.find_module(sb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(sb_module_id)); + + /* Connect grid output pins (OPIN) to switch block grid pins */ + for (size_t side = 0; side < module_sb.get_num_sides(); ++side) { + SideManager side_manager(side); + /* Iterate over the routing tracks on this side */ + /* Early skip: if there is no routing tracks at this side */ + if (0 == module_sb.get_chan_width(side_manager.get_side())) { + continue; + } + /* Find the Connection Block module */ + /* We find the original connection block and then spot its unique mirror! + * Do NOT use module_sb here!!! + */ + t_rr_type cb_type = + find_top_module_cb_type_by_sb_side(side_manager.get_side()); + vtr::Point instance_gsb_cb_coordinate = + find_top_module_gsb_coordinate_by_sb_side(rr_gsb, + side_manager.get_side()); + vtr::Point module_gsb_cb_coordinate = + find_top_module_gsb_coordinate_by_sb_side(rr_gsb, + side_manager.get_side()); + + /* Skip those Connection blocks that do not exist: + * 1. The CB does not exist in the device level! We should skip! + * 2. The CB does exist but we need to make sure if the GSB includes such + * CBs For TOP and LEFT side, check the existence using RRGSB method + * is_cb_exist() FOr RIGHT and BOTTOM side, find the adjacent RRGSB and then + * use is_cb_exist() + */ + if (TOP == side_manager.get_side() || LEFT == side_manager.get_side()) { + if (false == rr_gsb.is_cb_exist(cb_type)) { + continue; + } + } + + if (RIGHT == side_manager.get_side() || BOTTOM == side_manager.get_side()) { + const RRGSB& adjacent_gsb = + device_rr_gsb.get_gsb(module_gsb_cb_coordinate); + if (false == adjacent_gsb.is_cb_exist(cb_type)) { + continue; + } + } + + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ + if (true == compact_routing_hierarchy) { + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, module_gsb_cb_coordinate); + module_gsb_cb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_cb_coordinate.set_y(unique_mirror.get_y()); + } + + const RRGSB& module_cb = device_rr_gsb.get_gsb(module_gsb_cb_coordinate); + vtr::Point module_cb_coordinate(module_cb.get_cb_x(cb_type), + module_cb.get_cb_y(cb_type)); + std::string cb_module_name = + generate_connection_block_module_name(cb_type, module_cb_coordinate); + ModuleId cb_module_id = module_manager.find_module(cb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(cb_module_id)); + const RRGSB& instance_cb = + device_rr_gsb.get_gsb(instance_gsb_cb_coordinate); + vtr::Point instance_cb_coordinate(instance_cb.get_cb_x(cb_type), + instance_cb.get_cb_y(cb_type)); + + /* Check if the grid is inside the tile, if not, create ports */ + if (fabric_tile.cb_in_tile(fabric_tile_id, cb_type, + instance_gsb_cb_coordinate)) { + VTR_LOGV( + verbose, + "Skip adding ports to tile as connection block '%s' is part of the " + "tile along with the switch block '%s'...\n", + generate_connection_block_module_name(cb_type, instance_cb_coordinate) + .c_str(), + sb_module_name.c_str()); + if (!frame_view) { + size_t cb_instance = + cb_instances.at(cb_type)[fabric_tile.find_cb_index_in_tile( + fabric_tile_id, cb_type, instance_gsb_cb_coordinate)]; + + for (size_t itrack = 0; + itrack < module_sb.get_chan_width(side_manager.get_side()); + ++itrack) { + std::string sb_port_name = generate_sb_module_track_port_name( + rr_graph.node_type( + module_sb.get_chan_node(side_manager.get_side(), itrack)), + side_manager.get_side(), + module_sb.get_chan_node_direction(side_manager.get_side(), itrack)); + /* Prepare SB-related port information */ + ModulePortId sb_port_id = + module_manager.find_module_port(sb_module_id, sb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(sb_module_id, + sb_port_id)); + BasicPort sb_port = + module_manager.module_port(sb_module_id, sb_port_id); + + /* Prepare CB-related port information */ + PORTS cb_port_direction = OUT_PORT; + /* The cb port direction should be opposite to the sb port !!! */ + if (OUT_PORT == module_sb.get_chan_node_direction( + side_manager.get_side(), itrack)) { + cb_port_direction = IN_PORT; + } else { + VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction( + side_manager.get_side(), itrack)); + } + + /* Upper CB port is required if the routing tracks are on the top or + * right sides of the switch block, which indicated bottom and left + * sides of the connection blocks + */ + bool use_cb_upper_port = (TOP == side_manager.get_side()) || + (RIGHT == side_manager.get_side()); + std::string cb_port_name = generate_cb_module_track_port_name( + cb_type, cb_port_direction, use_cb_upper_port); + ModulePortId cb_port_id = + module_manager.find_module_port(cb_module_id, cb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(cb_module_id, + cb_port_id)); + BasicPort cb_port = + module_manager.module_port(cb_module_id, cb_port_id); + + /* Configure the net source and sink: + * If sb port is an output (source), cb port is an input (sink) + * If sb port is an input (sink), cb port is an output (source) + */ + if (OUT_PORT == module_sb.get_chan_node_direction( + side_manager.get_side(), itrack)) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, sb_module_id, sb_instance, + sb_port_id, itrack / 2); + module_manager.add_module_net_sink(tile_module, net, cb_module_id, + cb_instance, cb_port_id, + itrack / 2); + } else { + VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction( + side_manager.get_side(), itrack)); + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, cb_module_id, cb_instance, + cb_port_id, itrack / 2); + module_manager.add_module_net_sink(tile_module, net, sb_module_id, + sb_instance, sb_port_id, + itrack / 2); + } + } + } + } else { + /* Create input and output ports */ + std::string chan_input_port_name = generate_sb_module_track_port_name( + cb_type, side_manager.get_side(), IN_PORT); + /* Create a port on the tile module and create the net if required. FIXME: + * Create a proper name to avoid naming conflicts */ + ModulePortId sb_chan_input_port_id = + module_manager.find_module_port(sb_module_id, chan_input_port_name); + BasicPort chan_input_port = + module_manager.module_port(sb_module_id, sb_chan_input_port_id); + chan_input_port.set_name(generate_tile_module_port_name( + generate_switch_block_module_name( + fabric_tile.sb_coordinates(fabric_tile_id)[isb]), + chan_input_port.get_name())); + ModulePortId tile_chan_input_port_id = module_manager.add_port( + tile_module, chan_input_port, + ModuleManager::e_module_port_type::MODULE_INPUT_PORT); + VTR_LOGV( + verbose, + "Adding ports '%s' to tile as required by the switch block '%s'...\n", + chan_input_port.to_verilog_string().c_str(), sb_module_name.c_str()); + /* Create a net for each pin */ + if (!frame_view) { + for (size_t pin_id = 0; pin_id < chan_input_port.pins().size(); + ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, tile_module, 0, + tile_chan_input_port_id, chan_input_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink(tile_module, net, sb_module_id, + sb_instance, sb_chan_input_port_id, + chan_input_port.pins()[pin_id]); + } + } + + std::string chan_output_port_name = generate_sb_module_track_port_name( + cb_type, side_manager.get_side(), OUT_PORT); + /* Create a port on the tile module and create the net if required. FIXME: + * Create a proper name to avoid naming conflicts */ + ModulePortId sb_chan_output_port_id = + module_manager.find_module_port(sb_module_id, chan_output_port_name); + BasicPort chan_output_port = + module_manager.module_port(sb_module_id, sb_chan_output_port_id); + chan_output_port.set_name(generate_tile_module_port_name( + generate_switch_block_module_name( + fabric_tile.sb_coordinates(fabric_tile_id)[isb]), + chan_output_port.get_name())); + ModulePortId tile_chan_output_port_id = module_manager.add_port( + tile_module, chan_output_port, + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT); + VTR_LOGV( + verbose, + "Adding ports '%s' to tile as required by the switch block '%s'...\n", + chan_output_port.to_verilog_string().c_str(), sb_module_name.c_str()); + /* Create a net for each pin */ + if (!frame_view) { + for (size_t pin_id = 0; pin_id < chan_output_port.pins().size(); + ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, sb_module_id, sb_instance, + sb_chan_output_port_id, chan_output_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink(tile_module, net, tile_module, 0, + tile_chan_output_port_id, + chan_output_port.pins()[pin_id]); + } + } + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * This function will a port for tile where its connection blocks + * need to drive or to be driven by a switch block which is not in the tile + * + * +------------+ +------------------+ + * | Connection | | | + * | Block |----->| Switch Block | + * | X-direction|<-----| [x][y] | + * | [x][y] | | | + * +------------+ +------------------+ + * + *******************************************************************/ +static int build_tile_module_one_port_from_cb( + ModuleManager& module_manager, const ModuleId& tile_module, + const ModuleId& cb_module, const std::string& chan_port_name, + const vtr::Point& tile_coord, + const std::string& cb_instance_name_in_tile, const size_t& cb_instance, + const bool& frame_view, const bool& verbose) { + std::string cb_module_name = module_manager.module_name(cb_module); + ModulePortId chan_port_id = + module_manager.find_module_port(cb_module, chan_port_name); + BasicPort chan_port = module_manager.module_port(cb_module, chan_port_id); + ModuleManager::e_module_port_type chan_port_type = + module_manager.port_type(cb_module, chan_port_id); + + bool require_port_addition = false; + for (size_t pin_id = 0; pin_id < chan_port.pins().size(); ++pin_id) { + if (module_manager.valid_module_net_id( + tile_module, module_manager.module_instance_port_net( + tile_module, cb_module, cb_instance, chan_port_id, + chan_port.pins()[pin_id]))) { + continue; + } + require_port_addition = true; + break; + } + + /* Early exit if this port is fully connected inside the tile */ + if (!require_port_addition) { + return CMD_EXEC_SUCCESS; + } + + BasicPort tile_chan_port(chan_port); + tile_chan_port.set_name(generate_tile_module_port_name( + cb_instance_name_in_tile, chan_port.get_name())); + + /* Add new port */ + VTR_LOGV(verbose, + "Adding ports '%s' to tile as required by the " + "connection block '%s'...\n", + tile_chan_port.to_verilog_string().c_str(), cb_module_name.c_str()); + /* Create a new port and a new net. FIXME: Create a proper name to + * avoid naming conflicts */ + ModulePortId tile_module_port_id = + module_manager.add_port(tile_module, tile_chan_port, chan_port_type); + + if (!frame_view) { + for (size_t pin_id = 0; pin_id < chan_port.pins().size(); ++pin_id) { + if (module_manager.valid_module_net_id( + tile_module, module_manager.module_instance_port_net( + tile_module, cb_module, cb_instance, chan_port_id, + chan_port.pins()[pin_id]))) { + continue; + } + if (chan_port_type == + ModuleManager::e_module_port_type::MODULE_INPUT_PORT) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, tile_module, 0, tile_module_port_id, + chan_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink(tile_module, net, cb_module, + cb_instance, chan_port_id, + chan_port.pins()[pin_id]); + } else if (chan_port_type == + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, cb_module, cb_instance, chan_port_id, + chan_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink(tile_module, net, tile_module, 0, + tile_module_port_id, + chan_port.pins()[pin_id]); + } else { + VTR_LOG_ERROR( + "Expect either input or output port '%s' for cb module '%s' " + "required by tile[%lu][%lu]!\n", + chan_port.to_verilog_string().c_str(), cb_module_name.c_str(), + tile_coord.x(), tile_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * This function will create ports for tile where its connection blocks + * need to drive or to be driven by a switch block which is not in the tile + * + * +------------+ +------------------+ + * | Connection | | | + * | Block |----->| Switch Block | + * | X-direction|<-----| [x][y] | + * | [x][y] | | | + * +------------+ +------------------+ + * + *******************************************************************/ +static int build_tile_module_ports_from_cb( + ModuleManager& module_manager, const ModuleId& tile_module, + const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, + const FabricTile& fabric_tile, const FabricTileId& curr_fabric_tile_id, + const t_rr_type& cb_type, + const std::map>& cb_instances, + const size_t& icb, const bool& compact_routing_hierarchy, + const bool& frame_view, const bool& verbose) { + int status = CMD_EXEC_SUCCESS; + + size_t cb_instance = cb_instances.at(cb_type)[icb]; + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_cb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + vtr::Point module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); + + /* Skip those Connection blocks that do not exist */ + if (false == rr_gsb.is_cb_exist(cb_type)) { + return CMD_EXEC_SUCCESS; + } + + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ + if (true == compact_routing_hierarchy) { + vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, gsb_coord); + module_gsb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_coordinate.set_y(unique_mirror.get_y()); + } + + /* This is the source cb that is added to the top module */ + const RRGSB& module_cb = device_rr_gsb.get_gsb(module_gsb_coordinate); + vtr::Point module_cb_coordinate(module_cb.get_cb_x(cb_type), + module_cb.get_cb_y(cb_type)); + + /* Collect source-related information */ + std::string cb_module_name = + generate_connection_block_module_name(cb_type, module_cb_coordinate); + ModuleId cb_module = module_manager.find_module(cb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); + + /* Find the instance name for the connection block in the context of the tile + */ + vtr::Point cb_coord_in_unique_tile = + fabric_tile.cb_coordinates(curr_fabric_tile_id, cb_type)[icb]; + const RRGSB& unique_rr_gsb = device_rr_gsb.get_gsb(cb_coord_in_unique_tile); + std::string cb_instance_name_in_tile = generate_connection_block_module_name( + cb_type, unique_rr_gsb.get_cb_coordinate(cb_type)); + vtr::Point tile_coord = + fabric_tile.tile_coordinate(curr_fabric_tile_id); + + /* Check any track input and output are unconnected in the tile */ + /* Upper input port: W/2 == 0 tracks */ + std::string chan_upper_input_port_name = + generate_cb_module_track_port_name(cb_type, IN_PORT, true); + + /* Check if any of the input port is driven, if not add new port */ + status = build_tile_module_one_port_from_cb( + module_manager, tile_module, cb_module, chan_upper_input_port_name, + tile_coord, cb_instance_name_in_tile, cb_instance, frame_view, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Lower input port: W/2 == 1 tracks */ + std::string chan_lower_input_port_name = + generate_cb_module_track_port_name(cb_type, IN_PORT, false); + + /* Check if any of the input port is driven, if not add new port */ + status = build_tile_module_one_port_from_cb( + module_manager, tile_module, cb_module, chan_lower_input_port_name, + tile_coord, cb_instance_name_in_tile, cb_instance, frame_view, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Upper output port: W/2 == 0 tracks */ + std::string chan_upper_output_port_name = + generate_cb_module_track_port_name(cb_type, OUT_PORT, true); + + /* Check if any of the input port is driven, if not add new port */ + status = build_tile_module_one_port_from_cb( + module_manager, tile_module, cb_module, chan_upper_output_port_name, + tile_coord, cb_instance_name_in_tile, cb_instance, frame_view, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Lower output port: W/2 == 1 tracks */ + std::string chan_lower_output_port_name = + generate_cb_module_track_port_name(cb_type, OUT_PORT, false); + + /* Check if any of the input port is driven, if not add new port */ + status = build_tile_module_one_port_from_cb( + module_manager, tile_module, cb_module, chan_lower_output_port_name, + tile_coord, cb_instance_name_in_tile, cb_instance, frame_view, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * This function will create nets for the unconnected pins for a programmable + *block in a tile This function should be called after the following functions: + * - build_tile_module_port_and_nets_between_sb_and_pb() + * - build_tile_module_port_and_nets_between_cb_and_pb() + * - build_tile_module_port_and_nets_between_sb_and_cb() + * The functions above build nets/connections between the current programmable + *block and other routing blocks. However, it could happen that the programmable + *block is the only submodule under the tile. Also, it could happen that the + *programmable block drives or is driven by other blocks from another tile. As a + *result, we should build the nets for these unconnected pins + * Note that direct connections, e.g., carry chain is not handled at tile-level. + *It will be handled in the top-level module, which should not case a negative + *impact on the physical design. + * + * +------------+ + * | |-->grid_xxx + * | Grid | + * | [x][y] |<--grid_xxx + * | | + * +------------+ + ********************************************************************/ +static int build_tile_port_and_nets_from_pb( + ModuleManager& module_manager, const ModuleId& tile_module, + const DeviceGrid& grids, const size_t& layer, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const vtr::Point& pb_coord, const std::vector& pb_instances, + const FabricTile& fabric_tile, const FabricTileId& curr_fabric_tile_id, + const size_t& ipb, const bool& frame_view, const bool& verbose) { + size_t pb_instance = pb_instances[ipb]; + t_physical_tile_type_ptr phy_tile = grids.get_physical_type( + t_physical_tile_loc(pb_coord.x(), pb_coord.y(), layer)); + /* Empty type does not require a module */ + if (is_empty_type(phy_tile)) { + return CMD_EXEC_SUCCESS; + } + e_side grid_side = find_grid_border_side( + vtr::Point(grids.width(), grids.height()), pb_coord); + std::string pb_module_name = generate_grid_block_module_name( + std::string(GRID_MODULE_NAME_PREFIX), std::string(phy_tile->name), + is_io_type(phy_tile), grid_side); + ModuleId pb_module = module_manager.find_module(pb_module_name); + if (!pb_module) { + VTR_LOG_ERROR("Failed to find pb module '%s' required by tile[%lu][%lu]!\n", + pb_module_name.c_str(), pb_coord.x(), pb_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + + /* Find the pin side for I/O grids*/ + std::vector grid_pin_sides; + /* For I/O grids, we care only one side + * Otherwise, we will iterate all the 4 sides + */ + if (true == is_io_type(phy_tile)) { + grid_pin_sides = find_grid_module_pin_sides(phy_tile, grid_side); + } else { + grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT}; + } + + /* Create a map between pin class type and grid pin direction */ + std::map pin_type2type_map; + pin_type2type_map[RECEIVER] = ModuleManager::MODULE_INPUT_PORT; + pin_type2type_map[DRIVER] = ModuleManager::MODULE_OUTPUT_PORT; + + /* Iterate over sides, height and pins */ + for (const e_side& side : grid_pin_sides) { + for (int iwidth = 0; iwidth < phy_tile->width; ++iwidth) { + for (int iheight = 0; iheight < phy_tile->height; ++iheight) { + for (int ipin = 0; ipin < phy_tile->num_pins; ++ipin) { + if (!phy_tile->pinloc[iwidth][iheight][side][ipin]) { + continue; + } + /* Reach here, it means this pin is on this side */ + /* Generate the pin name, + * we give a empty coordinate but it will not be used (see details in + * the function + */ + BasicPort pin_info = + vpr_device_annotation.physical_tile_pin_port_info(phy_tile, ipin); + VTR_ASSERT(true == pin_info.is_valid()); + int subtile_index = + vpr_device_annotation.physical_tile_pin_subtile_index(phy_tile, + ipin); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < phy_tile->capacity); + std::string port_name = generate_grid_port_name( + iwidth, iheight, subtile_index, side, pin_info); + BasicPort pb_port(port_name, 0, 0); + ModulePortId pb_module_port_id = + module_manager.find_module_port(pb_module, port_name); + if (!module_manager.valid_module_port_id(pb_module, + pb_module_port_id)) { + VTR_LOG_ERROR( + "Failed to find port '%s' for pb module '%s' required by " + "tile[%lu][%lu]!\n", + pb_port.to_verilog_string().c_str(), pb_module_name.c_str(), + pb_coord.x(), pb_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + /* Create a proper name to avoid naming conflicts */ + std::string pb_instance_name_in_tile = + generate_grid_block_module_name_in_top_module( + std::string(GRID_MODULE_NAME_PREFIX), grids, + fabric_tile.pb_coordinates(curr_fabric_tile_id)[ipb]); + pb_port.set_name(generate_tile_module_port_name( + pb_instance_name_in_tile, pb_port.get_name())); + + /* Find the port from the pb module and see if it is already been + * driven or driving a net. if not, create a new port at the tile + * module */ + if (module_manager.port_type(pb_module, pb_module_port_id) == + ModuleManager::e_module_port_type::MODULE_INPUT_PORT) { + for (size_t pin_id = 0; pin_id < pb_port.pins().size(); ++pin_id) { + if (module_manager.valid_module_net_id( + tile_module, + module_manager.module_instance_port_net( + tile_module, pb_module, pb_instance, pb_module_port_id, + pb_port.pins()[pin_id]))) { + continue; + } + VTR_LOGV(verbose, + "Adding ports '%s' to tile as required by the " + "programmable block '%s'...\n", + pb_port.to_verilog_string().c_str(), + pb_module_name.c_str()); + /* Create a new port and a new net. */ + ModulePortId tile_module_port_id = module_manager.add_port( + tile_module, pb_port, + ModuleManager::e_module_port_type::MODULE_INPUT_PORT); + if (!frame_view) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, tile_module, 0, + tile_module_port_id, pb_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink( + tile_module, net, pb_module, pb_instance, pb_module_port_id, + pb_port.pins()[pin_id]); + } + } + } else if (module_manager.port_type(pb_module, pb_module_port_id) == + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT) { + /* Note that an output may drive multiple blocks, therefore, we + * cannot just check if there is a net driven by this pin, need to + * check the fannout of the net!!! */ + for (size_t pin_id = 0; pin_id < pb_port.pins().size(); ++pin_id) { + ModuleNetId curr_net = module_manager.module_instance_port_net( + tile_module, pb_module, pb_instance, pb_module_port_id, + pb_port.pins()[pin_id]); + bool require_port_addition = true; + if (module_manager.valid_module_net_id(tile_module, curr_net)) { + size_t num_fanout_in_tile = + module_manager.module_net_sinks(tile_module, curr_net).size(); + RRNodeId rr_node = rr_graph.node_lookup().find_node( + layer, pb_coord.x() + iwidth, pb_coord.y() + iheight, OPIN, + ipin, side); + size_t num_fanout_required = + rr_graph.node_out_edges(rr_node).size(); + if (num_fanout_in_tile == num_fanout_required) { + require_port_addition = false; + } + } + if (!require_port_addition) { + continue; + } + VTR_LOGV(verbose, + "Adding ports '%s' to tile as required by the " + "programmable block '%s'...\n", + pb_port.to_verilog_string().c_str(), + pb_module_name.c_str()); + /* Create a new port and a new net. FIXME: Create a proper name to + * avoid naming conflicts */ + ModulePortId tile_module_port_id = module_manager.add_port( + tile_module, pb_port, + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT); + if (!frame_view) { + ModuleNetId net = create_module_source_pin_net( + module_manager, tile_module, pb_module, pb_instance, + pb_module_port_id, pb_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink( + tile_module, net, tile_module, 0, tile_module_port_id, + pb_port.pins()[pin_id]); + } + } + } else { + VTR_LOG_ERROR( + "Expect either input or output port '%s' for pb module '%s' " + "required by tile[%lu][%lu]!\n", + pb_port.to_verilog_string().c_str(), pb_module_name.c_str(), + pb_coord.x(), pb_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + } + } + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Build the ports and associated nets for a tile module + * For each submodule, e.g., programmable block, connection block and switch + *blocks, we walk through their neighbours, starting from sb, cb and then + *programmable blocks. + * - If a neighbour is one of the submodules under this tile, we can build nets + *between the submodule and its neighbour. + * - If the neighbour is not under this tile, we should build ports for the tile + *module and then build nets to connect Note that if frame_view is enabled, nets + *are not built + *******************************************************************/ +static int build_tile_module_ports_and_nets( + ModuleManager& module_manager, const ModuleId& tile_module, + const DeviceGrid& grids, const size_t& layer, + const VprDeviceAnnotation& vpr_device_annotation, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph_view, + const FabricTile& fabric_tile, const FabricTileId& fabric_tile_id, + const std::vector& pb_instances, + const std::map>& cb_instances, + const std::vector& sb_instances, const bool& frame_view, + const bool& verbose) { + int status_code = CMD_EXEC_SUCCESS; + + /* Get the submodule of Switch blocks one by one, build connections between sb + * and pb */ + for (size_t isb = 0; isb < fabric_tile.sb_coordinates(fabric_tile_id).size(); + ++isb) { + vtr::Point sb_coord = + fabric_tile.sb_coordinates(fabric_tile_id)[isb]; + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(sb_coord); + status_code = build_tile_module_port_and_nets_between_sb_and_pb( + module_manager, tile_module, grids, layer, vpr_device_annotation, + device_rr_gsb, rr_graph_view, rr_gsb, fabric_tile, fabric_tile_id, + pb_instances, sb_instances, isb, true, frame_view, verbose); + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + /* Get the submodule of connection blocks one by one, build connections + * between cb and pb */ + for (t_rr_type cb_type : {CHANX, CHANY}) { + for (size_t icb = 0; + icb < fabric_tile.cb_coordinates(fabric_tile_id, cb_type).size(); + ++icb) { + vtr::Point cb_coord = + fabric_tile.cb_coordinates(fabric_tile_id, cb_type)[icb]; + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(cb_coord); + status_code = build_tile_module_port_and_nets_between_cb_and_pb( + module_manager, tile_module, grids, layer, vpr_device_annotation, + device_rr_gsb, rr_graph_view, rr_gsb, fabric_tile, fabric_tile_id, + cb_type, pb_instances, cb_instances, icb, true, frame_view, verbose); + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + } + + /* Get the submodule of connection blocks one by one, build connections + * between sb and cb */ + for (size_t isb = 0; isb < fabric_tile.sb_coordinates(fabric_tile_id).size(); + ++isb) { + vtr::Point sb_coord = + fabric_tile.sb_coordinates(fabric_tile_id)[isb]; + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(sb_coord); + status_code = build_tile_module_port_and_nets_between_sb_and_cb( + module_manager, tile_module, device_rr_gsb, rr_graph_view, rr_gsb, + fabric_tile, fabric_tile_id, cb_instances, sb_instances, isb, true, + frame_view, verbose); + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + /* Create the ports from pb which only connects to adjacent sb and cbs, as + * well as pb */ + for (size_t ipb = 0; ipb < fabric_tile.pb_coordinates(fabric_tile_id).size(); + ++ipb) { + vtr::Point pb_coord = + fabric_tile.pb_coordinates(fabric_tile_id)[ipb]; + status_code = build_tile_port_and_nets_from_pb( + module_manager, tile_module, grids, layer, vpr_device_annotation, + rr_graph_view, pb_coord, pb_instances, fabric_tile, fabric_tile_id, ipb, + frame_view, verbose); + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + /* Get the submodule of connection blocks one by one, build connections + * between cb and pb */ + for (t_rr_type cb_type : {CHANX, CHANY}) { + for (size_t icb = 0; + icb < fabric_tile.cb_coordinates(fabric_tile_id, cb_type).size(); + ++icb) { + vtr::Point cb_coord = + fabric_tile.cb_coordinates(fabric_tile_id, cb_type)[icb]; + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(cb_coord); + + /* Build any ports missing from connection blocks */ + status_code = build_tile_module_ports_from_cb( + module_manager, tile_module, device_rr_gsb, rr_gsb, fabric_tile, + fabric_tile_id, cb_type, cb_instances, icb, true, frame_view, verbose); + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + } + + return status_code; +} + +/******************************************************************** + * Build a tile module + * - Add instances + * - Add ports and nets + * - Add global ports + * - Add I/O ports + * - Add configuration ports and nets + *******************************************************************/ +static int build_tile_module( + ModuleManager& module_manager, DecoderLibrary& decoder_lib, + const FabricTile& fabric_tile, const FabricTileId& fabric_tile_id, + const DeviceGrid& grids, const size_t& layer, + const VprDeviceAnnotation& vpr_device_annotation, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph_view, + const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, const bool& frame_view, + const bool& verbose) { + int status_code = CMD_EXEC_SUCCESS; + + /* Create the module */ + vtr::Point tile_coord = fabric_tile.tile_coordinate(fabric_tile_id); + std::string module_name = generate_tile_module_name(tile_coord); + VTR_LOGV(verbose, "Building tile module '%s'...\n", module_name.c_str()); + ModuleId tile_module = module_manager.add_module(module_name); + + /* Add instance of programmable block */ + std::vector + pb_instances; /* Keep tracking the instance id of each pb */ + for (vtr::Point grid_coord : + fabric_tile.pb_coordinates(fabric_tile_id)) { + t_physical_tile_type_ptr phy_tile = grids.get_physical_type( + t_physical_tile_loc(grid_coord.x(), grid_coord.y(), layer)); + VTR_LOGV(verbose, "Try to find pb at [%lu][%lu]\n", grid_coord.x(), + grid_coord.y()); + /* Empty type does not require a module */ + if (!is_empty_type(phy_tile)) { + e_side grid_side = find_grid_border_side( + vtr::Point(grids.width(), grids.height()), grid_coord); + std::string pb_module_name = generate_grid_block_module_name( + std::string(GRID_MODULE_NAME_PREFIX), std::string(phy_tile->name), + is_io_type(phy_tile), grid_side); + ModuleId pb_module = module_manager.find_module(pb_module_name); + if (!pb_module) { + VTR_LOG_ERROR( + "Failed to find pb module '%s' required by tile[%lu][%lu]!\n", + pb_module_name.c_str(), tile_coord.x(), tile_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + size_t pb_instance = module_manager.num_instance(tile_module, pb_module); + module_manager.add_child_module(tile_module, pb_module, false); + std::string pb_instance_name = generate_grid_block_instance_name( + std::string(GRID_MODULE_NAME_PREFIX), std::string(phy_tile->name), + is_io_type(phy_tile), grid_side, grid_coord); + module_manager.set_child_instance_name(tile_module, pb_module, + pb_instance, pb_instance_name); + if (0 < find_module_num_config_bits(module_manager, pb_module, + circuit_lib, sram_model, + sram_orgz_type)) { + module_manager.add_configurable_child( + tile_module, pb_module, pb_instance, + ModuleManager::e_config_child_type::UNIFIED); + } + VTR_LOGV( + verbose, + "Added programmable module '%s' (instance: '%s') to tile[%lu][%lu]\n", + pb_module_name.c_str(), pb_instance_name.c_str(), tile_coord.x(), + tile_coord.y()); + pb_instances.push_back(pb_instance); + /* Add a custom I/O child with the grid */ + module_manager.add_io_child( + tile_module, pb_module, pb_instance, + vtr::Point(grid_coord.x(), grid_coord.y())); + } + } + + /* Add instance of connection blocks */ + std::map> + cb_instances; /* Keep tracking the instance id of each cb */ + for (t_rr_type cb_type : {CHANX, CHANY}) { + for (vtr::Point cb_coord : + fabric_tile.cb_coordinates(fabric_tile_id, cb_type)) { + /* get the unique module coord */ + const RRGSB& unique_rr_gsb = + device_rr_gsb.get_cb_unique_module(cb_type, cb_coord); + vtr::Point unique_cb_coord(unique_rr_gsb.get_cb_x(cb_type), + unique_rr_gsb.get_cb_y(cb_type)); + std::string cb_module_name = + generate_connection_block_module_name(cb_type, unique_cb_coord); + ModuleId cb_module = module_manager.find_module(cb_module_name); + if (!cb_module) { + VTR_LOG_ERROR( + "Failed to find connection block module '%s' required by " + "tile[%lu][%lu]!\n", + cb_module_name.c_str(), tile_coord.x(), tile_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + size_t cb_instance = module_manager.num_instance(tile_module, cb_module); + module_manager.add_child_module(tile_module, cb_module, false); + const RRGSB& inst_rr_gsb = device_rr_gsb.get_gsb(cb_coord); + std::string cb_instance_name = generate_connection_block_module_name( + cb_type, inst_rr_gsb.get_cb_coordinate(cb_type)); + module_manager.set_child_instance_name(tile_module, cb_module, + cb_instance, cb_instance_name); + if (0 < find_module_num_config_bits(module_manager, cb_module, + circuit_lib, sram_model, + sram_orgz_type)) { + module_manager.add_configurable_child( + tile_module, cb_module, cb_instance, + ModuleManager::e_config_child_type::UNIFIED); + } + VTR_LOGV(verbose, + "Added connection block module '%s' (instance: '%s') to " + "tile[%lu][%lu]\n", + cb_module_name.c_str(), cb_instance_name.c_str(), tile_coord.x(), + tile_coord.y()); + cb_instances[cb_type].push_back(cb_instance); + } + } + + /* Add instance of switch blocks */ + std::vector + sb_instances; /* Keep tracking the instance id of each sb */ + for (vtr::Point sb_coord : + fabric_tile.sb_coordinates(fabric_tile_id)) { + /* get the unique module coord */ + const RRGSB& unique_rr_gsb = device_rr_gsb.get_sb_unique_module(sb_coord); + vtr::Point unique_sb_coord(unique_rr_gsb.get_sb_x(), + unique_rr_gsb.get_sb_y()); + std::string sb_module_name = + generate_switch_block_module_name(unique_sb_coord); + ModuleId sb_module = module_manager.find_module(sb_module_name); + if (!sb_module) { + VTR_LOG_ERROR( + "Failed to find switch block module '%s' required by tile[%lu][%lu]!\n", + sb_module_name.c_str(), tile_coord.x(), tile_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + size_t sb_instance = module_manager.num_instance(tile_module, sb_module); + module_manager.add_child_module(tile_module, sb_module, false); + const RRGSB& inst_rr_gsb = device_rr_gsb.get_gsb(sb_coord); + std::string sb_instance_name = + generate_switch_block_module_name(inst_rr_gsb.get_sb_coordinate()); + module_manager.set_child_instance_name(tile_module, sb_module, sb_instance, + sb_instance_name); + if (0 < find_module_num_config_bits(module_manager, sb_module, circuit_lib, + sram_model, sram_orgz_type)) { + module_manager.add_configurable_child( + tile_module, sb_module, sb_instance, + ModuleManager::e_config_child_type::UNIFIED); + } + VTR_LOGV( + verbose, + "Added switch block module '%s' (instance: %s') to tile[%lu][%lu]\n", + sb_module_name.c_str(), sb_instance_name.c_str(), tile_coord.x(), + tile_coord.y()); + sb_instances.push_back(sb_instance); + } + + /* Add module nets and ports */ + status_code = build_tile_module_ports_and_nets( + module_manager, tile_module, grids, layer, vpr_device_annotation, + device_rr_gsb, rr_graph_view, fabric_tile, fabric_tile_id, pb_instances, + cb_instances, sb_instances, frame_view, verbose); + + /* Add global ports to the pb_module: + * This is a much easier job after adding sub modules (instances), + * we just need to find all the global ports from the child modules and build + * a list of it + */ + add_module_global_ports_from_child_modules(module_manager, tile_module); + + /* Count GPIO ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it + */ + add_module_gpio_ports_from_child_modules(module_manager, tile_module); + + /* Count shared SRAM ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it + */ + size_t module_num_shared_config_bits = + find_module_num_shared_config_bits_from_child_modules(module_manager, + tile_module); + if (0 < module_num_shared_config_bits) { + add_reserved_sram_ports_to_module_manager(module_manager, tile_module, + module_num_shared_config_bits); + } + + /* Count SRAM ports from the sub-modules under this Verilog module + * This is a much easier job after adding sub modules (instances), + * we just need to find all the I/O ports from the child modules and build a + * list of it + */ + size_t module_num_config_bits = + find_module_num_config_bits_from_child_modules( + module_manager, tile_module, circuit_lib, sram_model, sram_orgz_type, + ModuleManager::e_config_child_type::LOGICAL); + if (0 < module_num_config_bits) { + add_pb_sram_ports_to_module_manager(module_manager, tile_module, + circuit_lib, sram_model, sram_orgz_type, + module_num_config_bits); + } + + /* Add module nets to connect memory cells inside + * This is a one-shot addition that covers all the memory modules in this pb + * module! + */ + if (0 < module_manager.num_configurable_children( + tile_module, ModuleManager::e_config_child_type::LOGICAL)) { + add_pb_module_nets_memory_config_bus( + module_manager, decoder_lib, tile_module, sram_orgz_type, + circuit_lib.design_tech_type(sram_model), + ModuleManager::e_config_child_type::LOGICAL); + } + + VTR_LOGV(verbose, "Done\n"); + return status_code; +} + +/******************************************************************** + * Build all the tile modules + *******************************************************************/ +int build_tile_modules(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const FabricTile& fabric_tile, const DeviceGrid& grids, + const VprDeviceAnnotation& vpr_device_annotation, + const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph_view, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, + const bool& frame_view, const bool& verbose) { + vtr::ScopedStartFinishTimer timer("Build tile modules for the FPGA fabric"); + + int status_code = CMD_EXEC_SUCCESS; + + size_t layer = 0; + + /* Build a module for each unique tile */ + for (FabricTileId fabric_tile_id : fabric_tile.unique_tiles()) { + status_code = build_tile_module( + module_manager, decoder_lib, fabric_tile, fabric_tile_id, grids, layer, + vpr_device_annotation, device_rr_gsb, rr_graph_view, circuit_lib, + sram_model, sram_orgz_type, frame_view, verbose); + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + + return status_code; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_tile_modules.h b/openfpga/src/fabric/build_tile_modules.h new file mode 100644 index 000000000..0513d9850 --- /dev/null +++ b/openfpga/src/fabric/build_tile_modules.h @@ -0,0 +1,40 @@ +#ifndef BUILD_TILE_MODULES_H +#define BUILD_TILE_MODULES_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ + +#include + +#include "circuit_library.h" +#include "config_protocol.h" +#include "decoder_library.h" +#include "device_grid.h" +#include "device_rr_gsb.h" +#include "fabric_tile.h" +#include "module_manager.h" +#include "rr_graph_view.h" +#include "vpr_device_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int build_tile_modules(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const FabricTile& fabric_tile, const DeviceGrid& grids, + const VprDeviceAnnotation& vpr_device_annotation, + const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph_view, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, + const bool& frame_view, const bool& verbose); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 3de1dc176..5d668f2f2 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -16,12 +16,15 @@ /* Headers from openfpgashell library */ #include "build_module_graph_utils.h" #include "build_top_module.h" +#include "build_top_module_child_fine_grained_instance.h" +#include "build_top_module_child_tile_instance.h" #include "build_top_module_connection.h" #include "build_top_module_directs.h" #include "build_top_module_memory.h" #include "build_top_module_memory_bank.h" #include "build_top_module_utils.h" #include "command_exit_codes.h" +#include "module_manager_memory_utils.h" #include "module_manager_utils.h" #include "openfpga_device_grid_utils.h" #include "openfpga_naming.h" @@ -31,392 +34,6 @@ /* begin namespace openfpga */ namespace openfpga { -/******************************************************************** - * Add a instance of a grid module to the top module - *******************************************************************/ -static size_t add_top_module_grid_instance( - ModuleManager& module_manager, const ModuleId& top_module, - t_physical_tile_type_ptr grid_type, const e_side& border_side, - const vtr::Point& grid_coord) { - /* Find the module name for this type of grid */ - std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_module_name = generate_grid_block_module_name( - grid_module_name_prefix, std::string(grid_type->name), - is_io_type(grid_type), border_side); - ModuleId grid_module = module_manager.find_module(grid_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - /* Record the instance id */ - size_t grid_instance = module_manager.num_instance(top_module, grid_module); - /* Add the module to top_module */ - module_manager.add_child_module(top_module, grid_module, false); - /* Set an unique name to the instance - * Note: it is your risk to gurantee the name is unique! - */ - std::string instance_name = generate_grid_block_instance_name( - grid_module_name_prefix, std::string(grid_type->name), - is_io_type(grid_type), border_side, grid_coord); - module_manager.set_child_instance_name(top_module, grid_module, grid_instance, - instance_name); - - return grid_instance; -} - -/******************************************************************** - * Add all the grids as sub-modules across the fabric - * The grid modules are created for each unique type of grid (based - * on the type in data structure data_structure - * Here, we will iterate over the full fabric (coordinates) - * and instanciate the grid modules - * - * Return an 2-D array of instance ids of the grid modules that - * have been added - * - * This function assumes an island-style floorplanning for FPGA fabric - * - * - * +-----------------------------------+ - * | I/O grids | - * | TOP side | - * +-----------------------------------+ - * - * +-----------+ +-----------------------------------+ +------------+ - * | | | | | | - * | I/O grids | | Core grids | | I/O grids | - * | LEFT side | | (CLB, Heterogeneous blocks, etc.) | | RIGHT side | - * | | | | | | - * +-----------+ +-----------------------------------+ +------------+ - * - * +-----------------------------------+ - * | I/O grids | - * | BOTTOM side | - * +-----------------------------------+ - * - *******************************************************************/ -static vtr::Matrix add_top_module_grid_instances( - ModuleManager& module_manager, const ModuleId& top_module, - const DeviceGrid& grids) { - vtr::ScopedStartFinishTimer timer("Add grid instances to top module"); - - /* Reserve an array for the instance ids */ - vtr::Matrix grid_instance_ids({grids.width(), grids.height()}); - grid_instance_ids.fill(size_t(-1)); - - /* Instanciate I/O grids */ - /* Create the coordinate range for each side of FPGA fabric */ - std::map>> io_coordinates = - generate_perimeter_grid_coordinates(grids); - - for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { - for (const vtr::Point& io_coordinate : io_coordinates[io_side]) { - /* Bypass EMPTY grid */ - if (true == - is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { - continue; - } - /* Skip width, height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) || - (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { - /* Find the root of this grid, the instance id should be valid. - * We just copy it here - */ - vtr::Point root_grid_coord( - io_coordinate.x() - - grids[io_coordinate.x()][io_coordinate.y()].width_offset, - io_coordinate.y() - - grids[io_coordinate.x()][io_coordinate.y()].height_offset); - VTR_ASSERT(size_t(-1) != - grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]); - grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = - grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]; - continue; - } - - /* Add a grid module to top_module*/ - grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = - add_top_module_grid_instance( - module_manager, top_module, - grids[io_coordinate.x()][io_coordinate.y()].type, io_side, - io_coordinate); - } - } - - /* Instanciate core grids - * IMPORTANT: sequence matters here, it impacts the I/O indexing. - * We should follow the same sequence as the build_io_location_map()! - * If you change the sequence of walking through grids here, you should change - * it in the build_io_location map()! - */ - for (size_t ix = 1; ix < grids.width() - 1; ++ix) { - for (size_t iy = 1; iy < grids.height() - 1; ++iy) { - /* Bypass EMPTY grid */ - if (true == is_empty_type(grids[ix][iy].type)) { - continue; - } - /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[ix][iy].width_offset) || - (0 < grids[ix][iy].height_offset)) { - /* Find the root of this grid, the instance id should be valid. - * We just copy it here - */ - vtr::Point root_grid_coord(ix - grids[ix][iy].width_offset, - iy - grids[ix][iy].height_offset); - VTR_ASSERT(size_t(-1) != - grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]); - grid_instance_ids[ix][iy] = - grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]; - continue; - } - /* Add a grid module to top_module*/ - vtr::Point grid_coord(ix, iy); - grid_instance_ids[ix][iy] = add_top_module_grid_instance( - module_manager, top_module, grids[ix][iy].type, NUM_SIDES, grid_coord); - } - } - - return grid_instance_ids; -} - -/******************************************************************** - * Add switch blocks across the FPGA fabric to the top-level module - * Return an 2-D array of instance ids of the switch blocks that - * have been added - *******************************************************************/ -static vtr::Matrix add_top_module_switch_block_instances( - ModuleManager& module_manager, const ModuleId& top_module, - const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy) { - vtr::ScopedStartFinishTimer timer("Add switch block instances to top module"); - - vtr::Point sb_range = device_rr_gsb.get_gsb_range(); - - /* Reserve an array for the instance ids */ - vtr::Matrix sb_instance_ids({sb_range.x(), sb_range.y()}); - sb_instance_ids.fill(size_t(-1)); - - for (size_t ix = 0; ix < sb_range.x(); ++ix) { - for (size_t iy = 0; iy < sb_range.y(); ++iy) { - /* If we use compact routing hierarchy, we should instanciate the unique - * module of SB */ - const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - - if (false == rr_gsb.is_sb_exist()) { - continue; - } - - vtr::Point sb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); - if (true == compact_routing_hierarchy) { - vtr::Point sb_coord(ix, iy); - const RRGSB& unique_mirror = - device_rr_gsb.get_sb_unique_module(sb_coord); - sb_coordinate.set_x(unique_mirror.get_sb_x()); - sb_coordinate.set_y(unique_mirror.get_sb_y()); - } - std::string sb_module_name = - generate_switch_block_module_name(sb_coordinate); - ModuleId sb_module = module_manager.find_module(sb_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); - /* Record the instance id */ - sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()] = - module_manager.num_instance(top_module, sb_module); - /* Add the module to top_module */ - module_manager.add_child_module(top_module, sb_module, false); - /* Set an unique name to the instance - * Note: it is your risk to gurantee the name is unique! - */ - module_manager.set_child_instance_name( - top_module, sb_module, - sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], - generate_switch_block_module_name( - vtr::Point(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()))); - } - } - - return sb_instance_ids; -} - -/******************************************************************** - * Add switch blocks across the FPGA fabric to the top-level module - *******************************************************************/ -static vtr::Matrix add_top_module_connection_block_instances( - ModuleManager& module_manager, const ModuleId& top_module, - const DeviceRRGSB& device_rr_gsb, const t_rr_type& cb_type, - const bool& compact_routing_hierarchy) { - vtr::ScopedStartFinishTimer timer( - "Add connection block instances to top module"); - - vtr::Point cb_range = device_rr_gsb.get_gsb_range(); - - /* Reserve an array for the instance ids */ - vtr::Matrix cb_instance_ids({cb_range.x(), cb_range.y()}); - cb_instance_ids.fill(size_t(-1)); - - for (size_t ix = 0; ix < cb_range.x(); ++ix) { - for (size_t iy = 0; iy < cb_range.y(); ++iy) { - /* Check if the connection block exists in the device! - * Some of them do NOT exist due to heterogeneous blocks (height > 1) - * We will skip those modules - */ - const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - vtr::Point cb_coordinate(rr_gsb.get_cb_x(cb_type), - rr_gsb.get_cb_y(cb_type)); - if (false == rr_gsb.is_cb_exist(cb_type)) { - continue; - } - /* If we use compact routing hierarchy, we should instanciate the unique - * module of SB */ - if (true == compact_routing_hierarchy) { - vtr::Point cb_coord(ix, iy); - /* Note: use GSB coordinate when inquire for unique modules!!! */ - const RRGSB& unique_mirror = - device_rr_gsb.get_cb_unique_module(cb_type, cb_coord); - cb_coordinate.set_x(unique_mirror.get_cb_x(cb_type)); - cb_coordinate.set_y(unique_mirror.get_cb_y(cb_type)); - } - std::string cb_module_name = - generate_connection_block_module_name(cb_type, cb_coordinate); - ModuleId cb_module = module_manager.find_module(cb_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); - /* Record the instance id */ - cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)] = - module_manager.num_instance(top_module, cb_module); - /* Add the module to top_module */ - module_manager.add_child_module(top_module, cb_module, false); - /* Set an unique name to the instance - * Note: it is your risk to gurantee the name is unique! - */ - std::string cb_instance_name = generate_connection_block_module_name( - cb_type, - vtr::Point(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type))); - module_manager.set_child_instance_name( - top_module, cb_module, - cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], - cb_instance_name); - } - } - - return cb_instance_ids; -} - -/******************************************************************** - * Add the I/O children to the top-level module, which impacts the I/O indexing - * This is the default function to build the I/O sequence/indexing - * The I/O children is added in a maze shape - * The function supports I/Os in the center of grids, starting from the - *bottom-left corner and ending at the center - * - * +----------------------+ - * |+--------------------+| - * ||+------------------+|| - * |||+----------------+||| - * ||||+-------------->|||| - * ||||+---------------+||| - * |||+-----------------+|| - * ||+-------------------+| - * |+---------------------+ - * ^ - * io[0] - *******************************************************************/ -static void add_top_module_io_children( - ModuleManager& module_manager, const ModuleId& top_module, - const DeviceGrid& grids, const vtr::Matrix& grid_instance_ids) { - /* Create the coordinate range for the perimeter I/Os of FPGA fabric */ - std::map>> io_coordinates = - generate_perimeter_grid_coordinates(grids); - - for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { - for (const vtr::Point& io_coord : io_coordinates[io_side]) { - /* Bypass EMPTY grid */ - if (true == is_empty_type(grids[io_coord.x()][io_coord.y()].type)) { - continue; - } - /* Skip width, height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[io_coord.x()][io_coord.y()].width_offset) || - (0 < grids[io_coord.x()][io_coord.y()].height_offset)) { - continue; - } - /* Find the module name for this type of grid */ - t_physical_tile_type_ptr grid_type = - grids[io_coord.x()][io_coord.y()].type; - std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_module_name = generate_grid_block_module_name( - grid_module_name_prefix, std::string(grid_type->name), - is_io_type(grid_type), io_side); - ModuleId grid_module = module_manager.find_module(grid_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - /* Add a I/O children to top_module*/ - module_manager.add_io_child(top_module, grid_module, - grid_instance_ids[io_coord.x()][io_coord.y()], - vtr::Point(io_coord.x(), io_coord.y())); - } - } - - /* Walk through the center grids */ - size_t xmin = 1; - size_t xmax = grids.width() - 2; - size_t ymin = 1; - size_t ymax = grids.height() - 2; - std::vector> coords; - while (xmin < xmax && ymin < ymax) { - for (size_t iy = ymin; iy < ymax + 1; iy++) { - coords.push_back(vtr::Point(xmin, iy)); - } - for (size_t ix = xmin + 1; ix < xmax + 1; ix++) { - coords.push_back(vtr::Point(ix, ymax)); - } - for (size_t iy = ymax - 1; iy > ymin; iy--) { - coords.push_back(vtr::Point(xmax, iy)); - } - for (size_t ix = xmax; ix > xmin; ix--) { - coords.push_back(vtr::Point(ix, ymin)); - } - xmin++; - ymin++; - xmax--; - ymax--; - } - - /* If height is odd, add the missing horizental line */ - if ((grids.height() - 2) % 2 == 1) { - if (ymin == ymax) { - for (size_t ix = xmin; ix < xmax + 1; ix++) { - coords.push_back(vtr::Point(ix, ymin)); - } - } - } - /* If width is odd, add the missing vertical line */ - if ((grids.width() - 2) % 2 == 1) { - if (xmin == xmax) { - for (size_t iy = ymin; iy < ymax + 1; iy++) { - coords.push_back(vtr::Point(xmin, iy)); - } - } - } - - /* Now walk through the coordinates */ - for (vtr::Point coord : coords) { - /* Bypass EMPTY grid */ - if (true == is_empty_type(grids[coord.x()][coord.y()].type)) { - continue; - } - /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[coord.x()][coord.y()].width_offset) || - (0 < grids[coord.x()][coord.y()].height_offset)) { - continue; - } - /* Find the module name for this type of grid */ - t_physical_tile_type_ptr grid_type = grids[coord.x()][coord.y()].type; - std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); - std::string grid_module_name = generate_grid_block_module_name( - grid_module_name_prefix, std::string(grid_type->name), - is_io_type(grid_type), NUM_SIDES); - ModuleId grid_module = module_manager.find_module(grid_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); - /* Add a I/O children to top_module*/ - module_manager.add_io_child(top_module, grid_module, - grid_instance_ids[coord.x()][coord.y()], - vtr::Point(coord.x(), coord.y())); - } -} - /******************************************************************** * Print the top-level module for the FPGA fabric in Verilog format * This function will @@ -437,9 +54,11 @@ int build_top_module( const TileAnnotation& tile_annotation, const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, const TileDirect& tile_direct, const ArchDirect& arch_direct, const ConfigProtocol& config_protocol, - const CircuitModelId& sram_model, const bool& frame_view, - const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin, - const FabricKey& fabric_key, const bool& generate_random_fabric_key) { + const CircuitModelId& sram_model, const FabricTile& fabric_tile, + const bool& frame_view, const bool& compact_routing_hierarchy, + const bool& duplicate_grid_pin, const FabricKey& fabric_key, + const bool& generate_random_fabric_key, const bool& group_config_block, + const bool& verbose) { vtr::ScopedStartFinishTimer timer("Build FPGA fabric module"); int status = CMD_EXEC_SUCCESS; @@ -452,94 +71,27 @@ int build_top_module( /* Label module usage */ module_manager.set_module_usage(top_module, ModuleManager::MODULE_TOP); - std::map> cb_instance_ids; + size_t layer = 0; - /* Add sub modules, which are grid, SB and CBX/CBY modules as instances */ - /* Add all the grids across the fabric */ - vtr::Matrix grid_instance_ids = - add_top_module_grid_instances(module_manager, top_module, grids); - /* Add all the SBs across the fabric */ - vtr::Matrix sb_instance_ids = add_top_module_switch_block_instances( - module_manager, top_module, device_rr_gsb, compact_routing_hierarchy); - /* Add all the CBX and CBYs across the fabric */ - cb_instance_ids[CHANX] = add_top_module_connection_block_instances( - module_manager, top_module, device_rr_gsb, CHANX, - compact_routing_hierarchy); - cb_instance_ids[CHANY] = add_top_module_connection_block_instances( - module_manager, top_module, device_rr_gsb, CHANY, - compact_routing_hierarchy); - - /* Update I/O children list */ - add_top_module_io_children(module_manager, top_module, grids, - grid_instance_ids); - - /* Add nets when we need a complete fabric modeling, - * which is required by downstream functions - */ - if (false == frame_view) { - /* Reserve nets to be memory efficient */ - reserve_module_manager_module_nets(module_manager, top_module); - - /* Add module nets to connect the sub modules */ - add_top_module_nets_connect_grids_and_gsbs( - module_manager, top_module, vpr_device_annotation, grids, - grid_instance_ids, rr_graph, device_rr_gsb, sb_instance_ids, - cb_instance_ids, compact_routing_hierarchy, duplicate_grid_pin); - /* Add inter-CLB direct connections */ - add_top_module_nets_tile_direct_connections( - module_manager, top_module, circuit_lib, vpr_device_annotation, grids, - grid_instance_ids, tile_direct, arch_direct); - } - - /* Add global ports from grid ports that are defined as global in tile - * annotation */ - status = add_top_module_global_ports_from_grid_modules( - module_manager, top_module, tile_annotation, vpr_device_annotation, grids, - rr_graph, device_rr_gsb, cb_instance_ids, grid_instance_ids, clk_ntwk, - rr_clock_lookup); - if (CMD_EXEC_FATAL_ERROR == status) { - return status; - } - - /* Add GPIO ports from the sub-modules under this Verilog module - * For top-level module, we follow a special sequencing for I/O modules. So we - * rebuild the I/O children list here - */ - add_module_gpio_ports_from_child_modules(module_manager, top_module); - - /* Organize the list of memory modules and instances - * If we have an empty fabric key, we organize the memory modules as routine - * Otherwise, we will load the fabric key directly - */ - if (true == fabric_key.empty()) { - organize_top_module_memory_modules( - module_manager, top_module, circuit_lib, config_protocol, sram_model, - grids, grid_instance_ids, device_rr_gsb, sb_instance_ids, cb_instance_ids, - compact_routing_hierarchy); + if (fabric_tile.empty()) { + status = build_top_module_fine_grained_child_instances( + module_manager, top_module, blwl_sr_banks, circuit_lib, clk_ntwk, + rr_clock_lookup, vpr_device_annotation, grids, layer, tile_annotation, + rr_graph, device_rr_gsb, tile_direct, arch_direct, config_protocol, + sram_model, frame_view, compact_routing_hierarchy, duplicate_grid_pin, + fabric_key, group_config_block); } else { - VTR_ASSERT_SAFE(false == fabric_key.empty()); - /* Throw a fatal error when the fabric key has a mismatch in region - * organization. between architecture file and fabric key - */ - if (size_t(config_protocol.num_regions()) != fabric_key.regions().size()) { - VTR_LOG_ERROR( - "Fabric key has a different number of configurable regions (='%ld') " - "than architecture definition (=%d)!\n", - fabric_key.regions().size(), config_protocol.num_regions()); - return CMD_EXEC_FATAL_ERROR; - } + /* TODO: Build the tile instances under the top module */ + status = build_top_module_tile_child_instances( + module_manager, top_module, blwl_sr_banks, circuit_lib, clk_ntwk, + rr_clock_lookup, vpr_device_annotation, grids, layer, tile_annotation, + rr_graph, device_rr_gsb, tile_direct, arch_direct, fabric_tile, + config_protocol, sram_model, fabric_key, group_config_block, frame_view, + verbose); + } - status = load_top_module_memory_modules_from_fabric_key( - module_manager, top_module, circuit_lib, config_protocol, fabric_key); - if (CMD_EXEC_FATAL_ERROR == status) { - return status; - } - - status = load_top_module_shift_register_banks_from_fabric_key( - fabric_key, blwl_sr_banks); - if (CMD_EXEC_FATAL_ERROR == status) { - return status; - } + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; } /* Shuffle the configurable children in a random sequence */ @@ -587,7 +139,10 @@ int build_top_module( * module! */ if (false == frame_view) { - if (0 < module_manager.configurable_children(top_module).size()) { + if (0 < module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .size()) { add_top_module_nets_memory_config_bus( module_manager, decoder_lib, blwl_sr_banks, top_module, circuit_lib, config_protocol, circuit_lib.design_tech_type(sram_model), diff --git a/openfpga/src/fabric/build_top_module.h b/openfpga/src/fabric/build_top_module.h index 9a4fb8fe0..d62ac4993 100644 --- a/openfpga/src/fabric/build_top_module.h +++ b/openfpga/src/fabric/build_top_module.h @@ -15,6 +15,7 @@ #include "device_grid.h" #include "device_rr_gsb.h" #include "fabric_key.h" +#include "fabric_tile.h" #include "memory_bank_shift_register_banks.h" #include "module_manager.h" #include "rr_clock_spatial_lookup.h" @@ -40,9 +41,11 @@ int build_top_module( const TileAnnotation& tile_annotation, const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, const TileDirect& tile_direct, const ArchDirect& arch_direct, const ConfigProtocol& config_protocol, - const CircuitModelId& sram_model, const bool& frame_view, - const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin, - const FabricKey& fabric_key, const bool& generate_random_fabric_key); + const CircuitModelId& sram_model, const FabricTile& fabric_tile, + const bool& frame_view, const bool& compact_routing_hierarchy, + const bool& duplicate_grid_pin, const FabricKey& fabric_key, + const bool& generate_random_fabric_key, const bool& group_config_block, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_child_fine_grained_instance.cpp b/openfpga/src/fabric/build_top_module_child_fine_grained_instance.cpp new file mode 100644 index 000000000..7640a969c --- /dev/null +++ b/openfpga/src/fabric/build_top_module_child_fine_grained_instance.cpp @@ -0,0 +1,551 @@ +/******************************************************************** + * This file includes functions that are used to print the top-level + * module for the FPGA fabric in Verilog format + *******************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from vpr library */ +#include "vpr_utils.h" + +/* Headers from openfpgashell library */ +#include "build_module_graph_utils.h" +#include "build_top_module_child_fine_grained_instance.h" +#include "build_top_module_connection.h" +#include "build_top_module_directs.h" +#include "build_top_module_memory.h" +#include "build_top_module_memory_bank.h" +#include "build_top_module_utils.h" +#include "command_exit_codes.h" +#include "module_manager_memory_utils.h" +#include "module_manager_utils.h" +#include "openfpga_device_grid_utils.h" +#include "openfpga_naming.h" +#include "openfpga_reserved_words.h" +#include "rr_gsb_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Add a instance of a grid module to the top module + *******************************************************************/ +static size_t add_top_module_grid_instance( + ModuleManager& module_manager, const ModuleId& top_module, + t_physical_tile_type_ptr grid_type, const e_side& border_side, + const vtr::Point& grid_coord) { + /* Find the module name for this type of grid */ + std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), border_side); + ModuleId grid_module = module_manager.find_module(grid_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); + /* Record the instance id */ + size_t grid_instance = module_manager.num_instance(top_module, grid_module); + /* Add the module to top_module */ + module_manager.add_child_module(top_module, grid_module, false); + /* Set an unique name to the instance + * Note: it is your risk to gurantee the name is unique! + */ + std::string instance_name = generate_grid_block_instance_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), border_side, grid_coord); + module_manager.set_child_instance_name(top_module, grid_module, grid_instance, + instance_name); + + return grid_instance; +} + +/******************************************************************** + * Add all the grids as sub-modules across the fabric + * The grid modules are created for each unique type of grid (based + * on the type in data structure data_structure + * Here, we will iterate over the full fabric (coordinates) + * and instanciate the grid modules + * + * Return an 2-D array of instance ids of the grid modules that + * have been added + * + * This function assumes an island-style floorplanning for FPGA fabric + * + * + * +-----------------------------------+ + * | I/O grids | + * | TOP side | + * +-----------------------------------+ + * + * +-----------+ +-----------------------------------+ +------------+ + * | | | | | | + * | I/O grids | | Core grids | | I/O grids | + * | LEFT side | | (CLB, Heterogeneous blocks, etc.) | | RIGHT side | + * | | | | | | + * +-----------+ +-----------------------------------+ +------------+ + * + * +-----------------------------------+ + * | I/O grids | + * | BOTTOM side | + * +-----------------------------------+ + * + *******************************************************************/ +static vtr::Matrix add_top_module_grid_instances( + ModuleManager& module_manager, const ModuleId& top_module, + const DeviceGrid& grids, const size_t& layer) { + vtr::ScopedStartFinishTimer timer("Add grid instances to top module"); + + /* Reserve an array for the instance ids */ + vtr::Matrix grid_instance_ids({grids.width(), grids.height()}); + grid_instance_ids.fill(size_t(-1)); + + /* Instanciate I/O grids */ + /* Create the coordinate range for each side of FPGA fabric */ + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(grids); + + for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { + for (const vtr::Point& io_coordinate : io_coordinates[io_side]) { + t_physical_tile_loc phy_tile_loc(io_coordinate.x(), io_coordinate.y(), + layer); + t_physical_tile_type_ptr phy_tile_type = + grids.get_physical_type(phy_tile_loc); + /* Bypass EMPTY grid */ + if (true == is_empty_type(phy_tile_type)) { + continue; + } + /* Skip width, height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { + /* Find the root of this grid, the instance id should be valid. + * We just copy it here + */ + vtr::Point root_grid_coord( + io_coordinate.x() - grids.get_width_offset(phy_tile_loc), + io_coordinate.y() - grids.get_height_offset(phy_tile_loc)); + VTR_ASSERT(size_t(-1) != + grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]); + grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = + grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]; + continue; + } + + /* Add a grid module to top_module*/ + grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = + add_top_module_grid_instance(module_manager, top_module, phy_tile_type, + io_side, io_coordinate); + } + } + + /* Instanciate core grids + * IMPORTANT: sequence matters here, it impacts the I/O indexing. + * We should follow the same sequence as the build_io_location_map()! + * If you change the sequence of walking through grids here, you should change + * it in the build_io_location map()! + */ + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + t_physical_tile_loc phy_tile_loc(ix, iy, layer); + t_physical_tile_type_ptr phy_tile_type = + grids.get_physical_type(phy_tile_loc); + /* Bypass EMPTY grid */ + if (true == is_empty_type(phy_tile_type)) { + continue; + } + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { + /* Find the root of this grid, the instance id should be valid. + * We just copy it here + */ + vtr::Point root_grid_coord( + ix - grids.get_width_offset(phy_tile_loc), + iy - grids.get_height_offset(phy_tile_loc)); + VTR_ASSERT(size_t(-1) != + grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]); + grid_instance_ids[ix][iy] = + grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()]; + continue; + } + /* Add a grid module to top_module*/ + vtr::Point grid_coord(ix, iy); + grid_instance_ids[ix][iy] = add_top_module_grid_instance( + module_manager, top_module, phy_tile_type, NUM_SIDES, grid_coord); + } + } + + return grid_instance_ids; +} + +/******************************************************************** + * Add switch blocks across the FPGA fabric to the top-level module + * Return an 2-D array of instance ids of the switch blocks that + * have been added + *******************************************************************/ +static vtr::Matrix add_top_module_switch_block_instances( + ModuleManager& module_manager, const ModuleId& top_module, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const bool& compact_routing_hierarchy) { + vtr::ScopedStartFinishTimer timer("Add switch block instances to top module"); + + vtr::Point sb_range = device_rr_gsb.get_gsb_range(); + + /* Reserve an array for the instance ids */ + vtr::Matrix sb_instance_ids({sb_range.x(), sb_range.y()}); + sb_instance_ids.fill(size_t(-1)); + + for (size_t ix = 0; ix < sb_range.x(); ++ix) { + for (size_t iy = 0; iy < sb_range.y(); ++iy) { + /* If we use compact routing hierarchy, we should instanciate the unique + * module of SB */ + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); + + if (false == rr_gsb.is_sb_exist(rr_graph)) { + continue; + } + + vtr::Point sb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); + if (true == compact_routing_hierarchy) { + vtr::Point sb_coord(ix, iy); + const RRGSB& unique_mirror = + device_rr_gsb.get_sb_unique_module(sb_coord); + sb_coordinate.set_x(unique_mirror.get_sb_x()); + sb_coordinate.set_y(unique_mirror.get_sb_y()); + } + std::string sb_module_name = + generate_switch_block_module_name(sb_coordinate); + ModuleId sb_module = module_manager.find_module(sb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); + /* Record the instance id */ + sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()] = + module_manager.num_instance(top_module, sb_module); + /* Add the module to top_module */ + module_manager.add_child_module(top_module, sb_module, false); + /* Set an unique name to the instance + * Note: it is your risk to gurantee the name is unique! + */ + module_manager.set_child_instance_name( + top_module, sb_module, + sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], + generate_switch_block_module_name( + vtr::Point(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()))); + } + } + + return sb_instance_ids; +} + +/******************************************************************** + * Add switch blocks across the FPGA fabric to the top-level module + *******************************************************************/ +static vtr::Matrix add_top_module_connection_block_instances( + ModuleManager& module_manager, const ModuleId& top_module, + const DeviceRRGSB& device_rr_gsb, const t_rr_type& cb_type, + const bool& compact_routing_hierarchy) { + vtr::ScopedStartFinishTimer timer( + "Add connection block instances to top module"); + + vtr::Point cb_range = device_rr_gsb.get_gsb_range(); + + /* Reserve an array for the instance ids */ + vtr::Matrix cb_instance_ids({cb_range.x(), cb_range.y()}); + cb_instance_ids.fill(size_t(-1)); + + for (size_t ix = 0; ix < cb_range.x(); ++ix) { + for (size_t iy = 0; iy < cb_range.y(); ++iy) { + /* Check if the connection block exists in the device! + * Some of them do NOT exist due to heterogeneous blocks (height > 1) + * We will skip those modules + */ + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); + vtr::Point cb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + if (false == rr_gsb.is_cb_exist(cb_type)) { + continue; + } + /* If we use compact routing hierarchy, we should instanciate the unique + * module of SB */ + if (true == compact_routing_hierarchy) { + vtr::Point cb_coord(ix, iy); + /* Note: use GSB coordinate when inquire for unique modules!!! */ + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, cb_coord); + cb_coordinate.set_x(unique_mirror.get_cb_x(cb_type)); + cb_coordinate.set_y(unique_mirror.get_cb_y(cb_type)); + } + std::string cb_module_name = + generate_connection_block_module_name(cb_type, cb_coordinate); + ModuleId cb_module = module_manager.find_module(cb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); + /* Record the instance id */ + cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)] = + module_manager.num_instance(top_module, cb_module); + /* Add the module to top_module */ + module_manager.add_child_module(top_module, cb_module, false); + /* Set an unique name to the instance + * Note: it is your risk to gurantee the name is unique! + */ + std::string cb_instance_name = generate_connection_block_module_name( + cb_type, + vtr::Point(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type))); + module_manager.set_child_instance_name( + top_module, cb_module, + cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], + cb_instance_name); + } + } + + return cb_instance_ids; +} + +/******************************************************************** + * Add the I/O children to the top-level module, which impacts the I/O indexing + * This is the default function to build the I/O sequence/indexing + * The I/O children is added in a maze shape + * The function supports I/Os in the center of grids, starting from the + *bottom-left corner and ending at the center + * + * +----------------------+ + * |+--------------------+| + * ||+------------------+|| + * |||+----------------+||| + * ||||+-------------->|||| + * ||||+---------------+||| + * |||+-----------------+|| + * ||+-------------------+| + * |+---------------------+ + * ^ + * io[0] + *******************************************************************/ +static void add_top_module_io_children( + ModuleManager& module_manager, const ModuleId& top_module, + const DeviceGrid& grids, const size_t& layer, + const vtr::Matrix& grid_instance_ids) { + /* Create the coordinate range for the perimeter I/Os of FPGA fabric */ + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(grids); + + for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { + for (const vtr::Point& io_coord : io_coordinates[io_side]) { + t_physical_tile_loc phy_tile_loc(io_coord.x(), io_coord.y(), layer); + t_physical_tile_type_ptr grid_type = + grids.get_physical_type(phy_tile_loc); + /* Bypass EMPTY grid */ + if (true == is_empty_type(grid_type)) { + continue; + } + /* Skip width, height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { + continue; + } + /* Find the module name for this type of grid */ + std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), io_side); + ModuleId grid_module = module_manager.find_module(grid_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); + /* Add a I/O children to top_module*/ + module_manager.add_io_child(top_module, grid_module, + grid_instance_ids[io_coord.x()][io_coord.y()], + vtr::Point(io_coord.x(), io_coord.y())); + } + } + + /* Walk through the center grids */ + size_t xmin = 1; + size_t xmax = grids.width() - 2; + size_t ymin = 1; + size_t ymax = grids.height() - 2; + std::vector> coords; + while (xmin < xmax && ymin < ymax) { + for (size_t iy = ymin; iy < ymax + 1; iy++) { + coords.push_back(vtr::Point(xmin, iy)); + } + for (size_t ix = xmin + 1; ix < xmax + 1; ix++) { + coords.push_back(vtr::Point(ix, ymax)); + } + for (size_t iy = ymax - 1; iy > ymin; iy--) { + coords.push_back(vtr::Point(xmax, iy)); + } + for (size_t ix = xmax; ix > xmin; ix--) { + coords.push_back(vtr::Point(ix, ymin)); + } + xmin++; + ymin++; + xmax--; + ymax--; + } + + /* If height is odd, add the missing horizental line */ + if ((grids.height() - 2) % 2 == 1) { + if (ymin == ymax) { + for (size_t ix = xmin; ix < xmax + 1; ix++) { + coords.push_back(vtr::Point(ix, ymin)); + } + } + } + /* If width is odd, add the missing vertical line */ + if ((grids.width() - 2) % 2 == 1) { + /* Note: Do NOT add a coord two time! So when ymin == ymax, should skip this + * point. Think about a fabric of 3x3, where the point (1,1) is added twice + */ + if (xmin == xmax && ymin != ymax) { + for (size_t iy = ymin; iy < ymax + 1; iy++) { + coords.push_back(vtr::Point(xmin, iy)); + } + } + } + + /* Now walk through the coordinates */ + for (vtr::Point coord : coords) { + t_physical_tile_loc phy_tile_loc(coord.x(), coord.y(), layer); + t_physical_tile_type_ptr grid_type = grids.get_physical_type(phy_tile_loc); + /* Bypass EMPTY grid */ + if (true == is_empty_type(grid_type)) { + continue; + } + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { + continue; + } + /* Find the module name for this type of grid */ + std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); + std::string grid_module_name = generate_grid_block_module_name( + grid_module_name_prefix, std::string(grid_type->name), + is_io_type(grid_type), NUM_SIDES); + ModuleId grid_module = module_manager.find_module(grid_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); + /* Add a I/O children to top_module*/ + module_manager.add_io_child(top_module, grid_module, + grid_instance_ids[coord.x()][coord.y()], + vtr::Point(coord.x(), coord.y())); + } +} + +/******************************************************************** + * Add the fine-grained instances to the top module of FPGA fabric + * The fine-grained instances include programmable blocks, connection blocks and + *switch blocks, each of which is an instance under the top module + *******************************************************************/ +int build_top_module_fine_grained_child_instances( + ModuleManager& module_manager, const ModuleId& top_module, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const CircuitLibrary& circuit_lib, const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& rr_clock_lookup, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const size_t& layer, const TileAnnotation& tile_annotation, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const TileDirect& tile_direct, const ArchDirect& arch_direct, + const ConfigProtocol& config_protocol, const CircuitModelId& sram_model, + const bool& frame_view, const bool& compact_routing_hierarchy, + const bool& duplicate_grid_pin, const FabricKey& fabric_key, + const bool& group_config_block) { + int status = CMD_EXEC_SUCCESS; + std::map> cb_instance_ids; + + /* Add sub modules, which are grid, SB and CBX/CBY modules as instances */ + /* Add all the grids across the fabric */ + vtr::Matrix grid_instance_ids = + add_top_module_grid_instances(module_manager, top_module, grids, layer); + /* Add all the SBs across the fabric */ + vtr::Matrix sb_instance_ids = add_top_module_switch_block_instances( + module_manager, top_module, rr_graph, device_rr_gsb, + compact_routing_hierarchy); + /* Add all the CBX and CBYs across the fabric */ + cb_instance_ids[CHANX] = add_top_module_connection_block_instances( + module_manager, top_module, device_rr_gsb, CHANX, + compact_routing_hierarchy); + cb_instance_ids[CHANY] = add_top_module_connection_block_instances( + module_manager, top_module, device_rr_gsb, CHANY, + compact_routing_hierarchy); + + /* Update I/O children list */ + add_top_module_io_children(module_manager, top_module, grids, layer, + grid_instance_ids); + + /* Add nets when we need a complete fabric modeling, + * which is required by downstream functions + */ + if (false == frame_view) { + /* Reserve nets to be memory efficient */ + reserve_module_manager_module_nets(module_manager, top_module); + + /* Add module nets to connect the sub modules */ + add_top_module_nets_connect_grids_and_gsbs( + module_manager, top_module, vpr_device_annotation, grids, layer, + grid_instance_ids, rr_graph, device_rr_gsb, sb_instance_ids, + cb_instance_ids, compact_routing_hierarchy, duplicate_grid_pin); + /* Add inter-CLB direct connections */ + add_top_module_nets_tile_direct_connections( + module_manager, top_module, circuit_lib, vpr_device_annotation, grids, + layer, grid_instance_ids, tile_direct, arch_direct); + } + + /* Add global ports from grid ports that are defined as global in tile + * annotation */ + status = add_top_module_global_ports_from_grid_modules( + module_manager, top_module, tile_annotation, vpr_device_annotation, grids, + layer, rr_graph, device_rr_gsb, cb_instance_ids, grid_instance_ids, + clk_ntwk, rr_clock_lookup); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + + /* Add GPIO ports from the sub-modules under this Verilog module + * For top-level module, we follow a special sequencing for I/O modules. So we + * rebuild the I/O children list here + */ + add_module_gpio_ports_from_child_modules(module_manager, top_module); + + /* Organize the list of memory modules and instances + * If we have an empty fabric key, we organize the memory modules as routine + * Otherwise, we will load the fabric key directly + */ + if (true == fabric_key.empty()) { + organize_top_module_memory_modules( + module_manager, top_module, circuit_lib, config_protocol, sram_model, + grids, layer, grid_instance_ids, device_rr_gsb, rr_graph, sb_instance_ids, + cb_instance_ids, compact_routing_hierarchy); + } else { + VTR_ASSERT_SAFE(false == fabric_key.empty()); + /* Throw a fatal error when the fabric key has a mismatch in region + * organization. between architecture file and fabric key + */ + if (size_t(config_protocol.num_regions()) != fabric_key.regions().size()) { + VTR_LOG_ERROR( + "Fabric key has a different number of configurable regions (='%ld') " + "than architecture definition (=%d)!\n", + fabric_key.regions().size(), config_protocol.num_regions()); + return CMD_EXEC_FATAL_ERROR; + } + + status = load_top_module_memory_modules_from_fabric_key( + module_manager, top_module, circuit_lib, config_protocol, fabric_key); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + + status = load_top_module_shift_register_banks_from_fabric_key( + fabric_key, blwl_sr_banks); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + + /* Update the memory organization in sub module (non-top) */ + status = load_submodules_memory_modules_from_fabric_key( + module_manager, circuit_lib, config_protocol, fabric_key, + group_config_block); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + } + return CMD_EXEC_SUCCESS; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_child_fine_grained_instance.h b/openfpga/src/fabric/build_top_module_child_fine_grained_instance.h new file mode 100644 index 000000000..f54e07c24 --- /dev/null +++ b/openfpga/src/fabric/build_top_module_child_fine_grained_instance.h @@ -0,0 +1,51 @@ +#ifndef BUILD_TOP_MODULE_CHILD_FINE_GRAINED_INSTANCE_H +#define BUILD_TOP_MODULE_CHILD_FINE_GRAINED_INSTANCE_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ + +#include + +#include "arch_direct.h" +#include "circuit_library.h" +#include "clock_network.h" +#include "config_protocol.h" +#include "decoder_library.h" +#include "device_grid.h" +#include "device_rr_gsb.h" +#include "fabric_key.h" +#include "fabric_tile.h" +#include "memory_bank_shift_register_banks.h" +#include "module_manager.h" +#include "rr_clock_spatial_lookup.h" +#include "rr_graph_view.h" +#include "tile_annotation.h" +#include "tile_direct.h" +#include "vpr_device_annotation.h" +#include "vtr_geometry.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int build_top_module_fine_grained_child_instances( + ModuleManager& module_manager, const ModuleId& top_module, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const CircuitLibrary& circuit_lib, const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& rr_clock_lookup, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const size_t& layer, const TileAnnotation& tile_annotation, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const TileDirect& tile_direct, const ArchDirect& arch_direct, + const ConfigProtocol& config_protocol, const CircuitModelId& sram_model, + const bool& frame_view, const bool& compact_routing_hierarchy, + const bool& duplicate_grid_pin, const FabricKey& fabric_key, + const bool& group_config_block); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fabric/build_top_module_child_tile_instance.cpp b/openfpga/src/fabric/build_top_module_child_tile_instance.cpp new file mode 100644 index 000000000..ff2bae0aa --- /dev/null +++ b/openfpga/src/fabric/build_top_module_child_tile_instance.cpp @@ -0,0 +1,1969 @@ +/******************************************************************** + * This file includes functions that are used to print the top-level + * module for the FPGA fabric in Verilog format + *******************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from vpr library */ +#include "vpr_utils.h" + +/* Headers from openfpgashell library */ +#include "build_module_graph_utils.h" +#include "build_routing_module_utils.h" +#include "build_top_module_child_tile_instance.h" +#include "build_top_module_connection.h" +#include "build_top_module_directs.h" +#include "build_top_module_memory.h" +#include "build_top_module_memory_bank.h" +#include "build_top_module_utils.h" +#include "command_exit_codes.h" +#include "module_manager_memory_utils.h" +#include "module_manager_utils.h" +#include "openfpga_device_grid_utils.h" +#include "openfpga_naming.h" +#include "openfpga_physical_tile_utils.h" +#include "openfpga_reserved_words.h" +#include "openfpga_rr_graph_utils.h" +#include "rr_gsb_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Add a instance of a tile module to the top module + *******************************************************************/ +static size_t add_top_module_tile_instance(ModuleManager& module_manager, + const ModuleId& top_module, + const FabricTile& fabric_tile, + const FabricTileId& fabric_tile_id) { + /* Find the module name for this type of grid */ + vtr::Point unique_tile_coord = + fabric_tile.unique_tile_coordinate(fabric_tile_id); + std::string tile_module_name = generate_tile_module_name(unique_tile_coord); + ModuleId tile_module = module_manager.find_module(tile_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(tile_module)); + /* Record the instance id */ + size_t tile_instance = module_manager.num_instance(top_module, tile_module); + /* Add the module to top_module */ + module_manager.add_child_module(top_module, tile_module, false); + /* Set an unique name to the instance + * Note: it is your risk to gurantee the name is unique! + */ + vtr::Point tile_coord = fabric_tile.tile_coordinate(fabric_tile_id); + std::string instance_name = generate_tile_module_name(tile_coord); + module_manager.set_child_instance_name(top_module, tile_module, tile_instance, + instance_name); + return tile_instance; +} + +/******************************************************************** + * Add all the tiles as sub-modules across the fabric + * Here, we will iterate over the full fabric (coordinates) + * and instanciate the tile modules + * + * Return an 2-D array of instance ids of the grid modules that + * have been added + * + * This function assumes an island-style floorplanning for FPGA fabric + * + * + * +-----------------------------------+ + * | I/O tiles | + * | TOP side | + * +-----------------------------------+ + * + * +-----------+ +-----------------------------------+ +------------+ + * | | | | | | + * | I/O tiles | | Core tiles | | I/O tiles | + * | LEFT side | | (CLB, Heterogeneous blocks, etc.) | | RIGHT side | + * | | | | | | + * +-----------+ +-----------------------------------+ +------------+ + * + * +-----------------------------------+ + * | I/O tiles | + * | BOTTOM side | + * +-----------------------------------+ + * + *******************************************************************/ +static int add_top_module_tile_instances(ModuleManager& module_manager, + const ModuleId& top_module, + vtr::Matrix& tile_instance_ids, + const DeviceGrid& grids, + const FabricTile& fabric_tile) { + vtr::ScopedStartFinishTimer timer("Add tile instances to top module"); + int status = CMD_EXEC_SUCCESS; + + /* Reserve an array for the instance ids */ + tile_instance_ids.resize({grids.width(), grids.height()}); + tile_instance_ids.fill(size_t(-1)); + + /* Instanciate I/O grids */ + /* Create the coordinate range for each side of FPGA fabric */ + std::map>> io_coordinates = + generate_perimeter_tile_coordinates(grids); + + for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { + for (const vtr::Point& io_coord : io_coordinates[io_side]) { + FabricTileId fabric_tile_id = fabric_tile.find_tile(io_coord); + if (!fabric_tile.valid_tile_id(fabric_tile_id)) { + continue; + } + /* Add a tile module to top_module*/ + tile_instance_ids[io_coord.x()][io_coord.y()] = + add_top_module_tile_instance(module_manager, top_module, fabric_tile, + fabric_tile_id); + } + } + + /* Instanciate core grids + * IMPORTANT: sequence matters here, it impacts the I/O indexing. + * We should follow the same sequence as the build_io_location_map()! + * If you change the sequence of walking through grids here, you should change + * it in the build_io_location map()! + */ + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + vtr::Point curr_coord(ix, iy); + FabricTileId fabric_tile_id = fabric_tile.find_tile(curr_coord); + if (!fabric_tile.valid_tile_id(fabric_tile_id)) { + continue; + } + /* Add a tile module to top_module*/ + tile_instance_ids[curr_coord.x()][curr_coord.y()] = + add_top_module_tile_instance(module_manager, top_module, fabric_tile, + fabric_tile_id); + } + } + return status; +} + +/******************************************************************** + * Add the I/O children to the top-level module, which impacts the I/O indexing + * This is the default function to build the I/O sequence/indexing + * The I/O children is added in a maze shape + * The function supports I/Os in the center of grids, starting from the + *bottom-left corner and ending at the center + * + * +----------------------+ + * |+--------------------+| + * ||+------------------+|| + * |||+----------------+||| + * ||||+-------------->|||| + * ||||+---------------+||| + * |||+-----------------+|| + * ||+-------------------+| + * |+---------------------+ + * ^ + * io[0] + *******************************************************************/ +static void add_top_module_tile_io_children( + ModuleManager& module_manager, const ModuleId& top_module, + const DeviceGrid& grids, const FabricTile& fabric_tile, + const vtr::Matrix& tile_instance_ids) { + /* Create the coordinate range for the perimeter I/Os of FPGA fabric */ + std::map>> io_coordinates = + generate_perimeter_tile_coordinates(grids); + + for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { + for (const vtr::Point& io_coord : io_coordinates[io_side]) { + FabricTileId fabric_tile_id = fabric_tile.find_tile(io_coord); + if (!fabric_tile.valid_tile_id(fabric_tile_id)) { + continue; + } + /* Find the module name for this type of tile */ + vtr::Point unique_tile_coord = + fabric_tile.unique_tile_coordinate(fabric_tile_id); + std::string tile_module_name = + generate_tile_module_name(unique_tile_coord); + ModuleId tile_module = module_manager.find_module(tile_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(tile_module)); + /* Add a I/O children to top_module*/ + module_manager.add_io_child(top_module, tile_module, + tile_instance_ids[io_coord.x()][io_coord.y()], + vtr::Point(io_coord.x(), io_coord.y())); + } + } + + /* Walk through the center grids */ + size_t xmin = 1; + size_t xmax = grids.width() - 2; + size_t ymin = 1; + size_t ymax = grids.height() - 2; + std::vector> coords; + while (xmin < xmax && ymin < ymax) { + for (size_t iy = ymin; iy < ymax + 1; iy++) { + coords.push_back(vtr::Point(xmin, iy)); + } + for (size_t ix = xmin + 1; ix < xmax + 1; ix++) { + coords.push_back(vtr::Point(ix, ymax)); + } + for (size_t iy = ymax - 1; iy > ymin; iy--) { + coords.push_back(vtr::Point(xmax, iy)); + } + for (size_t ix = xmax; ix > xmin; ix--) { + coords.push_back(vtr::Point(ix, ymin)); + } + xmin++; + ymin++; + xmax--; + ymax--; + } + + /* If height is odd, add the missing horizental line */ + if ((grids.height() - 2) % 2 == 1) { + if (ymin == ymax) { + for (size_t ix = xmin; ix < xmax + 1; ix++) { + coords.push_back(vtr::Point(ix, ymin)); + } + } + } + /* If width is odd, add the missing vertical line */ + if ((grids.width() - 2) % 2 == 1) { + if (xmin == xmax) { + for (size_t iy = ymin; iy < ymax + 1; iy++) { + coords.push_back(vtr::Point(xmin, iy)); + } + } + } + + /* Now walk through the coordinates */ + for (vtr::Point coord : coords) { + FabricTileId fabric_tile_id = fabric_tile.find_tile(coord); + if (!fabric_tile.valid_tile_id(fabric_tile_id)) { + continue; + } + /* Find the module name for this type of tile */ + vtr::Point unique_tile_coord = + fabric_tile.unique_tile_coordinate(fabric_tile_id); + std::string tile_module_name = generate_tile_module_name(unique_tile_coord); + ModuleId tile_module = module_manager.find_module(tile_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(tile_module)); + /* Add a I/O children to top_module*/ + module_manager.add_io_child(top_module, tile_module, + tile_instance_ids[coord.x()][coord.y()], + vtr::Point(coord.x(), coord.y())); + } +} + +/******************************************************************** + * Add module nets to connect a switch block in a given tile to the programmable + *block in adjacent tiles + * + * TileA | TileB + * +------------+ | +------------+ + * | | | | | + * | Grid | | | Grid | + * | [x][y+1] | | | [x+1][y+1] | + * | |--|-+ +----| | + * +------------+ | | | +------------+ + * | | | | | + * ------------------+ v v | + * | +------------+ | + * +------>| |<-----+ + * | Switch | + * | Block | + * +------>| [x][y] |<-----+ + * | +------------+ | + * | ^ ^ | + * | | | | + * +------------+ | | +------------+ + * | |----+ +-----| | + * | Grid | | Grid | + * | [x][y] | | [x+1][y] | + * | | | | + * +------------+ +------------+ + * + *******************************************************************/ +static int build_top_module_tile_nets_between_sb_and_pb( + ModuleManager& module_manager, const ModuleId& top_module, + const ModuleId& curr_tile_module, + const vtr::Matrix& tile_instance_ids, + const size_t& curr_tile_instance_id, const DeviceGrid& grids, + const VprDeviceAnnotation& vpr_device_annotation, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph, + const RRGSB& rr_gsb, const FabricTile& fabric_tile, + const FabricTileId& curr_fabric_tile_id, + const size_t& sb_idx_in_curr_fabric_tile, + const bool& compact_routing_hierarchy, const bool& verbose) { + /* Skip those Switch blocks that do not exist */ + if (false == rr_gsb.is_sb_exist(rr_graph)) { + return CMD_EXEC_SUCCESS; + } + + vtr::Point sink_tile_coord = + fabric_tile.tile_coordinate(curr_fabric_tile_id); + FabricTileId sink_unique_tile = fabric_tile.unique_tile(sink_tile_coord); + vtr::Point sink_sb_coord_in_unique_tile = + fabric_tile.sb_coordinates(sink_unique_tile)[sb_idx_in_curr_fabric_tile]; + std::string sink_sb_instance_name_in_unique_tile = + generate_switch_block_module_name(sink_sb_coord_in_unique_tile); + + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), + rr_gsb.get_sb_y()); + vtr::Point module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); + + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ + if (true == compact_routing_hierarchy) { + vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); + const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord); + module_gsb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_coordinate.set_y(unique_mirror.get_y()); + } + + /* This is the source cb that is added to the top module */ + const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_coordinate); + vtr::Point module_sb_coordinate(module_sb.get_sb_x(), + module_sb.get_sb_y()); + + /* Connect grid output pins (OPIN) to switch block grid pins */ + for (size_t side = 0; side < module_sb.get_num_sides(); ++side) { + SideManager side_manager(side); + for (size_t inode = 0; + inode < module_sb.get_num_opin_nodes(side_manager.get_side()); + ++inode) { + /* Collect source-related information */ + vtr::Point grid_coordinate( + rr_graph.node_xlow( + rr_gsb.get_opin_node(side_manager.get_side(), inode)), + rr_graph.node_ylow( + rr_gsb.get_opin_node(side_manager.get_side(), inode))); + /* Check if the grid is inside the tile, if not, create ports */ + if (fabric_tile.pb_in_tile(curr_fabric_tile_id, grid_coordinate)) { + continue; + } + + /* Find the source tile id, coordinate etc., which is required to find + * source tile module and port Relationship between source tile and its + * unique module Take an example: + * + * grid_pin name should follow unique module [i0][j0] of + * src_tile[x0][y0] sb_pin name should follow unique module [i1][j1] of + * des_tile[x1][y1] + * + * However, instance id should follow the origin tiles + * + * Src tile Des tile + * +------------+ +--------------+ + * | | | | + * | Grid |------------>| Switch Block | + * | [x0][y0] | | [x1][y1] | + * | | | | + * +------------+ +--------------+ + * ^ ^ + * || unique_mirror || unique mirror + * +------------+ +--------------+ + * | | | | + * | Grid |<------------| Switch Block | + * | [i0][j0] | | [i1][j1] | + * | | | | + * +------------+ +--------------+ + * + */ + FabricTileId src_fabric_tile_id = + fabric_tile.find_tile_by_pb_coordinate(grid_coordinate); + size_t pb_idx_in_src_fabric_tile = + fabric_tile.find_pb_index_in_tile(src_fabric_tile_id, grid_coordinate); + vtr::Point src_tile_coord = + fabric_tile.tile_coordinate(src_fabric_tile_id); + vtr::Point src_unique_tile_coord = + fabric_tile.unique_tile_coordinate(src_fabric_tile_id); + FabricTileId src_unique_tile = fabric_tile.unique_tile(src_tile_coord); + vtr::Point src_pb_coord_in_unique_tile = + fabric_tile.pb_coordinates(src_unique_tile)[pb_idx_in_src_fabric_tile]; + std::string src_tile_module_name = + generate_tile_module_name(src_unique_tile_coord); + ModuleId src_tile_module = + module_manager.find_module(src_tile_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(src_tile_module)); + size_t src_tile_instance = + tile_instance_ids[src_tile_coord.x()][src_tile_coord.y()]; + + size_t src_grid_pin_index = rr_graph.node_pin_num( + rr_gsb.get_opin_node(side_manager.get_side(), inode)); + std::string src_grid_port_name = + generate_grid_module_port_name_in_top_module( + grids, grid_coordinate, src_grid_pin_index, vpr_device_annotation, + rr_graph, rr_gsb.get_opin_node(side_manager.get_side(), inode)); + + std::string src_grid_module_name = + generate_grid_block_module_name_in_top_module( + std::string(GRID_MODULE_NAME_PREFIX), grids, + src_pb_coord_in_unique_tile); + std::string src_tile_grid_port_name = generate_tile_module_port_name( + src_grid_module_name, src_grid_port_name); + VTR_LOGV(verbose, "Try to find port '%s' from tile[%lu][%lu]\n", + src_tile_grid_port_name.c_str(), src_tile_coord.x(), + src_tile_coord.y()); + ModulePortId src_tile_grid_port_id = module_manager.find_module_port( + src_tile_module, src_tile_grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + src_tile_module, src_tile_grid_port_id)); + BasicPort src_tile_grid_port = + module_manager.module_port(src_tile_module, src_tile_grid_port_id); + + /* Collect sink-related information */ + vtr::Point sink_sb_port_coord( + rr_graph.node_xlow( + module_sb.get_opin_node(side_manager.get_side(), inode)), + rr_graph.node_ylow( + module_sb.get_opin_node(side_manager.get_side(), inode))); + std::string sink_sb_port_name = generate_sb_module_grid_port_name( + side_manager.get_side(), + get_rr_graph_single_node_side( + rr_graph, module_sb.get_opin_node(side_manager.get_side(), inode)), + grids, vpr_device_annotation, rr_graph, + module_sb.get_opin_node(side_manager.get_side(), inode)); + + std::string sink_tile_sb_port_name = generate_tile_module_port_name( + sink_sb_instance_name_in_unique_tile, sink_sb_port_name); + ModulePortId sink_tile_sb_port_id = module_manager.find_module_port( + curr_tile_module, sink_tile_sb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + curr_tile_module, sink_tile_sb_port_id)); + BasicPort sink_tile_sb_port = + module_manager.module_port(curr_tile_module, sink_tile_sb_port_id); + + /* Create nets */ + VTR_LOGV( + verbose, + "Build inter-tile nets between switch block '%s' in tile[%lu][%lu] and " + "programmable block in tile[%lu][%lu]\n", + sink_sb_instance_name_in_unique_tile.c_str(), sink_tile_coord.x(), + sink_tile_coord.y(), src_tile_coord.x(), src_tile_coord.y()); + + /* Source and sink port should match in size */ + VTR_ASSERT(src_tile_grid_port.get_width() == + sink_tile_sb_port.get_width()); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < src_tile_grid_port.pins().size(); + ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, src_tile_module, src_tile_instance, + src_tile_grid_port_id, src_tile_grid_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink( + top_module, net, curr_tile_module, curr_tile_instance_id, + sink_tile_sb_port_id, sink_tile_sb_port.pins()[pin_id]); + } + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * This function will create nets for the connections + * between grid input pins and connection blocks + * In this case, the net source is the connection block pin, + * while the net sink is the grid input + * + * TileA | TileB + * +------------+ | +------------------+ +------------+ + * | | | | | | | + * | Grid |<-----| Connection Block |----->| Grid | + * | [x][y+1] | | | Y-direction | | [x+1][y+1] | + * | | | | [x][y+1] | | | + * +------------+ | +------------------+ +------------+ + * ^ | + * ----------------+ + * | + * +------------+ +------------------+ + * | Connection | | | + * | Block | | Switch Block | + * | X-direction| | [x][y] | + * | [x][y] | | | + * +------------+ +------------------+ + * | + * v + * +------------+ + * | | + * | Grid | + * | [x][y] | + * | | + * +------------+ + * + * + * Relationship between source connection block and its unique module + * Take an example of a CBY + * + * grid_pin name should follow unique module of Grid[x][y+1] + * cb_pin name should follow unique module of CBY[x][y+1] + * + * However, instance id should follow the origin Grid and Connection block + * + * + * +------------+ +------------------+ + * | | | | + * | Grid |<------------| Connection Block | + * | [x][y+1] | | Y-direction | + * | | | [x][y+1] | + * +------------+ +------------------+ + * ^ + * || unique mirror + * +------------+ +------------------+ + * | | | | + * | Grid |<------------| Connection Block | + * | [i][j+1] | | Y-direction | + * | | | [i][j+1] | + * +------------+ +------------------+ + * + *******************************************************************/ +static int build_top_module_tile_nets_between_cb_and_pb( + ModuleManager& module_manager, const ModuleId& top_module, + const ModuleId& tile_module, const vtr::Matrix& tile_instance_ids, + const size_t& tile_instance_id, const DeviceGrid& grids, + const VprDeviceAnnotation& vpr_device_annotation, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph, + const RRGSB& rr_gsb, const FabricTile& fabric_tile, + const FabricTileId& curr_fabric_tile_id, const t_rr_type& cb_type, + const size_t& cb_idx_in_curr_fabric_tile, + const bool& compact_routing_hierarchy, const bool& verbose) { + vtr::Point src_tile_coord = + fabric_tile.tile_coordinate(curr_fabric_tile_id); + FabricTileId src_unique_tile = fabric_tile.unique_tile(src_tile_coord); + vtr::Point src_cb_coord_in_unique_tile = fabric_tile.cb_coordinates( + src_unique_tile, cb_type)[cb_idx_in_curr_fabric_tile]; + const RRGSB& src_cb_inst_rr_gsb = + device_rr_gsb.get_gsb(src_cb_coord_in_unique_tile); + std::string src_cb_instance_name_in_unique_tile = + generate_connection_block_module_name( + cb_type, src_cb_inst_rr_gsb.get_cb_coordinate(cb_type)); + + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_cb_coordinate(rr_gsb.get_cb_x(cb_type), + rr_gsb.get_cb_y(cb_type)); + vtr::Point module_gsb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); + + /* Skip those Connection blocks that do not exist */ + if (false == rr_gsb.is_cb_exist(cb_type)) { + return CMD_EXEC_SUCCESS; + } + + /* Skip if the cb does not contain any configuration bits! */ + if (true == connection_block_contain_only_routing_tracks(rr_gsb, cb_type)) { + return CMD_EXEC_SUCCESS; + } + + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ + if (true == compact_routing_hierarchy) { + vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, gsb_coord); + module_gsb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_coordinate.set_y(unique_mirror.get_y()); + } + + /* This is the source cb that is added to the top module */ + const RRGSB& module_cb = device_rr_gsb.get_gsb(module_gsb_coordinate); + vtr::Point module_cb_coordinate(module_cb.get_cb_x(cb_type), + module_cb.get_cb_y(cb_type)); + + /* Iterate over the output pins of the Connection Block */ + std::vector cb_ipin_sides = module_cb.get_cb_ipin_sides(cb_type); + for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) { + enum e_side cb_ipin_side = cb_ipin_sides[iside]; + for (size_t inode = 0; inode < module_cb.get_num_ipin_nodes(cb_ipin_side); + ++inode) { + /* Collect sink-related information */ + /* Note that we use the instance cb pin here!!! + * because it has the correct coordinator for the grid!!! + */ + RRNodeId instance_ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode); + vtr::Point grid_coordinate( + rr_graph.node_xlow(instance_ipin_node), + rr_graph.node_ylow(instance_ipin_node)); + /* Check if the grid is inside the tile, if not, create ports */ + if (fabric_tile.pb_in_tile(curr_fabric_tile_id, grid_coordinate)) { + continue; + } + + /* Collect source-related information */ + RRNodeId module_ipin_node = module_cb.get_ipin_node(cb_ipin_side, inode); + vtr::Point cb_src_port_coord( + rr_graph.node_xlow(module_ipin_node), + rr_graph.node_ylow(module_ipin_node)); + std::string src_cb_port_name = generate_cb_module_grid_port_name( + cb_ipin_side, grids, vpr_device_annotation, rr_graph, module_ipin_node); + std::string src_tile_cb_port_name = generate_tile_module_port_name( + src_cb_instance_name_in_unique_tile, src_cb_port_name); + VTR_LOGV( + verbose, "Finding port '%s' from connection block in tile [%lu][%lu]\n", + src_tile_cb_port_name.c_str(), src_tile_coord.x(), src_tile_coord.y()); + ModulePortId src_cb_port_id = + module_manager.find_module_port(tile_module, src_tile_cb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(tile_module, + src_cb_port_id)); + BasicPort src_cb_port = + module_manager.module_port(tile_module, src_cb_port_id); + + FabricTileId sink_fabric_tile_id = + fabric_tile.find_tile_by_pb_coordinate(grid_coordinate); + size_t pb_idx_in_sink_fabric_tile = + fabric_tile.find_pb_index_in_tile(sink_fabric_tile_id, grid_coordinate); + vtr::Point sink_tile_coord = + fabric_tile.tile_coordinate(sink_fabric_tile_id); + vtr::Point sink_unique_tile_coord = + fabric_tile.unique_tile_coordinate(sink_fabric_tile_id); + FabricTileId sink_unique_tile = fabric_tile.unique_tile(sink_tile_coord); + vtr::Point sink_pb_coord_in_unique_tile = + fabric_tile.pb_coordinates( + sink_unique_tile)[pb_idx_in_sink_fabric_tile]; + std::string sink_tile_module_name = + generate_tile_module_name(sink_unique_tile_coord); + ModuleId sink_tile_module = + module_manager.find_module(sink_tile_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(sink_tile_module)); + size_t sink_tile_instance_id = + tile_instance_ids[sink_tile_coord.x()][sink_tile_coord.y()]; + + std::string sink_grid_module_name = + generate_grid_block_module_name_in_top_module( + std::string(GRID_MODULE_NAME_PREFIX), grids, + sink_pb_coord_in_unique_tile); + + size_t sink_grid_pin_index = rr_graph.node_pin_num(instance_ipin_node); + + std::string sink_grid_port_name = + generate_grid_module_port_name_in_top_module( + grids, grid_coordinate, sink_grid_pin_index, vpr_device_annotation, + rr_graph, rr_gsb.get_ipin_node(cb_ipin_side, inode)); + + std::string sink_tile_grid_port_name = generate_tile_module_port_name( + sink_grid_module_name, sink_grid_port_name); + ModulePortId sink_grid_port_id = module_manager.find_module_port( + sink_tile_module, sink_tile_grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + sink_tile_module, sink_grid_port_id)); + BasicPort sink_grid_port = + module_manager.module_port(sink_tile_module, sink_grid_port_id); + + /* Create nets */ + /* Source and sink port should match in size */ + VTR_ASSERT(src_cb_port.get_width() == sink_grid_port.get_width()); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < src_cb_port.pins().size(); ++pin_id) { + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, tile_module, tile_instance_id, + src_cb_port_id, src_cb_port.pins()[pin_id]); + /* Configure the net sink */ + module_manager.add_module_net_sink( + top_module, net, sink_tile_module, sink_tile_instance_id, + sink_grid_port_id, sink_grid_port.pins()[pin_id]); + } + VTR_LOGV(verbose, + "Built nets between connection block of tile[%lu][%lu] and grid " + "block of tile[%lu][%lu]\n", + src_tile_coord.x(), src_tile_coord.y(), sink_tile_coord.x(), + sink_tile_coord.y()); + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * This function will create nets for the connections + * between connection block and switch block pins + * Two cases should be considered: + * a. The switch block pin denotes an input of a routing track + * The net source is an output of a routing track of connection block + * while the net sink is an input of a routing track of switch block + * b. The switch block pin denotes an output of a routing track + * The net source is an output of routing track of switch block + * while the net sink is an input of a routing track of connection block + * + * TileA | TileB + * +------------+ +------------------+ | +------------+ + * | | | | | | | + * | Grid | | Connection Block | | | Grid | + * | [x][y+1] | | Y-direction | | | [x+1][y+1] | + * | | | [x][y+1] | | | | + * +------------+ +------------------+ | +------------+ + * | ^ | + * v | | + * +------------+ +------------------+ | +------------+ + * | Connection |----->| |----->| Connection | + * | Block | | Switch Block | | | Block | + * | X-direction|<-----| [x][y] |<-----| X-direction| + * | [x][y] | | | | | [x+1][y] | + * +------------+ +------------------+ | +------------+ + * | ^ | + * ------------------------------------------+ + * v | + * +------------+ +------------------+ +------------+ + * | | | | | | + * | Grid | | Connection Block | | Grid | + * | [x][y] | | Y-direction | | [x][y+1] | + * | | | [x][y] | | | + * +------------+ +------------------+ +------------+ + * + * Here, to achieve the purpose, we can simply iterate over the + * four sides of switch block and make connections to adjancent + * connection blocks + * + *******************************************************************/ +static int build_top_module_tile_nets_between_sb_and_cb( + ModuleManager& module_manager, const ModuleId& top_module, + const ModuleId& tile_module, const vtr::Matrix& tile_instance_ids, + const size_t& tile_instance_id, const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph, const RRGSB& rr_gsb, + const FabricTile& fabric_tile, const FabricTileId& curr_fabric_tile_id, + const size_t& sb_idx_in_curr_fabric_tile, + const bool& compact_routing_hierarchy, const bool& verbose) { + /* We could have two different coordinators, one is the instance, the other is + * the module */ + vtr::Point instance_sb_coordinate(rr_gsb.get_sb_x(), + rr_gsb.get_sb_y()); + vtr::Point module_gsb_sb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); + + vtr::Point sb_tile_coord = + fabric_tile.tile_coordinate(curr_fabric_tile_id); + FabricTileId sb_unique_tile = fabric_tile.unique_tile(sb_tile_coord); + vtr::Point sb_coord_in_unique_tile = + fabric_tile.sb_coordinates(sb_unique_tile)[sb_idx_in_curr_fabric_tile]; + std::string sb_instance_name_in_unique_tile = + generate_switch_block_module_name(sb_coord_in_unique_tile); + + /* Skip those Switch blocks that do not exist */ + if (false == rr_gsb.is_sb_exist(rr_graph)) { + return CMD_EXEC_SUCCESS; + } + + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ + if (true == compact_routing_hierarchy) { + vtr::Point gsb_coord(rr_gsb.get_x(), rr_gsb.get_y()); + const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(gsb_coord); + module_gsb_sb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_sb_coordinate.set_y(unique_mirror.get_y()); + } + + /* This is the source cb that is added to the top module */ + const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_sb_coordinate); + vtr::Point module_sb_coordinate(module_sb.get_sb_x(), + module_sb.get_sb_y()); + std::string sb_module_name = + generate_switch_block_module_name(module_sb_coordinate); + ModuleId sb_module_id = module_manager.find_module(sb_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(sb_module_id)); + + /* Connect grid output pins (OPIN) to switch block grid pins */ + for (size_t side = 0; side < module_sb.get_num_sides(); ++side) { + SideManager side_manager(side); + /* Iterate over the routing tracks on this side */ + /* Early skip: if there is no routing tracks at this side */ + if (0 == module_sb.get_chan_width(side_manager.get_side())) { + continue; + } + /* Find the Connection Block module */ + /* We find the original connection block and then spot its unique mirror! + * Do NOT use module_sb here!!! + */ + t_rr_type cb_type = + find_top_module_cb_type_by_sb_side(side_manager.get_side()); + vtr::Point instance_gsb_cb_coordinate = + find_top_module_gsb_coordinate_by_sb_side(rr_gsb, + side_manager.get_side()); + vtr::Point module_gsb_cb_coordinate = + find_top_module_gsb_coordinate_by_sb_side(rr_gsb, + side_manager.get_side()); + + /* Skip those Connection blocks that do not exist: + * 1. The CB does not exist in the device level! We should skip! + * 2. The CB does exist but we need to make sure if the GSB includes such + * CBs For TOP and LEFT side, check the existence using RRGSB method + * is_cb_exist() FOr RIGHT and BOTTOM side, find the adjacent RRGSB and then + * use is_cb_exist() + */ + if (TOP == side_manager.get_side() || LEFT == side_manager.get_side()) { + if (false == rr_gsb.is_cb_exist(cb_type)) { + continue; + } + } + + if (RIGHT == side_manager.get_side() || BOTTOM == side_manager.get_side()) { + const RRGSB& adjacent_gsb = + device_rr_gsb.get_gsb(module_gsb_cb_coordinate); + if (false == adjacent_gsb.is_cb_exist(cb_type)) { + continue; + } + } + + /* If we use compact routing hierarchy, we should find the unique module of + * CB, which is added to the top module */ + if (true == compact_routing_hierarchy) { + const RRGSB& unique_mirror = + device_rr_gsb.get_cb_unique_module(cb_type, module_gsb_cb_coordinate); + module_gsb_cb_coordinate.set_x(unique_mirror.get_x()); + module_gsb_cb_coordinate.set_y(unique_mirror.get_y()); + } + + const RRGSB& instance_cb = + device_rr_gsb.get_gsb(instance_gsb_cb_coordinate); + vtr::Point instance_cb_coordinate(instance_cb.get_cb_x(cb_type), + instance_cb.get_cb_y(cb_type)); + + /* Check if the grid is inside the tile, if not, create ports */ + if (fabric_tile.cb_in_tile(curr_fabric_tile_id, cb_type, + instance_gsb_cb_coordinate)) { + continue; + } + /* Collect cb tile information */ + FabricTileId cb_tile = fabric_tile.find_tile_by_cb_coordinate( + cb_type, instance_gsb_cb_coordinate); + vtr::Point cb_tile_coord = fabric_tile.tile_coordinate(cb_tile); + size_t cb_idx_in_cb_tile = fabric_tile.find_cb_index_in_tile( + cb_tile, cb_type, instance_gsb_cb_coordinate); + FabricTileId cb_unique_tile = fabric_tile.unique_tile(cb_tile_coord); + vtr::Point cb_unique_tile_coord = + fabric_tile.tile_coordinate(cb_unique_tile); + vtr::Point cb_coord_in_cb_unique_tile = + fabric_tile.cb_coordinates(cb_unique_tile, cb_type)[cb_idx_in_cb_tile]; + const RRGSB& unique_cb_rr_gsb = + device_rr_gsb.get_gsb(cb_coord_in_cb_unique_tile); + std::string cb_instance_name_in_unique_tile = + generate_connection_block_module_name( + cb_type, unique_cb_rr_gsb.get_cb_coordinate(cb_type)); + std::string cb_tile_module_name = + generate_tile_module_name(cb_unique_tile_coord); + ModuleId cb_tile_module = module_manager.find_module(cb_tile_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(cb_tile_module)); + size_t cb_tile_instance = + tile_instance_ids[cb_tile_coord.x()][cb_tile_coord.y()]; + + /* Create nets */ + for (size_t itrack = 0; + itrack < module_sb.get_chan_width(side_manager.get_side()); ++itrack) { + std::string sb_port_name = generate_sb_module_track_port_name( + rr_graph.node_type( + module_sb.get_chan_node(side_manager.get_side(), itrack)), + side_manager.get_side(), + module_sb.get_chan_node_direction(side_manager.get_side(), itrack)); + /* Prepare SB-related port information */ + std::string sb_tile_sb_port_name = generate_tile_module_port_name( + sb_instance_name_in_unique_tile, sb_port_name); + ModulePortId sb_port_id = + module_manager.find_module_port(tile_module, sb_tile_sb_port_name); + VTR_ASSERT(true == + module_manager.valid_module_port_id(tile_module, sb_port_id)); + BasicPort sb_port = module_manager.module_port(tile_module, sb_port_id); + + /* Prepare CB-related port information */ + PORTS cb_port_direction = OUT_PORT; + /* The cb port direction should be opposite to the sb port !!! */ + if (OUT_PORT == + module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { + cb_port_direction = IN_PORT; + } else { + VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction( + side_manager.get_side(), itrack)); + } + + /* Upper CB port is required if the routing tracks are on the top or + * right sides of the switch block, which indicated bottom and left + * sides of the connection blocks + */ + bool use_cb_upper_port = + (TOP == side_manager.get_side()) || (RIGHT == side_manager.get_side()); + std::string cb_port_name = generate_cb_module_track_port_name( + cb_type, cb_port_direction, use_cb_upper_port); + std::string cb_tile_cb_port_name = generate_tile_module_port_name( + cb_instance_name_in_unique_tile, cb_port_name); + VTR_LOGV( + verbose, "Finding port '%s' from connection block in tile [%lu][%lu]\n", + cb_tile_cb_port_name.c_str(), cb_tile_coord.x(), cb_tile_coord.y()); + ModulePortId cb_port_id = + module_manager.find_module_port(cb_tile_module, cb_tile_cb_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(cb_tile_module, + cb_port_id)); + BasicPort cb_port = + module_manager.module_port(cb_tile_module, cb_port_id); + + /* Configure the net source and sink: + * If sb port is an output (source), cb port is an input (sink) + * If sb port is an input (sink), cb port is an output (source) + */ + if (OUT_PORT == + module_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, tile_module, tile_instance_id, sb_port_id, + itrack / 2); + module_manager.add_module_net_sink(top_module, net, cb_tile_module, + cb_tile_instance, cb_port_id, + itrack / 2); + } else { + VTR_ASSERT(IN_PORT == module_sb.get_chan_node_direction( + side_manager.get_side(), itrack)); + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, cb_tile_module, cb_tile_instance, + cb_port_id, itrack / 2); + module_manager.add_module_net_sink(top_module, net, tile_module, + tile_instance_id, sb_port_id, + itrack / 2); + } + VTR_LOGV(verbose, + "Built nets between switch block of tile[%lu][%lu] and " + "connection block of tile[%lu][%lu]\n", + sb_tile_coord.x(), sb_tile_coord.y(), cb_tile_coord.x(), + cb_tile_coord.y()); + } + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Add module nets to connect the pins between tiles + * To make it easy, this function will iterate over all the tiles, through which + *we can obtain the coordinates of each programmable block (PB), connection + *block (CB) and switch block (SB). With the coordinates, we can then trace the + *connections between these blocks using the RRGSB data structure. + * + * +--------+ +----------+ + * | Tile |--->| Tile | + * | [x][y] |<---| [x+1][y] | + * +--------+ +----------+ + * + * The inter-tile connections can be categorized into four types: + * - PB-to-SB connections: We use the GSB to find the connections with a given + *SB coordinate. Note that we only care the connections where the driver PB is + *not in this tile. + * - CB-to-PB connections: We use the GSB to find the connections with a given + *CB coordinate. Note that we only care the connections where the sink PB is not + *in this tile. + * - SB-to-CB connections: We use the GSB to find the connections with a given + *SB coordinate. Note that we only care the connections where the sink CB is not + *in this tile. + * - PB-to-PB connections: We use the tile direct data structure to find all the + *connections. Note that we only care the connections where the driver PB is not + *in this tile. + * + *******************************************************************/ +static int add_top_module_nets_around_one_tile( + ModuleManager& module_manager, const ModuleId& top_module, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& tile_instance_ids, + const RRGraphView& rr_graph_view, const DeviceRRGSB& device_rr_gsb, + const FabricTile& fabric_tile, const FabricTileId& curr_fabric_tile_id, + const bool& verbose) { + int status = CMD_EXEC_SUCCESS; + + /* Find the module name for this type of tile */ + vtr::Point unique_tile_coord = + fabric_tile.unique_tile_coordinate(curr_fabric_tile_id); + std::string tile_module_name = generate_tile_module_name(unique_tile_coord); + ModuleId tile_module = module_manager.find_module(tile_module_name); + if (!module_manager.valid_module_id(tile_module)) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Find the instance id for this tile */ + vtr::Point tile_coord = + fabric_tile.tile_coordinate(curr_fabric_tile_id); + size_t tile_instance_id = tile_instance_ids[tile_coord.x()][tile_coord.y()]; + + /* Get the submodule of Switch blocks one by one, build connections between sb + * and pb */ + for (size_t isb = 0; + isb < fabric_tile.sb_coordinates(curr_fabric_tile_id).size(); ++isb) { + vtr::Point sb_coord = + fabric_tile.sb_coordinates(curr_fabric_tile_id)[isb]; + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(sb_coord); + status = build_top_module_tile_nets_between_sb_and_pb( + module_manager, top_module, tile_module, tile_instance_ids, + tile_instance_id, grids, vpr_device_annotation, device_rr_gsb, + rr_graph_view, rr_gsb, fabric_tile, curr_fabric_tile_id, isb, true, + verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + /* Get the submodule of connection blocks one by one, build connections + * between cb and pb */ + for (t_rr_type cb_type : {CHANX, CHANY}) { + for (size_t icb = 0; + icb < fabric_tile.cb_coordinates(curr_fabric_tile_id, cb_type).size(); + ++icb) { + vtr::Point cb_coord = + fabric_tile.cb_coordinates(curr_fabric_tile_id, cb_type)[icb]; + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(cb_coord); + status = build_top_module_tile_nets_between_cb_and_pb( + module_manager, top_module, tile_module, tile_instance_ids, + tile_instance_id, grids, vpr_device_annotation, device_rr_gsb, + rr_graph_view, rr_gsb, fabric_tile, curr_fabric_tile_id, cb_type, icb, + true, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + } + /* Get the submodule of connection blocks one by one, build connections + * between sb and cb */ + for (size_t isb = 0; + isb < fabric_tile.sb_coordinates(curr_fabric_tile_id).size(); ++isb) { + vtr::Point sb_coord = + fabric_tile.sb_coordinates(curr_fabric_tile_id)[isb]; + const RRGSB& rr_gsb = device_rr_gsb.get_gsb(sb_coord); + status = build_top_module_tile_nets_between_sb_and_cb( + module_manager, top_module, tile_module, tile_instance_ids, + tile_instance_id, device_rr_gsb, rr_graph_view, rr_gsb, fabric_tile, + curr_fabric_tile_id, isb, true, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Walk through each tile instance and add module nets to connect the pins + *between tiles + *******************************************************************/ +static int add_top_module_nets_connect_tiles( + ModuleManager& module_manager, const ModuleId& top_module, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& tile_instance_ids, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const FabricTile& fabric_tile, + const bool& verbose) { + vtr::ScopedStartFinishTimer timer("Add module nets between tiles"); + int status = CMD_EXEC_SUCCESS; + + for (size_t ix = 0; ix < grids.width(); ++ix) { + for (size_t iy = 0; iy < grids.height(); ++iy) { + vtr::Point curr_coord(ix, iy); + FabricTileId curr_fabric_tile_id = fabric_tile.find_tile(curr_coord); + if (!fabric_tile.valid_tile_id(curr_fabric_tile_id)) { + continue; + } + status = add_top_module_nets_around_one_tile( + module_manager, top_module, vpr_device_annotation, grids, + tile_instance_ids, rr_graph, device_rr_gsb, fabric_tile, + curr_fabric_tile_id, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + } + + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Organize the memory modules for tiles under the top-level module + * Follow a snake-like sequence + * +-----------------------> Tail + * +<----------------------+ + * | + * ... + * +---------------------->+ + * +<----------------------+ + * head ----------------------->+ + *******************************************************************/ +static void organize_top_module_tile_based_memory_modules( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const CircuitModelId& sram_model, const DeviceGrid& grids, + const vtr::Matrix& tile_instance_ids, const FabricTile& fabric_tile) { + /* Ensure clean vectors to return */ + VTR_ASSERT(true == + module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .empty()); + + std::vector> tile_coords; + bool positive_direction = true; + for (size_t iy = 0; iy < grids.height(); ++iy) { + /* For positive direction: -----> */ + if (true == positive_direction) { + for (size_t ix = 0; ix < grids.width(); ++ix) { + tile_coords.push_back(vtr::Point(ix, iy)); + } + } else { + VTR_ASSERT(false == positive_direction); + /* For negative direction: -----> */ + for (int ix = grids.width() - 1; ix >= 0; --ix) { + tile_coords.push_back(vtr::Point(ix, iy)); + } + } + /* Flip the positive direction to be negative */ + positive_direction = !positive_direction; + } + + for (const vtr::Point& tile_coord : tile_coords) { + FabricTileId curr_fabric_tile_id = fabric_tile.find_tile(tile_coord); + if (!fabric_tile.valid_tile_id(curr_fabric_tile_id)) { + continue; + } + vtr::Point curr_tile_coord = + fabric_tile.tile_coordinate(curr_fabric_tile_id); + vtr::Point unique_tile_coord = + fabric_tile.unique_tile_coordinate(curr_fabric_tile_id); + std::string tile_module_name = generate_tile_module_name(unique_tile_coord); + ModuleId tile_module = module_manager.find_module(tile_module_name); + VTR_ASSERT(module_manager.valid_module_id(tile_module)); + + if (0 < find_module_num_config_bits(module_manager, tile_module, + circuit_lib, sram_model, + config_protocol.type())) { + module_manager.add_configurable_child( + top_module, tile_module, + tile_instance_ids[curr_tile_coord.x()][curr_tile_coord.y()], + ModuleManager::e_config_child_type::UNIFIED, + vtr::Point(curr_tile_coord.x(), curr_tile_coord.y())); + } + } + + /* Split memory modules into different regions */ + build_top_module_configurable_regions(module_manager, top_module, + config_protocol); +} + +/********************************************************************* + * Generate an input port for routing multiplexer inside the tile + * which is the middle output of a routing track + ********************************************************************/ +static ModulePinInfo find_tile_module_chan_port( + const ModuleManager& module_manager, const ModuleId& tile_module, + const vtr::Point& cb_coord_in_tile, const RRGraphView& rr_graph, + const RRGSB& rr_gsb, const t_rr_type& cb_type, const RRNodeId& chan_rr_node) { + ModulePinInfo input_port_info; + /* Generate the input port object */ + switch (rr_graph.node_type(chan_rr_node)) { + case CHANX: + case CHANY: { + /* Create port description for the routing track middle output */ + int chan_node_track_id = + rr_gsb.get_cb_chan_node_index(cb_type, chan_rr_node); + /* Create a port description for the middle output */ + std::string input_port_name = generate_cb_module_track_port_name( + cb_type, IN_PORT, 0 == chan_node_track_id % 2); + std::string tile_input_port_name = generate_tile_module_port_name( + generate_connection_block_module_name(cb_type, cb_coord_in_tile), + input_port_name); + /* Must find a valid port id in the Switch Block module */ + input_port_info.first = + module_manager.find_module_port(tile_module, tile_input_port_name); + input_port_info.second = chan_node_track_id / 2; + VTR_ASSERT(true == module_manager.valid_module_port_id( + tile_module, input_port_info.first)); + break; + } + default: /* OPIN, SOURCE, IPIN, SINK are invalid*/ + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid rr_node type! Should be [OPIN|CHANX|CHANY].\n"); + exit(1); + } + + return input_port_info; +} + +/******************************************************************** + * Add nets between a global port and its sinks at an entry point of clock tree + *******************************************************************/ +static int build_top_module_global_net_from_tile_clock_arch_tree( + ModuleManager& module_manager, const ModuleId& top_module, + const ModulePortId& top_module_port, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, + const vtr::Matrix& tile_instance_ids, const FabricTile& fabric_tile, + const ClockNetwork& clk_ntwk, const std::string& clk_tree_name, + const RRClockSpatialLookup& rr_clock_lookup) { + int status = CMD_EXEC_SUCCESS; + + /* Ensure the clock arch tree name is valid */ + ClockTreeId clk_tree = clk_ntwk.find_tree(clk_tree_name); + if (!clk_ntwk.valid_tree_id(clk_tree)) { + VTR_LOG( + "Fail to find a matched clock tree '%s' in the clock architecture " + "definition", + clk_tree_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + + /* Ensure the clock tree width matches the global port size */ + if (clk_ntwk.tree_width(clk_tree) != + module_manager.module_port(top_module, top_module_port).get_width()) { + VTR_LOG( + "Clock tree '%s' does not have the same width '%lu' as the port '%'s of " + "FPGA top module", + clk_tree_name.c_str(), clk_ntwk.tree_width(clk_tree), + module_manager.module_port(top_module, top_module_port) + .get_name() + .c_str()); + return CMD_EXEC_FATAL_ERROR; + } + + for (ClockTreePinId pin : clk_ntwk.pins(clk_tree)) { + BasicPort src_port = + module_manager.module_port(top_module, top_module_port); + /* Add the module net */ + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, top_module_port, + src_port.pins()[size_t(pin)]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + for (ClockSpineId spine : clk_ntwk.tree_top_spines(clk_tree)) { + vtr::Point entry_point = clk_ntwk.spine_start_point(spine); + Direction entry_dir = clk_ntwk.spine_direction(spine); + t_rr_type entry_track_type = clk_ntwk.spine_track_type(spine); + /* Find the routing resource node of the entry point */ + RRNodeId entry_rr_node = + rr_clock_lookup.find_node(entry_point.x(), entry_point.y(), clk_tree, + clk_ntwk.spine_level(spine), pin, entry_dir); + + /* Get the tile module and instance at the entry point */ + const RRGSB& rr_gsb = device_rr_gsb.get_gsb_by_cb_coordinate( + entry_track_type, vtr::Point(entry_point.x(), entry_point.y())); + vtr::Point cb_coord_in_tile = rr_gsb.get_sb_coordinate(); + FabricTileId curr_fabric_tile_id = fabric_tile.find_tile_by_cb_coordinate( + entry_track_type, cb_coord_in_tile); + vtr::Point curr_fabric_tile_coord = + fabric_tile.tile_coordinate(curr_fabric_tile_id); + FabricTileId unique_fabric_tile_id = + fabric_tile.unique_tile(curr_fabric_tile_coord); + vtr::Point unique_fabric_tile_coord = + fabric_tile.tile_coordinate(unique_fabric_tile_id); + + ModuleId tile_module = module_manager.find_module( + generate_tile_module_name(unique_fabric_tile_coord)); + size_t tile_instance = tile_instance_ids[curr_fabric_tile_coord.x()] + [curr_fabric_tile_coord.y()]; + + /* Find the port name */ + size_t cb_idx_in_curr_fabric_tile = fabric_tile.find_cb_index_in_tile( + curr_fabric_tile_id, entry_track_type, cb_coord_in_tile); + vtr::Point cb_coord_in_unique_fabric_tile = + fabric_tile.cb_coordinates( + unique_fabric_tile_id, entry_track_type)[cb_idx_in_curr_fabric_tile]; + ModulePinInfo des_pin_info = find_tile_module_chan_port( + module_manager, tile_module, cb_coord_in_unique_fabric_tile, rr_graph, + rr_gsb, entry_track_type, entry_rr_node); + + /* Configure the net sink */ + BasicPort sink_port = + module_manager.module_port(tile_module, des_pin_info.first); + module_manager.add_module_net_sink(top_module, net, tile_module, + tile_instance, des_pin_info.first, + sink_port.pins()[des_pin_info.second]); + } + } + + return status; +} + +/******************************************************************** + * Add global port connection for a given port of a physical tile + * that are defined as global in tile annotation + *******************************************************************/ +static int build_top_module_global_net_for_given_tile_module( + ModuleManager& module_manager, const ModuleId& top_module, + const ModulePortId& top_module_port, const TileAnnotation& tile_annotation, + const TileGlobalPortId& tile_global_port, + const BasicPort& tile_port_to_connect, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const size_t& layer, const vtr::Point& grid_coordinate, + const e_side& border_side, const vtr::Matrix& tile_instance_ids, + const FabricTile& fabric_tile) { + /* Get the tile module and instance */ + FabricTileId curr_fabric_tile_id = + fabric_tile.find_tile_by_pb_coordinate(grid_coordinate); + vtr::Point curr_fabric_tile_coord = + fabric_tile.tile_coordinate(curr_fabric_tile_id); + FabricTileId unique_fabric_tile_id = + fabric_tile.unique_tile(curr_fabric_tile_coord); + vtr::Point unique_fabric_tile_coord = + fabric_tile.tile_coordinate(unique_fabric_tile_id); + std::string tile_module_name = + generate_tile_module_name(unique_fabric_tile_coord); + ModuleId tile_module = module_manager.find_module(tile_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(tile_module)); + size_t tile_instance = + tile_instance_ids[curr_fabric_tile_coord.x()][curr_fabric_tile_coord.y()]; + + /* Get the grid coordinate in the context of the tile */ + size_t pb_idx_in_curr_fabric_tile = + fabric_tile.find_pb_index_in_tile(curr_fabric_tile_id, grid_coordinate); + vtr::Point pb_coord_in_unique_fabric_tile = + fabric_tile.pb_coordinates( + unique_fabric_tile_id)[pb_idx_in_curr_fabric_tile]; + + t_physical_tile_type_ptr physical_tile = grids.get_physical_type( + t_physical_tile_loc(grid_coordinate.x(), grid_coordinate.y(), layer)); + /* Find the module name for this type of grid */ + std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); + std::string grid_instance_name = + generate_grid_block_module_name_in_top_module( + grid_module_name_prefix, grids, pb_coord_in_unique_fabric_tile); + /* Find the source port at the top-level module */ + BasicPort src_port = module_manager.module_port(top_module, top_module_port); + + /* Walk through each instance considering the unique sub tile and capacity + * range, each instance may have an independent pin to be driven by a global + * net! */ + for (const t_sub_tile& sub_tile : physical_tile->sub_tiles) { + VTR_ASSERT(1 == sub_tile.equivalent_sites.size()); + int grid_pin_start_index = physical_tile->num_pins; + t_physical_tile_port physical_tile_port; + physical_tile_port.num_pins = 0; + + /* Count the total number of pins for this type of sub tile */ + int sub_tile_num_pins = sub_tile.num_phy_pins / sub_tile.capacity.total(); + + /* For each instance of the same sub tile type, find the port of the grid + * module according to the tile annotation A tile may consist of multiple + * subtile, connect to all the pins from sub tiles */ + for (int subtile_index = sub_tile.capacity.low; + subtile_index <= sub_tile.capacity.high; subtile_index++) { + for (const t_physical_tile_port& tile_port : sub_tile.ports) { + if (std::string(tile_port.name) == tile_port_to_connect.get_name()) { + BasicPort ref_tile_port(tile_port.name, tile_port.num_pins); + /* Port size must match!!! */ + if (false == ref_tile_port.contained(tile_port_to_connect)) { + VTR_LOG_ERROR( + "Tile annotation '%s' port '%s[%lu:%lu]' is out of the range of " + "physical tile port '%s[%lu:%lu]'!", + tile_annotation.global_port_name(tile_global_port).c_str(), + tile_port_to_connect.get_name().c_str(), + tile_port_to_connect.get_lsb(), tile_port_to_connect.get_msb(), + ref_tile_port.get_name().c_str(), ref_tile_port.get_lsb(), + ref_tile_port.get_msb()); + return CMD_EXEC_FATAL_ERROR; + } + grid_pin_start_index = + sub_tile.sub_tile_to_tile_pin_indices + [(subtile_index - sub_tile.capacity.low) * sub_tile_num_pins + + tile_port.absolute_first_pin_index]; + physical_tile_port = tile_port; + break; + } + } + /* Ensure the pin index is valid */ + VTR_ASSERT(grid_pin_start_index < physical_tile->num_pins); + /* Ensure port width is in range */ + VTR_ASSERT(src_port.get_width() == tile_port_to_connect.get_width()); + + /* Create a pin id mapping between the source port (top module) and the + * sink port (grid module) */ + std::map sink2src_pin_map; + for (size_t ipin = 0; ipin < tile_port_to_connect.get_width(); ++ipin) { + size_t sink_pin = tile_port_to_connect.pins()[ipin]; + size_t src_pin = src_port.pins()[ipin]; + sink2src_pin_map[sink_pin] = src_pin; + } + + /* Create the connections */ + for (size_t pin_id = tile_port_to_connect.get_lsb(); + pin_id < tile_port_to_connect.get_msb() + 1; ++pin_id) { + int grid_pin_index = grid_pin_start_index + pin_id; + /* Find the module pin */ + size_t grid_pin_width = physical_tile->pin_width_offset[grid_pin_index]; + size_t grid_pin_height = + physical_tile->pin_height_offset[grid_pin_index]; + std::vector pin_sides = find_physical_tile_pin_side( + physical_tile, grid_pin_index, border_side); + + BasicPort grid_pin_info = + vpr_device_annotation.physical_tile_pin_port_info(physical_tile, + grid_pin_index); + VTR_ASSERT(true == grid_pin_info.is_valid()); + + /* Build nets */ + for (const e_side& pin_side : pin_sides) { + std::string grid_port_name = + generate_grid_port_name(grid_pin_width, grid_pin_height, + subtile_index, pin_side, grid_pin_info); + std::string tile_grid_port_name = + generate_tile_module_port_name(grid_instance_name, grid_port_name); + ModulePortId tile_grid_port_id = + module_manager.find_module_port(tile_module, tile_grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id( + tile_module, tile_grid_port_id)); + + VTR_ASSERT(1 == + module_manager.module_port(tile_module, tile_grid_port_id) + .get_width()); + + ModuleNetId net = create_module_source_pin_net( + module_manager, top_module, top_module, 0, top_module_port, + src_port.pins()[sink2src_pin_map[pin_id]]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Configure the net sink */ + BasicPort sink_port = + module_manager.module_port(tile_module, tile_grid_port_id); + module_manager.add_module_net_sink(top_module, net, tile_module, + tile_instance, tile_grid_port_id, + sink_port.pins()[0]); + } + } + } + } + + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Add nets between a global port and its sinks at each tile modules + *******************************************************************/ +static int build_top_module_global_net_from_tile_modules( + ModuleManager& module_manager, const ModuleId& top_module, + const ModulePortId& top_module_port, const TileAnnotation& tile_annotation, + const TileGlobalPortId& tile_global_port, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const size_t& layer, const vtr::Matrix& tile_instance_ids, + const FabricTile& fabric_tile) { + int status = CMD_EXEC_SUCCESS; + + std::map>> io_coordinates = + generate_perimeter_grid_coordinates(grids); + + for (size_t tile_info_id = 0; + tile_info_id < + tile_annotation.global_port_tile_names(tile_global_port).size(); + ++tile_info_id) { + std::string tile_name = + tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id]; + BasicPort tile_port = + tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id]; + /* Find the coordinates for the wanted tiles */ + vtr::Point start_coord(1, 1); + vtr::Point end_coord(grids.width() - 1, grids.height() - 1); + vtr::Point range = tile_annotation.global_port_tile_coordinates( + tile_global_port)[tile_info_id]; + bool out_of_range = false; + + /* -1 means all the x should be considered */ + if (size_t(-1) != range.x()) { + if ((range.x() < start_coord.x()) || (range.x() > end_coord.x())) { + out_of_range = true; + } else { + /* Set the range */ + start_coord.set_x(range.x()); + end_coord.set_x(range.x()); + } + } + + /* -1 means all the y should be considered */ + if (size_t(-1) != range.y()) { + if ((range.y() < start_coord.y()) || (range.y() > end_coord.y())) { + out_of_range = true; + } else { + /* Set the range */ + start_coord.set_y(range.y()); + end_coord.set_y(range.y()); + } + } + + /* Error out immediately if the coordinate is not valid! */ + if (true == out_of_range) { + VTR_LOG_ERROR( + "Coordinate (%lu, %lu) in tile annotation for tile '%s' is out of " + "range (%lu:%lu, %lu:%lu)!", + range.x(), range.y(), tile_name.c_str(), start_coord.x(), end_coord.x(), + start_coord.y(), end_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + + /* Spot the port from child modules from core grids */ + for (size_t ix = start_coord.x(); ix < end_coord.x(); ++ix) { + for (size_t iy = start_coord.y(); iy < end_coord.y(); ++iy) { + t_physical_tile_loc phy_tile_loc(ix, iy, layer); + t_physical_tile_type_ptr phy_tile_type = + grids.get_physical_type(phy_tile_loc); + /* Bypass EMPTY tiles */ + if (true == is_empty_type(phy_tile_type)) { + continue; + } + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { + continue; + } + + /* Bypass the tiles whose names do not match */ + if (std::string(phy_tile_type->name) != tile_name) { + continue; + } + + /* Create nets and finish connection build-up */ + status = build_top_module_global_net_for_given_tile_module( + module_manager, top_module, top_module_port, tile_annotation, + tile_global_port, tile_port, vpr_device_annotation, grids, layer, + vtr::Point(ix, iy), NUM_SIDES, tile_instance_ids, + fabric_tile); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + } + } + + /* Walk through all the grids on the perimeter, which are I/O grids */ + for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { + for (const vtr::Point& io_coordinate : io_coordinates[io_side]) { + t_physical_tile_loc phy_tile_loc(io_coordinate.x(), io_coordinate.y(), + layer); + t_physical_tile_type_ptr phy_tile_type = + grids.get_physical_type(phy_tile_loc); + /* Bypass EMPTY grid */ + if (true == is_empty_type(phy_tile_type)) { + continue; + } + + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { + continue; + } + + /* Bypass the tiles whose names do not match */ + if (std::string(phy_tile_type->name) != tile_name) { + continue; + } + + /* Check if the coordinate satisfy the tile coordinate defintion + * - Bypass if the x is a specific number (!= -1), and io_coordinate + * is different + * - Bypass if the y is a specific number (!= -1), and io_coordinate + * is different + */ + if ((size_t(-1) != range.x()) && (range.x() != io_coordinate.x())) { + continue; + } + if ((size_t(-1) != range.y()) && (range.y() != io_coordinate.y())) { + continue; + } + + /* Create nets and finish connection build-up */ + status = build_top_module_global_net_for_given_tile_module( + module_manager, top_module, top_module_port, tile_annotation, + tile_global_port, tile_port, vpr_device_annotation, grids, layer, + io_coordinate, io_side, tile_instance_ids, fabric_tile); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + } + } + } + + return status; +} + +/******************************************************************** + * Add global ports from tile ports that are defined as global in tile + *annotation + *******************************************************************/ +static int add_top_module_global_ports_from_tile_modules( + ModuleManager& module_manager, const ModuleId& top_module, + const TileAnnotation& tile_annotation, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const size_t& layer, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, + const vtr::Matrix& tile_instance_ids, const FabricTile& fabric_tile, + const ClockNetwork& clk_ntwk, const RRClockSpatialLookup& rr_clock_lookup) { + int status = CMD_EXEC_SUCCESS; + + /* Add the global ports which are NOT yet added to the top-level module + * (in different names than the global ports defined in circuit library + */ + std::vector global_ports_to_add; + for (const TileGlobalPortId& tile_global_port : + tile_annotation.global_ports()) { + ModulePortId module_port = module_manager.find_module_port( + top_module, tile_annotation.global_port_name(tile_global_port)); + /* The global port size is derived from the maximum port size among all the + * tile port defintion */ + if (ModulePortId::INVALID() == module_port) { + BasicPort global_port_to_add; + global_port_to_add.set_name( + tile_annotation.global_port_name(tile_global_port)); + size_t max_port_size = 0; + for (const BasicPort& tile_port : + tile_annotation.global_port_tile_ports(tile_global_port)) { + max_port_size = std::max(tile_port.get_width(), max_port_size); + } + global_port_to_add.set_width(max_port_size); + global_ports_to_add.push_back(global_port_to_add); + } + } + + for (const BasicPort& global_port_to_add : global_ports_to_add) { + module_manager.add_port(top_module, global_port_to_add, + ModuleManager::MODULE_GLOBAL_PORT); + } + + /* Add module nets */ + for (const TileGlobalPortId& tile_global_port : + tile_annotation.global_ports()) { + /* Must found one valid port! */ + ModulePortId top_module_port = module_manager.find_module_port( + top_module, tile_annotation.global_port_name(tile_global_port)); + VTR_ASSERT(ModulePortId::INVALID() != top_module_port); + + /* There are two cases when building the nets: + * - If the net will go through a dedicated clock tree network, the net will + * drive an input of a routing block + * - If the net will be directly wired to tiles, the net will drive an input + * of a tile + */ + if (!tile_annotation.global_port_clock_arch_tree_name(tile_global_port) + .empty()) { + status = build_top_module_global_net_from_tile_clock_arch_tree( + module_manager, top_module, top_module_port, rr_graph, device_rr_gsb, + tile_instance_ids, fabric_tile, clk_ntwk, + tile_annotation.global_port_clock_arch_tree_name(tile_global_port), + rr_clock_lookup); + } else { + status = build_top_module_global_net_from_tile_modules( + module_manager, top_module, top_module_port, tile_annotation, + tile_global_port, vpr_device_annotation, grids, layer, + tile_instance_ids, fabric_tile); + } + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } + } + return status; +} + +/******************************************************************** + * Add module net for one direction connection between two CLBs or + * two grids + * This function will + * 1. find the pin id and port id of the source clb port in module manager + * 2. find the pin id and port id of the destination clb port in module manager + * 3. add a direct connection module to the top module + * 4. add a first module net and configure its source and sink, + * in order to connect the source pin to the input of the top module + * 4. add a second module net and configure its source and sink, + * in order to connect the sink pin to the output of the top module + *******************************************************************/ +static void add_module_nets_connect_tile_direct_connection( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const size_t& layer, const vtr::Matrix& tile_instance_ids, + const FabricTile& fabric_tile, const TileDirect& tile_direct, + const TileDirectId& tile_direct_id, const ArchDirect& arch_direct) { + vtr::Point device_size(grids.width(), grids.height()); + std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); + + /* Find the module name of source clb */ + vtr::Point src_clb_coord = + tile_direct.from_tile_coordinate(tile_direct_id); + FabricTileId src_tile_id = + fabric_tile.find_tile_by_pb_coordinate(src_clb_coord); + vtr::Point src_tile_coord = fabric_tile.tile_coordinate(src_tile_id); + FabricTileId src_unique_tile_id = fabric_tile.unique_tile(src_tile_coord); + vtr::Point src_unique_tile_coord = + fabric_tile.tile_coordinate(src_unique_tile_id); + std::string src_module_name = + generate_tile_module_name(src_unique_tile_coord); + ModuleId src_tile_module = module_manager.find_module(src_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(src_tile_module)); + /* Record the instance id */ + size_t src_tile_instance = + tile_instance_ids[src_tile_coord.x()][src_tile_coord.y()]; + /* Grid instance name in the unique tile */ + size_t pb_idx_in_src_tile = + fabric_tile.find_pb_index_in_tile(src_tile_id, src_clb_coord); + vtr::Point pb_coord_in_unique_src_tile = + fabric_tile.pb_coordinates(src_unique_tile_id)[pb_idx_in_src_tile]; + std::string src_grid_instance_name = + generate_grid_block_module_name_in_top_module( + grid_module_name_prefix, grids, pb_coord_in_unique_src_tile); + + /* Find the module name of sink clb */ + vtr::Point des_clb_coord = + tile_direct.to_tile_coordinate(tile_direct_id); + FabricTileId des_tile_id = + fabric_tile.find_tile_by_pb_coordinate(des_clb_coord); + vtr::Point des_tile_coord = fabric_tile.tile_coordinate(des_tile_id); + FabricTileId des_unique_tile_id = fabric_tile.unique_tile(des_tile_coord); + vtr::Point des_unique_tile_coord = + fabric_tile.tile_coordinate(des_unique_tile_id); + std::string des_module_name = + generate_tile_module_name(des_unique_tile_coord); + ModuleId des_tile_module = module_manager.find_module(des_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(des_tile_module)); + /* Record the instance id */ + size_t des_tile_instance = + tile_instance_ids[des_tile_coord.x()][des_tile_coord.y()]; + /* Grid instance name in the unique tile */ + size_t pb_idx_in_des_tile = + fabric_tile.find_pb_index_in_tile(des_tile_id, des_clb_coord); + vtr::Point pb_coord_in_unique_des_tile = + fabric_tile.pb_coordinates(des_unique_tile_id)[pb_idx_in_des_tile]; + std::string des_grid_instance_name = + generate_grid_block_module_name_in_top_module( + grid_module_name_prefix, grids, pb_coord_in_unique_des_tile); + + /* Find the module id of a direct connection module */ + CircuitModelId direct_circuit_model = + arch_direct.circuit_model(tile_direct.arch_direct(tile_direct_id)); + std::string direct_module_name = circuit_lib.model_name(direct_circuit_model); + ModuleId direct_module = module_manager.find_module(direct_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(direct_module)); + + /* Find inputs and outputs of the direct circuit module */ + std::vector direct_input_ports = + circuit_lib.model_ports_by_type(direct_circuit_model, + CIRCUIT_MODEL_PORT_INPUT, true); + VTR_ASSERT(1 == direct_input_ports.size()); + ModulePortId direct_input_port_id = module_manager.find_module_port( + direct_module, circuit_lib.port_prefix(direct_input_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id(direct_module, + direct_input_port_id)); + VTR_ASSERT(1 == + module_manager.module_port(direct_module, direct_input_port_id) + .get_width()); + + std::vector direct_output_ports = + circuit_lib.model_ports_by_type(direct_circuit_model, + CIRCUIT_MODEL_PORT_OUTPUT, true); + VTR_ASSERT(1 == direct_output_ports.size()); + ModulePortId direct_output_port_id = module_manager.find_module_port( + direct_module, circuit_lib.port_prefix(direct_output_ports[0])); + VTR_ASSERT(true == module_manager.valid_module_port_id( + direct_module, direct_output_port_id)); + VTR_ASSERT(1 == + module_manager.module_port(direct_module, direct_output_port_id) + .get_width()); + + /* Generate the pin name of source port/pin in the grid */ + e_side src_pin_grid_side = tile_direct.from_tile_side(tile_direct_id); + size_t src_tile_pin = tile_direct.from_tile_pin(tile_direct_id); + + t_physical_tile_loc src_tile_loc(src_clb_coord.x(), src_clb_coord.y(), layer); + t_physical_tile_type_ptr src_grid_type_descriptor = + grids.get_physical_type(src_tile_loc); + size_t src_pin_width = + src_grid_type_descriptor->pin_width_offset[src_tile_pin]; + size_t src_pin_height = + src_grid_type_descriptor->pin_height_offset[src_tile_pin]; + + BasicPort src_pin_info = vpr_device_annotation.physical_tile_pin_port_info( + src_grid_type_descriptor, src_tile_pin); + VTR_ASSERT(true == src_pin_info.is_valid()); + int src_subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + src_grid_type_descriptor, src_tile_pin); + VTR_ASSERT(OPEN != src_subtile_index && + src_subtile_index < src_grid_type_descriptor->capacity); + std::string src_port_name = + generate_grid_port_name(src_pin_width, src_pin_height, src_subtile_index, + src_pin_grid_side, src_pin_info); + src_port_name = + generate_tile_module_port_name(src_grid_instance_name, src_port_name); + ModulePortId src_port_id = + module_manager.find_module_port(src_tile_module, src_port_name); + if (true != + module_manager.valid_module_port_id(src_tile_module, src_port_id)) { + VTR_LOG_ERROR("Fail to find port '%s[%lu][%lu].%s'\n", + src_module_name.c_str(), src_tile_coord.x(), + src_tile_coord.y(), src_port_name.c_str()); + } + VTR_ASSERT(true == + module_manager.valid_module_port_id(src_tile_module, src_port_id)); + VTR_ASSERT( + 1 == module_manager.module_port(src_tile_module, src_port_id).get_width()); + + /* Generate the pin name of sink port/pin in the grid */ + e_side sink_pin_grid_side = tile_direct.to_tile_side(tile_direct_id); + size_t sink_tile_pin = tile_direct.to_tile_pin(tile_direct_id); + + t_physical_tile_loc des_tile_loc(des_clb_coord.x(), des_clb_coord.y(), layer); + t_physical_tile_type_ptr sink_grid_type_descriptor = + grids.get_physical_type(des_tile_loc); + size_t sink_pin_width = + sink_grid_type_descriptor->pin_width_offset[src_tile_pin]; + size_t sink_pin_height = + sink_grid_type_descriptor->pin_height_offset[src_tile_pin]; + + BasicPort sink_pin_info = vpr_device_annotation.physical_tile_pin_port_info( + sink_grid_type_descriptor, sink_tile_pin); + VTR_ASSERT(true == sink_pin_info.is_valid()); + int sink_subtile_index = + vpr_device_annotation.physical_tile_pin_subtile_index( + sink_grid_type_descriptor, sink_tile_pin); + VTR_ASSERT(OPEN != src_subtile_index && + src_subtile_index < sink_grid_type_descriptor->capacity); + std::string sink_port_name = + generate_grid_port_name(sink_pin_width, sink_pin_height, sink_subtile_index, + sink_pin_grid_side, sink_pin_info); + sink_port_name = + generate_tile_module_port_name(des_grid_instance_name, sink_port_name); + ModulePortId sink_port_id = + module_manager.find_module_port(des_tile_module, sink_port_name); + VTR_ASSERT( + true == module_manager.valid_module_port_id(des_tile_module, sink_port_id)); + VTR_ASSERT( + 1 == module_manager.module_port(des_tile_module, sink_port_id).get_width()); + + /* Add a submodule of direct connection module to the top-level module */ + size_t direct_instance_id = + module_manager.num_instance(top_module, direct_module); + module_manager.add_child_module(top_module, direct_module, false); + + /* Create the 1st module net */ + ModuleNetId net_direct_src = module_manager.create_module_net(top_module); + /* Connect the wire between src_pin of clb and direct_instance input*/ + module_manager.add_module_net_source(top_module, net_direct_src, + src_tile_module, src_tile_instance, + src_port_id, 0); + module_manager.add_module_net_sink(top_module, net_direct_src, direct_module, + direct_instance_id, direct_input_port_id, + 0); + + /* Create the 2nd module net + * Connect the wire between direct_instance output and sink_pin of clb + */ + ModuleNetId net_direct_sink = + create_module_source_pin_net(module_manager, top_module, direct_module, + direct_instance_id, direct_output_port_id, 0); + module_manager.add_module_net_sink(top_module, net_direct_sink, + des_tile_module, des_tile_instance, + sink_port_id, 0); +} + +/******************************************************************** + * Add module net of clb-to-clb direct connections to module manager + * Note that the direct connections are not limited to CLBs only. + * It can be more generic and thus cover all the grid types, + * such as heterogeneous blocks + *******************************************************************/ +static void add_top_module_nets_connect_tile_direct_connections( + ModuleManager& module_manager, const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const size_t& layer, const vtr::Matrix& tile_instance_ids, + const FabricTile& fabric_tile, const TileDirect& tile_direct, + const ArchDirect& arch_direct) { + vtr::ScopedStartFinishTimer timer( + "Add module nets for inter-tile connections"); + + for (const TileDirectId& tile_direct_id : tile_direct.directs()) { + add_module_nets_connect_tile_direct_connection( + module_manager, top_module, circuit_lib, vpr_device_annotation, grids, + layer, tile_instance_ids, fabric_tile, tile_direct, tile_direct_id, + arch_direct); + } +} + +/******************************************************************** + * Add the tile-level instances to the top module of FPGA fabric + * and build connects between them + *******************************************************************/ +int build_top_module_tile_child_instances( + ModuleManager& module_manager, const ModuleId& top_module, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const CircuitLibrary& circuit_lib, const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& rr_clock_lookup, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const size_t& layer, const TileAnnotation& tile_annotation, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const TileDirect& tile_direct, const ArchDirect& arch_direct, + const FabricTile& fabric_tile, const ConfigProtocol& config_protocol, + const CircuitModelId& sram_model, const FabricKey& fabric_key, + const bool& group_config_block, const bool& frame_view, const bool& verbose) { + int status = CMD_EXEC_SUCCESS; + vtr::Matrix tile_instance_ids; + status = add_top_module_tile_instances(module_manager, top_module, + tile_instance_ids, grids, fabric_tile); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Update the I/O children list */ + add_top_module_tile_io_children(module_manager, top_module, grids, + fabric_tile, tile_instance_ids); + + /* Build the nets between tiles */ + if (false == frame_view) { + /* Reserve nets to be memory efficient */ + reserve_module_manager_module_nets(module_manager, top_module); + /* Regular nets between tiles */ + status = add_top_module_nets_connect_tiles( + module_manager, top_module, vpr_device_annotation, grids, + tile_instance_ids, rr_graph, device_rr_gsb, fabric_tile, verbose); + if (status != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + /* TODO: Inter-tile direct connections */ + add_top_module_nets_connect_tile_direct_connections( + module_manager, top_module, circuit_lib, vpr_device_annotation, grids, + layer, tile_instance_ids, fabric_tile, tile_direct, arch_direct); + } + + /* Add global ports from tile modules: how to connect to clock architecture + * and the global port from tile annotation + */ + status = add_top_module_global_ports_from_tile_modules( + module_manager, top_module, tile_annotation, vpr_device_annotation, grids, + layer, rr_graph, device_rr_gsb, tile_instance_ids, fabric_tile, clk_ntwk, + rr_clock_lookup); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + + /* Add GPIO ports from the sub-modules under this Verilog module + * For top-level module, we follow a special sequencing for I/O modules. So we + * rebuild the I/O children list here + */ + add_module_gpio_ports_from_child_modules(module_manager, top_module); + + /* Organize the list of memory modules and instances + * If we have an empty fabric key, we organize the memory modules as routine + * Otherwise, we will load the fabric key directly + */ + if (true == fabric_key.empty()) { + organize_top_module_tile_based_memory_modules( + module_manager, top_module, circuit_lib, config_protocol, sram_model, + grids, tile_instance_ids, fabric_tile); + } else { + VTR_ASSERT_SAFE(false == fabric_key.empty()); + /* Throw a fatal error when the fabric key has a mismatch in region + * organization. between architecture file and fabric key + */ + if (size_t(config_protocol.num_regions()) != fabric_key.regions().size()) { + VTR_LOG_ERROR( + "Fabric key has a different number of configurable regions (='%ld') " + "than architecture definition (=%d)!\n", + fabric_key.regions().size(), config_protocol.num_regions()); + return CMD_EXEC_FATAL_ERROR; + } + + status = load_top_module_memory_modules_from_fabric_key( + module_manager, top_module, circuit_lib, config_protocol, fabric_key); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + + status = load_top_module_shift_register_banks_from_fabric_key( + fabric_key, blwl_sr_banks); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + + /* Update the memory organization in sub module (non-top) */ + status = load_submodules_memory_modules_from_fabric_key( + module_manager, circuit_lib, config_protocol, fabric_key, + group_config_block); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + } + + return CMD_EXEC_SUCCESS; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_child_tile_instance.h b/openfpga/src/fabric/build_top_module_child_tile_instance.h new file mode 100644 index 000000000..57d3604e4 --- /dev/null +++ b/openfpga/src/fabric/build_top_module_child_tile_instance.h @@ -0,0 +1,50 @@ +#ifndef BUILD_TOP_MODULE_CHILD_TILE_INSTANCE_H +#define BUILD_TOP_MODULE_CHILD_TILE_INSTANCE_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ + +#include + +#include "arch_direct.h" +#include "circuit_library.h" +#include "clock_network.h" +#include "config_protocol.h" +#include "decoder_library.h" +#include "device_grid.h" +#include "device_rr_gsb.h" +#include "fabric_key.h" +#include "fabric_tile.h" +#include "memory_bank_shift_register_banks.h" +#include "module_manager.h" +#include "rr_clock_spatial_lookup.h" +#include "rr_graph_view.h" +#include "tile_annotation.h" +#include "tile_direct.h" +#include "vpr_device_annotation.h" +#include "vtr_geometry.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int build_top_module_tile_child_instances( + ModuleManager& module_manager, const ModuleId& top_module, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const CircuitLibrary& circuit_lib, const ClockNetwork& clk_ntwk, + const RRClockSpatialLookup& rr_clock_lookup, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const size_t& layer, const TileAnnotation& tile_annotation, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const TileDirect& tile_direct, const ArchDirect& arch_direct, + const FabricTile& fabric_tile, const ConfigProtocol& config_protocol, + const CircuitModelId& sram_model, const FabricKey& fabric_key, + const bool& group_config_block, const bool& frame_view, const bool& verbose); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index d2284d318..d49a6f1cf 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -64,12 +64,12 @@ namespace openfpga { static void add_top_module_nets_connect_grids_and_sb( ModuleManager& module_manager, const ModuleId& top_module, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, - const vtr::Matrix& sb_instance_ids, + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const RRGSB& rr_gsb, const vtr::Matrix& sb_instance_ids, const bool& compact_routing_hierarchy) { /* Skip those Switch blocks that do not exist */ - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { return; } @@ -126,8 +126,8 @@ static void add_top_module_nets_connect_grids_and_sb( size_t src_grid_pin_index = rr_graph.node_pin_num( rr_gsb.get_opin_node(side_manager.get_side(), inode)); - t_physical_tile_type_ptr grid_type_descriptor = - grids[grid_coordinate.x()][grid_coordinate.y()].type; + t_physical_tile_type_ptr grid_type_descriptor = grids.get_physical_type( + t_physical_tile_loc(grid_coordinate.x(), grid_coordinate.y(), layer)); size_t src_grid_pin_width = grid_type_descriptor->pin_width_offset[src_grid_pin_index]; size_t src_grid_pin_height = @@ -227,12 +227,12 @@ static void add_top_module_nets_connect_grids_and_sb( static void add_top_module_nets_connect_grids_and_sb_with_duplicated_pins( ModuleManager& module_manager, const ModuleId& top_module, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, - const vtr::Matrix& sb_instance_ids, + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const RRGSB& rr_gsb, const vtr::Matrix& sb_instance_ids, const bool& compact_routing_hierarchy) { /* Skip those Switch blocks that do not exist */ - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { return; } @@ -300,8 +300,10 @@ static void add_top_module_nets_connect_grids_and_sb_with_duplicated_pins( size_t src_grid_pin_index = rr_graph.node_pin_num( rr_gsb.get_opin_node(side_manager.get_side(), inode)); + t_physical_tile_loc phy_tile_loc(grid_coordinate.x(), grid_coordinate.y(), + layer); t_physical_tile_type_ptr grid_type_descriptor = - grids[grid_coordinate.x()][grid_coordinate.y()].type; + grids.get_physical_type(phy_tile_loc); size_t src_grid_pin_width = grid_type_descriptor->pin_width_offset[src_grid_pin_index]; size_t src_grid_pin_height = @@ -437,9 +439,10 @@ static void add_top_module_nets_connect_grids_and_sb_with_duplicated_pins( static void add_top_module_nets_connect_grids_and_cb( ModuleManager& module_manager, const ModuleId& top_module, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, const RRGSB& rr_gsb, - const t_rr_type& cb_type, const vtr::Matrix& cb_instance_ids, + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const RRGSB& rr_gsb, const t_rr_type& cb_type, + const vtr::Matrix& cb_instance_ids, const bool& compact_routing_hierarchy) { /* We could have two different coordinators, one is the instance, the other is * the module */ @@ -519,8 +522,8 @@ static void add_top_module_nets_connect_grids_and_cb( grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; size_t sink_grid_pin_index = rr_graph.node_pin_num(instance_ipin_node); - t_physical_tile_type_ptr grid_type_descriptor = - grids[grid_coordinate.x()][grid_coordinate.y()].type; + t_physical_tile_type_ptr grid_type_descriptor = grids.get_physical_type( + t_physical_tile_loc(grid_coordinate.x(), grid_coordinate.y(), layer)); size_t sink_grid_pin_width = grid_type_descriptor->pin_width_offset[sink_grid_pin_index]; size_t sink_grid_pin_height = @@ -614,7 +617,7 @@ static void add_top_module_nets_connect_sb_and_cb( vtr::Point module_gsb_sb_coordinate(rr_gsb.get_x(), rr_gsb.get_y()); /* Skip those Switch blocks that do not exist */ - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { return; } @@ -802,8 +805,9 @@ static void add_top_module_nets_connect_sb_and_cb( void add_top_module_nets_connect_grids_and_gsbs( ModuleManager& module_manager, const ModuleId& top_module, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const vtr::Matrix& sb_instance_ids, const std::map>& cb_instance_ids, const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin) { vtr::ScopedStartFinishTimer timer("Add module nets between grids and GSBs"); @@ -818,24 +822,24 @@ void add_top_module_nets_connect_grids_and_gsbs( /* Connect the grid pins of the GSB to adjacent grids */ if (false == duplicate_grid_pin) { add_top_module_nets_connect_grids_and_sb( - module_manager, top_module, vpr_device_annotation, grids, + module_manager, top_module, vpr_device_annotation, grids, layer, grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, sb_instance_ids, compact_routing_hierarchy); } else { VTR_ASSERT_SAFE(true == duplicate_grid_pin); add_top_module_nets_connect_grids_and_sb_with_duplicated_pins( - module_manager, top_module, vpr_device_annotation, grids, + module_manager, top_module, vpr_device_annotation, grids, layer, grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, sb_instance_ids, compact_routing_hierarchy); } add_top_module_nets_connect_grids_and_cb( - module_manager, top_module, vpr_device_annotation, grids, + module_manager, top_module, vpr_device_annotation, grids, layer, grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, CHANX, cb_instance_ids.at(CHANX), compact_routing_hierarchy); add_top_module_nets_connect_grids_and_cb( - module_manager, top_module, vpr_device_annotation, grids, + module_manager, top_module, vpr_device_annotation, grids, layer, grid_instance_ids, rr_graph, device_rr_gsb, rr_gsb, CHANY, cb_instance_ids.at(CHANY), compact_routing_hierarchy); @@ -856,10 +860,10 @@ static int build_top_module_global_net_for_given_grid_module( const TileGlobalPortId& tile_global_port, const BasicPort& tile_port_to_connect, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Point& grid_coordinate, const e_side& border_side, - const vtr::Matrix& grid_instance_ids) { - t_physical_tile_type_ptr physical_tile = - grids[grid_coordinate.x()][grid_coordinate.y()].type; + const size_t& layer, const vtr::Point& grid_coordinate, + const e_side& border_side, const vtr::Matrix& grid_instance_ids) { + t_physical_tile_type_ptr physical_tile = grids.get_physical_type( + t_physical_tile_loc(grid_coordinate.x(), grid_coordinate.y(), layer)); /* Find the module name for this type of grid */ std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); std::string grid_module_name = generate_grid_block_module_name( @@ -982,7 +986,7 @@ static int build_top_module_global_net_from_grid_modules( const ModulePortId& top_module_port, const TileAnnotation& tile_annotation, const TileGlobalPortId& tile_global_port, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids) { + const size_t& layer, const vtr::Matrix& grid_instance_ids) { int status = CMD_EXEC_SUCCESS; std::map>> io_coordinates = @@ -1038,25 +1042,28 @@ static int build_top_module_global_net_from_grid_modules( /* Spot the port from child modules from core grids */ for (size_t ix = start_coord.x(); ix < end_coord.x(); ++ix) { for (size_t iy = start_coord.y(); iy < end_coord.y(); ++iy) { + t_physical_tile_loc tile_loc(ix, iy, layer); + t_physical_tile_type_ptr phy_tile_type = + grids.get_physical_type(tile_loc); /* Bypass EMPTY tiles */ - if (true == is_empty_type(grids[ix][iy].type)) { + if (true == is_empty_type(phy_tile_type)) { continue; } /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[ix][iy].width_offset) || - (0 < grids[ix][iy].height_offset)) { + if ((0 < grids.get_width_offset(tile_loc)) || + (0 < grids.get_height_offset(tile_loc))) { continue; } /* Bypass the tiles whose names do not match */ - if (std::string(grids[ix][iy].type->name) != tile_name) { + if (std::string(phy_tile_type->name) != tile_name) { continue; } /* Create nets and finish connection build-up */ status = build_top_module_global_net_for_given_grid_module( module_manager, top_module, top_module_port, tile_annotation, - tile_global_port, tile_port, vpr_device_annotation, grids, + tile_global_port, tile_port, vpr_device_annotation, grids, layer, vtr::Point(ix, iy), NUM_SIDES, grid_instance_ids); if (CMD_EXEC_FATAL_ERROR == status) { return status; @@ -1067,22 +1074,23 @@ static int build_top_module_global_net_from_grid_modules( /* Walk through all the grids on the perimeter, which are I/O grids */ for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { for (const vtr::Point& io_coordinate : io_coordinates[io_side]) { + t_physical_tile_loc tile_loc(io_coordinate.x(), io_coordinate.y(), + layer); + t_physical_tile_type_ptr phy_tile_type = + grids.get_physical_type(tile_loc); /* Bypass EMPTY grid */ - if (true == - is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { + if (true == is_empty_type(phy_tile_type)) { continue; } /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) || - (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { + if ((0 < grids.get_width_offset(tile_loc)) || + (0 < grids.get_height_offset(tile_loc))) { continue; } /* Bypass the tiles whose names do not match */ - if (std::string( - grids[io_coordinate.x()][io_coordinate.y()].type->name) != - tile_name) { + if (std::string(phy_tile_type->name) != tile_name) { continue; } @@ -1102,7 +1110,7 @@ static int build_top_module_global_net_from_grid_modules( /* Create nets and finish connection build-up */ status = build_top_module_global_net_for_given_grid_module( module_manager, top_module, top_module_port, tile_annotation, - tile_global_port, tile_port, vpr_device_annotation, grids, + tile_global_port, tile_port, vpr_device_annotation, grids, layer, io_coordinate, io_side, grid_instance_ids); if (CMD_EXEC_FATAL_ERROR == status) { return status; @@ -1200,7 +1208,8 @@ int add_top_module_global_ports_from_grid_modules( ModuleManager& module_manager, const ModuleId& top_module, const TileAnnotation& tile_annotation, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const size_t& layer, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const std::map>& cb_instance_ids, const vtr::Matrix& grid_instance_ids, const ClockNetwork& clk_ntwk, const RRClockSpatialLookup& rr_clock_lookup) { @@ -1259,7 +1268,8 @@ int add_top_module_global_ports_from_grid_modules( } else { status = build_top_module_global_net_from_grid_modules( module_manager, top_module, top_module_port, tile_annotation, - tile_global_port, vpr_device_annotation, grids, grid_instance_ids); + tile_global_port, vpr_device_annotation, grids, layer, + grid_instance_ids); } if (status == CMD_EXEC_FATAL_ERROR) { return status; diff --git a/openfpga/src/fabric/build_top_module_connection.h b/openfpga/src/fabric/build_top_module_connection.h index a155d6a7d..d4c18e7a7 100644 --- a/openfpga/src/fabric/build_top_module_connection.h +++ b/openfpga/src/fabric/build_top_module_connection.h @@ -28,8 +28,9 @@ namespace openfpga { void add_top_module_nets_connect_grids_and_gsbs( ModuleManager& module_manager, const ModuleId& top_module, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, const RRGraphView& rr_graph, - const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const vtr::Matrix& sb_instance_ids, const std::map>& cb_instance_ids, const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin); @@ -37,7 +38,8 @@ int add_top_module_global_ports_from_grid_modules( ModuleManager& module_manager, const ModuleId& top_module, const TileAnnotation& tile_annotation, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, + const size_t& layer, const RRGraphView& rr_graph, + const DeviceRRGSB& device_rr_gsb, const std::map>& cb_instance_ids, const vtr::Matrix& grid_instance_ids, const ClockNetwork& clk_ntwk, const RRClockSpatialLookup& rr_clock_lookup); diff --git a/openfpga/src/fabric/build_top_module_directs.cpp b/openfpga/src/fabric/build_top_module_directs.cpp index 9b0179493..205c54702 100644 --- a/openfpga/src/fabric/build_top_module_directs.cpp +++ b/openfpga/src/fabric/build_top_module_directs.cpp @@ -39,15 +39,17 @@ static void add_module_nets_tile_direct_connection( ModuleManager& module_manager, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, const TileDirect& tile_direct, - const TileDirectId& tile_direct_id, const ArchDirect& arch_direct) { + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const TileDirect& tile_direct, const TileDirectId& tile_direct_id, + const ArchDirect& arch_direct) { vtr::Point device_size(grids.width(), grids.height()); /* Find the module name of source clb */ vtr::Point src_clb_coord = tile_direct.from_tile_coordinate(tile_direct_id); + t_physical_tile_loc src_grid_loc(src_clb_coord.x(), src_clb_coord.y(), layer); t_physical_tile_type_ptr src_grid_type = - grids[src_clb_coord.x()][src_clb_coord.y()].type; + grids.get_physical_type(src_grid_loc); e_side src_grid_border_side = find_grid_border_side(device_size, src_clb_coord); std::string src_module_name_prefix(GRID_MODULE_NAME_PREFIX); @@ -63,8 +65,10 @@ static void add_module_nets_tile_direct_connection( /* Find the module name of sink clb */ vtr::Point des_clb_coord = tile_direct.to_tile_coordinate(tile_direct_id); + t_physical_tile_loc sink_grid_loc(des_clb_coord.x(), des_clb_coord.y(), + layer); t_physical_tile_type_ptr sink_grid_type = - grids[des_clb_coord.x()][des_clb_coord.y()].type; + grids.get_physical_type(sink_grid_loc); e_side sink_grid_border_side = find_grid_border_side(device_size, des_clb_coord); std::string sink_module_name_prefix(GRID_MODULE_NAME_PREFIX); @@ -114,7 +118,7 @@ static void add_module_nets_tile_direct_connection( size_t src_tile_pin = tile_direct.from_tile_pin(tile_direct_id); t_physical_tile_type_ptr src_grid_type_descriptor = - grids[src_clb_coord.x()][src_clb_coord.y()].type; + grids.get_physical_type(src_grid_loc); size_t src_pin_width = src_grid_type_descriptor->pin_width_offset[src_tile_pin]; size_t src_pin_height = @@ -148,7 +152,7 @@ static void add_module_nets_tile_direct_connection( size_t sink_tile_pin = tile_direct.to_tile_pin(tile_direct_id); t_physical_tile_type_ptr sink_grid_type_descriptor = - grids[des_clb_coord.x()][des_clb_coord.y()].type; + grids.get_physical_type(sink_grid_loc); size_t sink_pin_width = sink_grid_type_descriptor->pin_width_offset[src_tile_pin]; size_t sink_pin_height = @@ -209,15 +213,15 @@ void add_top_module_nets_tile_direct_connections( ModuleManager& module_manager, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, const TileDirect& tile_direct, - const ArchDirect& arch_direct) { + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const TileDirect& tile_direct, const ArchDirect& arch_direct) { vtr::ScopedStartFinishTimer timer( "Add module nets for inter-tile connections"); for (const TileDirectId& tile_direct_id : tile_direct.directs()) { add_module_nets_tile_direct_connection( module_manager, top_module, circuit_lib, vpr_device_annotation, grids, - grid_instance_ids, tile_direct, tile_direct_id, arch_direct); + layer, grid_instance_ids, tile_direct, tile_direct_id, arch_direct); } } diff --git a/openfpga/src/fabric/build_top_module_directs.h b/openfpga/src/fabric/build_top_module_directs.h index 4de48efb7..7e85661dc 100644 --- a/openfpga/src/fabric/build_top_module_directs.h +++ b/openfpga/src/fabric/build_top_module_directs.h @@ -26,8 +26,8 @@ void add_top_module_nets_tile_direct_connections( ModuleManager& module_manager, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, const TileDirect& tile_direct, - const ArchDirect& arch_direct); + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const TileDirect& tile_direct, const ArchDirect& arch_direct); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 9b61e0a55..a7d137a5e 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -86,7 +86,7 @@ static void organize_top_module_tile_cb_modules( module_manager.add_configurable_child( top_module, cb_module, cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], - config_coord); + ModuleManager::e_config_child_type::UNIFIED, config_coord); } } @@ -134,10 +134,11 @@ static void organize_top_module_tile_memory_modules( const e_config_protocol_type& sram_orgz_type, const CircuitModelId& sram_model, const DeviceGrid& grids, const vtr::Matrix& grid_instance_ids, - const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph, + const vtr::Matrix& sb_instance_ids, const std::map>& cb_instance_ids, - const bool& compact_routing_hierarchy, const vtr::Point& tile_coord, - const e_side& tile_border_side) { + const bool& compact_routing_hierarchy, const size_t& layer, + const vtr::Point& tile_coord, const e_side& tile_border_side) { vtr::Point gsb_coord_range = device_rr_gsb.get_gsb_range(); vtr::Point gsb_coord(tile_coord.x(), tile_coord.y() - 1); @@ -165,7 +166,7 @@ static void organize_top_module_tile_memory_modules( * we will update the memory module and instance list */ /* If the CB does not exist, we can skip addition */ - if (true == rr_gsb.is_sb_exist()) { + if (true == rr_gsb.is_sb_exist(rr_graph)) { if (0 < find_module_num_config_bits(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type)) { @@ -173,7 +174,8 @@ static void organize_top_module_tile_memory_modules( rr_gsb.get_sb_y() * 2 + 1); module_manager.add_configurable_child( top_module, sb_module, - sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], config_coord); + sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], + ModuleManager::e_config_child_type::UNIFIED, config_coord); } } @@ -190,8 +192,8 @@ static void organize_top_module_tile_memory_modules( } /* Find the module name for this type of grid */ - t_physical_tile_type_ptr grid_type = - grids[tile_coord.x()][tile_coord.y()].type; + t_physical_tile_loc phy_tile_loc(tile_coord.x(), tile_coord.y(), layer); + t_physical_tile_type_ptr grid_type = grids.get_physical_type(phy_tile_loc); /* Skip EMPTY Grid */ if (true == is_empty_type(grid_type)) { @@ -199,8 +201,8 @@ static void organize_top_module_tile_memory_modules( } /* Skip width > 1 or height > 1 Grid, which should already been processed when * offset=0 */ - if ((0 < grids[tile_coord.x()][tile_coord.y()].width_offset) || - (0 < grids[tile_coord.x()][tile_coord.y()].height_offset)) { + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { return; } @@ -219,7 +221,8 @@ static void organize_top_module_tile_memory_modules( vtr::Point config_coord(tile_coord.x() * 2, tile_coord.y() * 2); module_manager.add_configurable_child( top_module, grid_module, - grid_instance_ids[tile_coord.x()][tile_coord.y()], config_coord); + grid_instance_ids[tile_coord.x()][tile_coord.y()], + ModuleManager::e_config_child_type::UNIFIED, config_coord); } } @@ -262,21 +265,28 @@ static void organize_top_module_tile_memory_modules( * - This function should NOT modify configurable children * *******************************************************************/ -static void build_top_module_configurable_regions( +void build_top_module_configurable_regions( ModuleManager& module_manager, const ModuleId& top_module, const ConfigProtocol& config_protocol) { vtr::ScopedStartFinishTimer timer( "Build configurable regions for the top module"); /* Ensure we have valid configurable children */ - VTR_ASSERT(false == module_manager.configurable_children(top_module).empty()); + VTR_ASSERT(false == + module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .empty()); /* Ensure that our region definition is valid */ VTR_ASSERT(1 <= config_protocol.num_regions()); /* Exclude decoders from the list */ size_t num_configurable_children = - module_manager.configurable_children(top_module).size(); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); if (CONFIG_MEM_MEMORY_BANK == config_protocol.type() || CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { num_configurable_children -= 2; @@ -291,7 +301,10 @@ static void build_top_module_configurable_regions( bool create_region = true; ConfigRegionId curr_region = ConfigRegionId::INVALID(); for (size_t ichild = 0; - ichild < module_manager.configurable_children(top_module).size(); + ichild < module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++ichild) { if (true == create_region) { curr_region = module_manager.add_config_region(top_module); @@ -300,8 +313,11 @@ static void build_top_module_configurable_regions( /* Add the child to a region */ module_manager.add_configurable_child_to_region( top_module, curr_region, - module_manager.configurable_children(top_module)[ichild], - module_manager.configurable_child_instances(top_module)[ichild], ichild); + module_manager.configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild], + module_manager.configurable_child_instances( + top_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild], + ichild); /* See if the current region is full or not: * For the last region, we will keep adding until we finish all the children @@ -422,12 +438,17 @@ void organize_top_module_memory_modules( ModuleManager& module_manager, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, const CircuitModelId& sram_model, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph, + const vtr::Matrix& sb_instance_ids, const std::map>& cb_instance_ids, const bool& compact_routing_hierarchy) { /* Ensure clean vectors to return */ - VTR_ASSERT(true == module_manager.configurable_children(top_module).empty()); + VTR_ASSERT(true == + module_manager + .configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL) + .empty()); /* First, organize the I/O tiles on the border */ /* Special for the I/O tileas on RIGHT and BOTTOM, @@ -477,8 +498,9 @@ void organize_top_module_memory_modules( /* Identify the GSB that surrounds the grid */ organize_top_module_tile_memory_modules( module_manager, top_module, circuit_lib, config_protocol.type(), - sram_model, grids, grid_instance_ids, device_rr_gsb, sb_instance_ids, - cb_instance_ids, compact_routing_hierarchy, io_coord, io_side); + sram_model, grids, grid_instance_ids, device_rr_gsb, rr_graph, + sb_instance_ids, cb_instance_ids, compact_routing_hierarchy, layer, + io_coord, io_side); } } @@ -505,8 +527,9 @@ void organize_top_module_memory_modules( for (const vtr::Point& core_coord : core_coords) { organize_top_module_tile_memory_modules( module_manager, top_module, circuit_lib, config_protocol.type(), - sram_model, grids, grid_instance_ids, device_rr_gsb, sb_instance_ids, - cb_instance_ids, compact_routing_hierarchy, core_coord, NUM_SIDES); + sram_model, grids, grid_instance_ids, device_rr_gsb, rr_graph, + sb_instance_ids, cb_instance_ids, compact_routing_hierarchy, layer, + core_coord, NUM_SIDES); } /* Split memory modules into different regions */ @@ -530,7 +553,11 @@ void organize_top_module_memory_modules( void shuffle_top_module_configurable_children( ModuleManager& module_manager, const ModuleId& top_module, const ConfigProtocol& config_protocol) { - size_t num_keys = module_manager.configurable_children(top_module).size(); + size_t num_keys = + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); std::vector shuffled_keys; shuffled_keys.reserve(num_keys); for (size_t ikey = 0; ikey < num_keys; ++ikey) { @@ -541,11 +568,14 @@ void shuffle_top_module_configurable_children( /* Cache the configurable children and their instances */ std::vector orig_configurable_children = - module_manager.configurable_children(top_module); + module_manager.configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL); std::vector orig_configurable_child_instances = - module_manager.configurable_child_instances(top_module); + module_manager.configurable_child_instances( + top_module, ModuleManager::e_config_child_type::PHYSICAL); std::vector> orig_configurable_child_coordinates = - module_manager.configurable_child_coordinates(top_module); + module_manager.configurable_child_coordinates( + top_module, ModuleManager::e_config_child_type::PHYSICAL); /* Reorganize the configurable children */ module_manager.clear_configurable_children(top_module); @@ -554,6 +584,7 @@ void shuffle_top_module_configurable_children( module_manager.add_configurable_child( top_module, orig_configurable_children[shuffled_keys[ikey]], orig_configurable_child_instances[shuffled_keys[ikey]], + ModuleManager::e_config_child_type::UNIFIED, orig_configurable_child_coordinates[shuffled_keys[ikey]]); } @@ -650,9 +681,10 @@ int load_top_module_memory_modules_from_fabric_key( } /* Now we can add the child to configurable children of the top module */ - module_manager.add_configurable_child(top_module, instance_info.first, - instance_info.second, - fabric_key.key_coordinate(key)); + module_manager.add_configurable_child( + top_module, instance_info.first, instance_info.second, + ModuleManager::e_config_child_type::UNIFIED, + fabric_key.key_coordinate(key)); module_manager.add_configurable_child_to_region( top_module, top_module_config_region, instance_info.first, instance_info.second, curr_configurable_child_id); @@ -1329,17 +1361,27 @@ static void add_top_module_nets_cmos_memory_bank_config_bus( * Note: this MUST be done after adding all the module nets to other regular * configurable children */ - module_manager.add_configurable_child(top_module, bl_decoder_module, - curr_bl_decoder_instance_id); + module_manager.add_configurable_child( + top_module, bl_decoder_module, curr_bl_decoder_instance_id, + ModuleManager::e_config_child_type::PHYSICAL); module_manager.add_configurable_child_to_region( top_module, config_region, bl_decoder_module, curr_bl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); - module_manager.add_configurable_child(top_module, wl_decoder_module, - curr_wl_decoder_instance_id); + module_manager.add_configurable_child( + top_module, wl_decoder_module, curr_wl_decoder_instance_id, + ModuleManager::e_config_child_type::PHYSICAL); module_manager.add_configurable_child_to_region( top_module, config_region, wl_decoder_module, curr_wl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); } } @@ -1759,8 +1801,8 @@ static void add_top_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; ModulePortId child_din_port = module_manager.find_module_port( child_module, std::string(DECODER_DATA_IN_PORT_NAME)); BasicPort child_din_port_info = @@ -1794,8 +1836,8 @@ static void add_top_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; ModulePortId child_en_port = module_manager.find_module_port( child_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort child_en_port_info = @@ -1814,12 +1856,17 @@ static void add_top_module_nets_cmos_memory_frame_decoder_config_bus( } /* Add the decoder as the last configurable children */ - module_manager.add_configurable_child(parent_module, decoder_module, - decoder_instance); + module_manager.add_configurable_child( + parent_module, decoder_module, decoder_instance, + ModuleManager::e_config_child_type::PHYSICAL); /* Register the configurable child to configuration region */ module_manager.add_configurable_child_to_region( parent_module, config_region, decoder_module, decoder_instance, - module_manager.configurable_children(parent_module).size() - 1); + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); } /********************************************************************* @@ -1927,10 +1974,10 @@ static void add_top_module_nets_cmos_memory_config_bus( case CONFIG_MEM_STANDALONE: add_module_nets_cmos_flatten_memory_config_bus( module_manager, parent_module, config_protocol.type(), - CIRCUIT_MODEL_PORT_BL); + CIRCUIT_MODEL_PORT_BL, ModuleManager::e_config_child_type::PHYSICAL); add_module_nets_cmos_flatten_memory_config_bus( module_manager, parent_module, config_protocol.type(), - CIRCUIT_MODEL_PORT_WL); + CIRCUIT_MODEL_PORT_WL, ModuleManager::e_config_child_type::PHYSICAL); break; case CONFIG_MEM_SCAN_CHAIN: { add_top_module_nets_cmos_memory_chain_config_bus( diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index 0f4a17d6a..163d7614a 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -18,6 +18,7 @@ #include "fabric_key.h" #include "memory_bank_shift_register_banks.h" #include "module_manager.h" +#include "rr_graph_view.h" #include "vtr_ndmatrix.h" #include "vtr_vector.h" @@ -32,11 +33,16 @@ void organize_top_module_memory_modules( ModuleManager& module_manager, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, const CircuitModelId& sram_model, const DeviceGrid& grids, - const vtr::Matrix& grid_instance_ids, - const DeviceRRGSB& device_rr_gsb, const vtr::Matrix& sb_instance_ids, + const size_t& layer, const vtr::Matrix& grid_instance_ids, + const DeviceRRGSB& device_rr_gsb, const RRGraphView& rr_graph, + const vtr::Matrix& sb_instance_ids, const std::map>& cb_instance_ids, const bool& compact_routing_hierarchy); +void build_top_module_configurable_regions( + ModuleManager& module_manager, const ModuleId& top_module, + const ConfigProtocol& config_protocol); + void shuffle_top_module_configurable_children( ModuleManager& module_manager, const ModuleId& top_module, const ConfigProtocol& config_protocol); diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 0e5823ae2..62b12f254 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -58,7 +58,11 @@ static void add_module_nets_to_ql_memory_bank_shift_register_module( const std::string& chain_head_port_name, const std::string& chain_tail_port_name) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -78,28 +82,30 @@ static void add_module_nets_to_ql_memory_bank_shift_register_module( /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = circuit_lib.port_prefix(model_input_port); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } @@ -133,9 +139,15 @@ static void add_module_nets_to_ql_memory_bank_shift_register_module( /* Find the port name of previous memory module */ std::string src_port_name = circuit_lib.port_prefix(model_output_port); ModuleId net_src_module_id = - module_manager.configurable_children(parent_module).back(); + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .back(); size_t net_src_instance_id = - module_manager.configurable_child_instances(parent_module).back(); + module_manager + .configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL) + .back(); ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); @@ -244,8 +256,9 @@ static ModuleId build_bl_shift_register_chain_module( size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_mem_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_mem_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Build module nets to wire bl outputs of sram modules to BL outputs of * memory module */ @@ -362,8 +375,9 @@ static ModuleId build_wl_shift_register_chain_module( size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); module_manager.add_child_module(mem_module, sram_mem_module); - module_manager.add_configurable_child(mem_module, sram_mem_module, - sram_mem_instance); + module_manager.add_configurable_child( + mem_module, sram_mem_module, sram_mem_instance, + ModuleManager::e_config_child_type::UNIFIED); /* Build module nets to wire wl outputs of sram modules to WL outputs of * memory module */ @@ -698,11 +712,16 @@ static void add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus( * Note: this MUST be done after adding all the module nets to other regular * configurable children */ - module_manager.add_configurable_child(top_module, bl_decoder_module, - curr_bl_decoder_instance_id); + module_manager.add_configurable_child( + top_module, bl_decoder_module, curr_bl_decoder_instance_id, + ModuleManager::e_config_child_type::UNIFIED); module_manager.add_configurable_child_to_region( top_module, config_region, bl_decoder_module, curr_bl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); } } @@ -967,11 +986,16 @@ static void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus( * Note: this MUST be done after adding all the module nets to other regular * configurable children */ - module_manager.add_configurable_child(top_module, wl_decoder_module, - curr_wl_decoder_instance_id); + module_manager.add_configurable_child( + top_module, wl_decoder_module, curr_wl_decoder_instance_id, + ModuleManager::e_config_child_type::UNIFIED); module_manager.add_configurable_child_to_region( top_module, config_region, wl_decoder_module, curr_wl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size() - + 1); } } diff --git a/openfpga/src/fabric/build_top_module_utils.cpp b/openfpga/src/fabric/build_top_module_utils.cpp index c4405623a..ebf52eb77 100644 --- a/openfpga/src/fabric/build_top_module_utils.cpp +++ b/openfpga/src/fabric/build_top_module_utils.cpp @@ -11,6 +11,7 @@ /* Module builder headers */ #include "build_top_module_utils.h" +#include "openfpga_rr_graph_utils.h" /* begin namespace openfpga */ namespace openfpga { @@ -28,10 +29,47 @@ std::string generate_grid_block_module_name_in_top_module( /* Determine if the grid locates at the border */ vtr::Point device_size(grids.width(), grids.height()); e_side border_side = find_grid_border_side(device_size, grid_coord); + t_physical_tile_type_ptr phy_tile_type = grids.get_physical_type( + t_physical_tile_loc(grid_coord.x(), grid_coord.y(), 0)); return generate_grid_block_module_name( - prefix, std::string(grids[grid_coord.x()][grid_coord.y()].type->name), - is_io_type(grids[grid_coord.x()][grid_coord.y()].type), border_side); + prefix, std::string(phy_tile_type->name), is_io_type(phy_tile_type), + border_side); +} + +/******************************************************************** + * Generate the port name for a grid block, by considering + * 1. its pin index + * 2. side on the grid + * 3. relative position in the physical tile + * + * This function is mainly used in the top-level module generation + * Note that it may be useful for other modules but not tried yet! + *******************************************************************/ +std::string generate_grid_module_port_name_in_top_module( + const DeviceGrid& grids, const vtr::Point& grid_coordinate, + const size_t& sink_grid_pin_index, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const RRNodeId& inode) { + t_physical_tile_type_ptr grid_type_descriptor = grids.get_physical_type( + t_physical_tile_loc(grid_coordinate.x(), grid_coordinate.y(), 0)); + size_t sink_grid_pin_width = + grid_type_descriptor->pin_width_offset[sink_grid_pin_index]; + size_t sink_grid_pin_height = + grid_type_descriptor->pin_height_offset[sink_grid_pin_index]; + BasicPort sink_grid_pin_info = + vpr_device_annotation.physical_tile_pin_port_info(grid_type_descriptor, + sink_grid_pin_index); + VTR_ASSERT(true == sink_grid_pin_info.is_valid()); + int subtile_index = vpr_device_annotation.physical_tile_pin_subtile_index( + grid_type_descriptor, sink_grid_pin_index); + VTR_ASSERT(OPEN != subtile_index && + subtile_index < grid_type_descriptor->capacity); + std::string sink_grid_port_name = generate_grid_port_name( + sink_grid_pin_width, sink_grid_pin_height, subtile_index, + get_rr_graph_single_node_side(rr_graph, inode), sink_grid_pin_info); + + return sink_grid_port_name; } /******************************************************************** diff --git a/openfpga/src/fabric/build_top_module_utils.h b/openfpga/src/fabric/build_top_module_utils.h index 394a3408a..3a871b3e1 100644 --- a/openfpga/src/fabric/build_top_module_utils.h +++ b/openfpga/src/fabric/build_top_module_utils.h @@ -9,6 +9,7 @@ #include "device_grid.h" #include "rr_gsb.h" +#include "vpr_device_annotation.h" #include "vtr_geometry.h" /******************************************************************** @@ -22,6 +23,12 @@ std::string generate_grid_block_module_name_in_top_module( const std::string& prefix, const DeviceGrid& grids, const vtr::Point& grid_coord); +std::string generate_grid_module_port_name_in_top_module( + const DeviceGrid& grids, const vtr::Point& grid_coordinate, + const size_t& sink_grid_pin_index, + const VprDeviceAnnotation& vpr_device_annotation, const RRGraphView& rr_graph, + const RRNodeId& inode); + t_rr_type find_top_module_cb_type_by_sb_side(const e_side& sb_side); vtr::Point find_top_module_gsb_coordinate_by_sb_side( diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index d5e7ef978..cef0a79d4 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -7,6 +7,7 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ +#include "command_exit_codes.h" #include "openfpga_digest.h" /* Headers from archopenfpga library */ @@ -18,6 +19,57 @@ /* begin namespace openfpga */ namespace openfpga { +/*************************************************************************************** + * Add module-level keys to fabric key + ***************************************************************************************/ +static int add_module_keys_to_fabric_key(const ModuleManager& module_manager, + const ModuleId& curr_module, + FabricKey& fabric_key) { + /* Bypass top-level module */ + std::string module_name = module_manager.module_name(curr_module); + if (module_name == generate_fpga_top_module_name() || + module_name == generate_fpga_core_module_name()) { + return CMD_EXEC_SUCCESS; + } + /* Bypass modules which does not have any configurable children */ + if (module_manager + .configurable_children(curr_module, + ModuleManager::e_config_child_type::PHYSICAL) + .empty()) { + return CMD_EXEC_SUCCESS; + } + /* Now create the module and add subkey one by one */ + FabricKeyModuleId key_module_id = fabric_key.create_module(module_name); + if (!key_module_id) { + return CMD_EXEC_FATAL_ERROR; + } + size_t num_config_child = + module_manager + .configurable_children(curr_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); + for (size_t ichild = 0; ichild < num_config_child; ++ichild) { + ModuleId child_module = module_manager.configurable_children( + curr_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild]; + size_t child_instance = module_manager.configurable_child_instances( + curr_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild]; + + FabricSubKeyId sub_key = fabric_key.create_module_key(key_module_id); + fabric_key.set_sub_key_name(sub_key, + module_manager.module_name(child_module)); + fabric_key.set_sub_key_value(sub_key, child_instance); + + if (false == + module_manager.instance_name(curr_module, child_module, child_instance) + .empty()) { + fabric_key.set_sub_key_alias( + sub_key, module_manager.instance_name(curr_module, child_module, + child_instance)); + } + } + return CMD_EXEC_SUCCESS; +} + /*************************************************************************************** * Write the fabric key of top module to an XML file * We will use the writer API in libfabrickey @@ -29,7 +81,9 @@ namespace openfpga { int write_fabric_key_to_xml_file( const ModuleManager& module_manager, const std::string& fname, const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose) { + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const bool& include_module_keys, const bool& verbose) { + int err_code = CMD_EXEC_SUCCESS; std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'"); @@ -47,15 +101,27 @@ int write_fabric_key_to_xml_file( /* Find top-level module */ std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.find_module(top_module_name); - if (true != module_manager.valid_module_id(top_module)) { - VTR_LOGV_ERROR(verbose, "Unable to find the top-level module '%s'!\n", - top_module_name.c_str()); - return 1; + std::string core_module_name = generate_fpga_core_module_name(); + ModuleId core_module = module_manager.find_module(core_module_name); + if (!module_manager.valid_module_id(top_module) && + !module_manager.valid_module_id(core_module)) { + VTR_LOGV_ERROR( + verbose, "Unable to find the top-level/core-level module '%s' or '%s'!\n", + top_module_name.c_str(), core_module_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + if (module_manager.valid_module_id(top_module) && + module_manager.valid_module_id(core_module)) { + top_module = core_module; } /* Build a fabric key database by visiting all the configurable children */ FabricKey fabric_key; - size_t num_keys = module_manager.configurable_children(top_module).size(); + size_t num_keys = + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); fabric_key.reserve_keys(num_keys); @@ -165,8 +231,19 @@ int write_fabric_key_to_xml_file( VTR_LOGV(verbose, "Created %lu regions and %lu keys for the top module %s.\n", num_regions, num_keys, top_module_name.c_str()); + /* Output module subkeys if specified */ + if (include_module_keys) { + for (ModuleId submodule : module_manager.modules()) { + err_code = + add_module_keys_to_fabric_key(module_manager, submodule, fabric_key); + if (err_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + } + /* Call the XML writer for fabric key */ - int err_code = write_xml_fabric_key(fname.c_str(), fabric_key); + err_code = write_xml_fabric_key(fname.c_str(), fabric_key); return err_code; } diff --git a/openfpga/src/fabric/fabric_key_writer.h b/openfpga/src/fabric/fabric_key_writer.h index 34327d307..77413b812 100644 --- a/openfpga/src/fabric/fabric_key_writer.h +++ b/openfpga/src/fabric/fabric_key_writer.h @@ -20,7 +20,8 @@ namespace openfpga { int write_fabric_key_to_xml_file( const ModuleManager& module_manager, const std::string& fname, const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose); + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const bool& include_module_keys, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp index b1474835a..48d03095d 100644 --- a/openfpga/src/fabric/module_manager.cpp +++ b/openfpga/src/fabric/module_manager.cpp @@ -26,6 +26,17 @@ ModuleManager::module_range ModuleManager::modules() const { return vtr::make_range(ids_.begin(), ids_.end()); } +std::vector ModuleManager::modules_by_usage( + const ModuleManager::e_module_usage_type& usage) const { + std::vector module_list; + for (ModuleId curr_module : ids_) { + if (usages_[curr_module] == usage) { + module_list.push_back(curr_module); + } + } + return module_list; +} + /* Find all the ports belonging to a module */ ModuleManager::module_port_range ModuleManager::module_ports( const ModuleId& module) const { @@ -78,28 +89,56 @@ std::vector ModuleManager::child_module_instances( /* Find all the configurable child modules under a parent module */ std::vector ModuleManager::configurable_children( - const ModuleId& parent_module) const { + const ModuleId& parent_module, const e_config_child_type& type) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); - return configurable_children_[parent_module]; + if (type == ModuleManager::e_config_child_type::LOGICAL) { + return logical_configurable_children_[parent_module]; + } + VTR_ASSERT(type == ModuleManager::e_config_child_type::PHYSICAL); + return physical_configurable_children_[parent_module]; } /* Find all the instances of configurable child modules under a parent module */ std::vector ModuleManager::configurable_child_instances( - const ModuleId& parent_module) const { + const ModuleId& parent_module, const e_config_child_type& type) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); - return configurable_child_instances_[parent_module]; + if (type == ModuleManager::e_config_child_type::LOGICAL) { + return logical_configurable_child_instances_[parent_module]; + } + VTR_ASSERT(type == ModuleManager::e_config_child_type::PHYSICAL); + return physical_configurable_child_instances_[parent_module]; } std::vector> ModuleManager::configurable_child_coordinates( + const ModuleId& parent_module, const e_config_child_type& type) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(type == ModuleManager::e_config_child_type::PHYSICAL); + + return physical_configurable_child_coordinates_[parent_module]; +} + +/* Find all the configurable child modules under a parent module */ +std::vector ModuleManager::logical2physical_configurable_children( const ModuleId& parent_module) const { /* Validate the module_id */ VTR_ASSERT(valid_module_id(parent_module)); - return configurable_child_coordinates_[parent_module]; + return logical2physical_configurable_children_[parent_module]; +} + +/* Find all the instances of configurable child modules under a parent module */ +std::vector +ModuleManager::logical2physical_configurable_child_instance_names( + const ModuleId& parent_module) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_id(parent_module)); + + return logical2physical_configurable_child_instance_names_[parent_module]; } /* Find all the configurable child modules under a parent module */ @@ -166,7 +205,7 @@ std::vector ModuleManager::region_configurable_children( for (const size_t& child_id : config_region_children_[parent_module][region]) { region_config_children.push_back( - configurable_children_[parent_module][child_id]); + physical_configurable_children_[parent_module][child_id]); } return region_config_children; @@ -185,7 +224,7 @@ std::vector ModuleManager::region_configurable_child_instances( for (const size_t& child_id : config_region_children_[parent_module][region]) { region_config_child_instances.push_back( - configurable_child_instances_[parent_module][child_id]); + physical_configurable_child_instances_[parent_module][child_id]); } return region_config_child_instances; @@ -205,7 +244,7 @@ ModuleManager::region_configurable_child_coordinates( for (const size_t& child_id : config_region_children_[parent_module][region]) { region_config_child_coordinates.push_back( - configurable_child_coordinates_[parent_module][child_id]); + physical_configurable_child_coordinates_[parent_module][child_id]); } return region_config_child_coordinates; @@ -376,6 +415,16 @@ size_t ModuleManager::instance_id(const ModuleId& parent_module, return size_t(-1); } +size_t ModuleManager::num_configurable_children( + const ModuleId& parent_module, const e_config_child_type& type) const { + VTR_ASSERT(valid_module_id(parent_module)); + if (type == ModuleManager::e_config_child_type::LOGICAL) { + return logical_configurable_children_[parent_module].size(); + } + VTR_ASSERT(type == ModuleManager::e_config_child_type::PHYSICAL); + return physical_configurable_children_[parent_module].size(); +} + ModuleManager::e_module_port_type ModuleManager::port_type( const ModuleId& module, const ModulePortId& port) const { /* validate both module id and port id*/ @@ -612,6 +661,26 @@ bool ModuleManager::net_sink_exist(const ModuleId& module, return false; } +bool ModuleManager::unified_configurable_children( + const ModuleId& curr_module) const { + if (logical_configurable_children_[curr_module].size() != + physical_configurable_children_[curr_module].size()) { + return false; + } + for (size_t ichild = 0; + ichild < logical_configurable_children_[curr_module].size(); ++ichild) { + if (logical_configurable_children_[curr_module][ichild] != + physical_configurable_children_[curr_module][ichild]) { + return false; + } + if (logical_configurable_child_instances_[curr_module][ichild] != + physical_configurable_child_instances_[curr_module][ichild]) { + return false; + } + } + return true; +} + /****************************************************************************** * Private Accessors ******************************************************************************/ @@ -654,10 +723,15 @@ ModuleId ModuleManager::add_module(const std::string& name) { children_.emplace_back(); num_child_instances_.emplace_back(); child_instance_names_.emplace_back(); - configurable_children_.emplace_back(); - configurable_child_instances_.emplace_back(); - configurable_child_regions_.emplace_back(); - configurable_child_coordinates_.emplace_back(); + logical_configurable_children_.emplace_back(); + logical_configurable_child_instances_.emplace_back(); + physical_configurable_children_.emplace_back(); + physical_configurable_child_instances_.emplace_back(); + physical_configurable_child_regions_.emplace_back(); + physical_configurable_child_coordinates_.emplace_back(); + + logical2physical_configurable_children_.emplace_back(); + logical2physical_configurable_child_instance_names_.emplace_back(); config_region_ids_.emplace_back(); config_region_children_.emplace_back(); @@ -747,7 +821,13 @@ void ModuleManager::set_module_name(const ModuleId& module, const std::string& name) { /* Validate the id of module */ VTR_ASSERT(valid_module_id(module)); + std::string old_name = names_[module]; names_[module] = name; + + /* Unregister the old name */ + name_id_map_.erase(old_name); + /* Register the new name */ + name_id_map_[name] = module; } void ModuleManager::set_module_usage(const ModuleId& module, @@ -768,6 +848,14 @@ void ModuleManager::set_port_is_wire(const ModuleId& module, port_is_wire_[module][port] = is_wire; } +/* Set a port to be a wire */ +void ModuleManager::set_port_is_wire(const ModuleId& module, + const ModulePortId& port_id, + const bool& is_wire) { + VTR_ASSERT(valid_module_port_id(module, port_id)); + port_is_wire_[module][port_id] = is_wire; +} + /* Set a port to be a mappable I/O */ void ModuleManager::set_port_is_mappable_io(const ModuleId& module, const ModulePortId& port_id, @@ -788,6 +876,14 @@ void ModuleManager::set_port_is_register(const ModuleId& module, port_is_register_[module][port] = is_register; } +/* Set a port to be a register */ +void ModuleManager::set_port_is_register(const ModuleId& module, + const ModulePortId& port_id, + const bool& is_register) { + VTR_ASSERT(valid_module_port_id(module, port_id)); + port_is_register_[module][port_id] = is_register; +} + /* Set the preprocessing flag for a port */ void ModuleManager::set_port_preproc_flag(const ModuleId& module, const ModulePortId& port, @@ -881,6 +977,7 @@ void ModuleManager::set_child_instance_name(const ModuleId& parent_module, void ModuleManager::add_configurable_child(const ModuleId& parent_module, const ModuleId& child_module, const size_t& child_instance, + const e_config_child_type& type, const vtr::Point coord) { /* Validate the id of both parent and child modules */ VTR_ASSERT(valid_module_id(parent_module)); @@ -888,29 +985,108 @@ void ModuleManager::add_configurable_child(const ModuleId& parent_module, /* Ensure that the instance id is in range */ VTR_ASSERT(child_instance < num_instance(parent_module, child_module)); - configurable_children_[parent_module].push_back(child_module); - configurable_child_instances_[parent_module].push_back(child_instance); - configurable_child_regions_[parent_module].push_back( - ConfigRegionId::INVALID()); - configurable_child_coordinates_[parent_module].push_back(coord); + if (type == ModuleManager::e_config_child_type::LOGICAL || + type == ModuleManager::e_config_child_type::UNIFIED) { + logical_configurable_children_[parent_module].push_back(child_module); + logical_configurable_child_instances_[parent_module].push_back( + child_instance); + } + if (type == ModuleManager::e_config_child_type::PHYSICAL || + type == ModuleManager::e_config_child_type::UNIFIED) { + physical_configurable_children_[parent_module].push_back(child_module); + physical_configurable_child_instances_[parent_module].push_back( + child_instance); + physical_configurable_child_regions_[parent_module].push_back( + ConfigRegionId::INVALID()); + physical_configurable_child_coordinates_[parent_module].push_back(coord); + } + + if (type == ModuleManager::e_config_child_type::UNIFIED) { + logical2physical_configurable_children_[parent_module].push_back( + child_module); + logical2physical_configurable_child_instance_names_[parent_module] + .emplace_back(); + } else if (type == ModuleManager::e_config_child_type::LOGICAL) { + logical2physical_configurable_children_[parent_module].emplace_back(); + logical2physical_configurable_child_instance_names_[parent_module] + .emplace_back(); + } } -void ModuleManager::reserve_configurable_child(const ModuleId& parent_module, - const size_t& num_children) { +void ModuleManager::set_logical2physical_configurable_child( + const ModuleId& parent_module, const size_t& logical_child_id, + const ModuleId& physical_child_module) { + /* Sanity checks */ VTR_ASSERT(valid_module_id(parent_module)); - /* Do reserve when the number of children is larger than current size of lists - */ - if (num_children > configurable_children_[parent_module].size()) { - configurable_children_[parent_module].reserve(num_children); + VTR_ASSERT(logical_child_id < + num_configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)); + /* Create the pair */ + logical2physical_configurable_children_[parent_module][logical_child_id] = + physical_child_module; +} + +void ModuleManager::set_logical2physical_configurable_child_instance_name( + const ModuleId& parent_module, const size_t& logical_child_id, + const std::string& physical_child_instance_name) { + /* Sanity checks */ + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(logical_child_id < + num_configurable_children( + parent_module, ModuleManager::e_config_child_type::LOGICAL)); + /* Create the pair */ + logical2physical_configurable_child_instance_names_ + [parent_module][logical_child_id] = physical_child_instance_name; +} + +void ModuleManager::reserve_configurable_child( + const ModuleId& parent_module, const size_t& num_children, + const e_config_child_type& type) { + VTR_ASSERT(valid_module_id(parent_module)); + if (type == ModuleManager::e_config_child_type::LOGICAL || + type == ModuleManager::e_config_child_type::UNIFIED) { + /* Do reserve when the number of children is larger than current size of + * lists + */ + if (num_children > logical_configurable_children_[parent_module].size()) { + logical_configurable_children_[parent_module].reserve(num_children); + } + if (num_children > + logical_configurable_child_instances_[parent_module].size()) { + logical_configurable_child_instances_[parent_module].reserve( + num_children); + } + if (num_children > + logical2physical_configurable_children_[parent_module].size()) { + logical2physical_configurable_children_[parent_module].reserve( + num_children); + } + if (num_children > + logical2physical_configurable_child_instance_names_[parent_module] + .size()) { + logical2physical_configurable_child_instance_names_[parent_module] + .reserve(num_children); + } } - if (num_children > configurable_child_instances_[parent_module].size()) { - configurable_child_instances_[parent_module].reserve(num_children); - } - if (num_children > configurable_child_regions_[parent_module].size()) { - configurable_child_regions_[parent_module].reserve(num_children); - } - if (num_children > configurable_child_coordinates_[parent_module].size()) { - configurable_child_coordinates_[parent_module].reserve(num_children); + if (type == ModuleManager::e_config_child_type::PHYSICAL || + type == ModuleManager::e_config_child_type::UNIFIED) { + if (num_children > physical_configurable_children_[parent_module].size()) { + physical_configurable_children_[parent_module].reserve(num_children); + } + if (num_children > + physical_configurable_child_instances_[parent_module].size()) { + physical_configurable_child_instances_[parent_module].reserve( + num_children); + } + if (num_children > + physical_configurable_child_regions_[parent_module].size()) { + physical_configurable_child_regions_[parent_module].reserve(num_children); + } + if (num_children > + physical_configurable_child_coordinates_[parent_module].size()) { + physical_configurable_child_coordinates_[parent_module].reserve( + num_children); + } } } @@ -939,23 +1115,28 @@ void ModuleManager::add_configurable_child_to_region( /* Ensure that the child module is in the configurable children list */ VTR_ASSERT(child_module == - configurable_children(parent_module)[config_child_id]); + configurable_children( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[config_child_id]); VTR_ASSERT(child_instance == - configurable_child_instances(parent_module)[config_child_id]); + configurable_child_instances( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[config_child_id]); /* If the child is already in another region, error out */ - if ((true == - valid_region_id( - parent_module, - configurable_child_regions_[parent_module][config_child_id])) && + if ((true == valid_region_id( + parent_module, + physical_configurable_child_regions_[parent_module] + [config_child_id])) && (config_region != - configurable_child_regions_[parent_module][config_child_id])) { + physical_configurable_child_regions_[parent_module][config_child_id])) { VTR_LOGF_ERROR( __FILE__, __LINE__, "Try to add a configurable child '%s[%lu]' to region '%lu' which is " "already added to another region '%lu'!\n", module_name(child_module).c_str(), child_instance, size_t(config_region), - size_t(configurable_child_regions_[parent_module][config_child_id])); + size_t( + physical_configurable_child_regions_[parent_module][config_child_id])); exit(1); } @@ -1185,16 +1366,107 @@ ModuleNetSinkId ModuleManager::add_module_net_sink( return net_sink; } +ModuleId ModuleManager::create_wrapper_module( + const ModuleId& existing_module, const std::string& wrapper_module_name, + const std::string& instance_name, const bool& add_nets) { + /* Create a new module with the given name */ + ModuleId wrapper_module = add_module(wrapper_module_name); + if (!wrapper_module) { + return wrapper_module; + } + /* Add the existing module as an instance */ + add_child_module(wrapper_module, existing_module, false); + set_child_instance_name(wrapper_module, existing_module, 0, instance_name); + + /* A fast-lookup on the port linking: wrapper_module port -> existing_module + * port */ + std::map port_map; + /* Herit ports */ + for (ModulePortId existing_port : module_ports(existing_module)) { + /* Create new port */ + BasicPort existing_port_info = module_port(existing_module, existing_port); + ModuleManager::e_module_port_type existing_port_type = + port_type(existing_module, existing_port); + ModulePortId new_port = + add_port(wrapper_module, existing_port_info, existing_port_type); + /* Set port attributes */ + set_port_is_wire(wrapper_module, new_port, + port_is_wire(existing_module, existing_port)); + set_port_is_mappable_io( + wrapper_module, new_port, + port_is_mappable_io(existing_module, existing_port)); + set_port_is_register(wrapper_module, new_port, + port_is_register(existing_module, existing_port)); + set_port_preproc_flag(wrapper_module, new_port, + port_preproc_flag(existing_module, existing_port)); + /* Register in port mapping */ + port_map[new_port] = existing_port; + } + + /* Add nets */ + if (!add_nets) { + return wrapper_module; + } + /* The number of nets are the sum of input and output pins */ + size_t num_nets_to_reserve = 0; + for (ModulePortId new_port : module_ports(wrapper_module)) { + BasicPort new_port_info = module_port(wrapper_module, new_port); + num_nets_to_reserve += new_port_info.get_width(); + } + reserve_module_nets(wrapper_module, num_nets_to_reserve); + for (ModulePortId new_port : module_ports(wrapper_module)) { + BasicPort new_port_info = module_port(wrapper_module, new_port); + /* For each input pin, create a new source */ + ModuleManager::e_module_port_type new_port_type = + port_type(wrapper_module, new_port); + /* Check if the pin size are matching or not */ + ModulePortId existing_port = port_map[new_port]; + BasicPort existing_port_info = module_port(existing_module, existing_port); + VTR_ASSERT(existing_port_info == new_port_info); + if (new_port_type != + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT) { + for (size_t ipin = 0; ipin < new_port_info.pins().size(); ++ipin) { + /* Create new net */ + ModuleNetId new_net = create_module_net(wrapper_module); + VTR_ASSERT(valid_module_net_id(wrapper_module, new_net)); + add_module_net_source(wrapper_module, new_net, wrapper_module, 0, + new_port, new_port_info.pins()[ipin]); + add_module_net_sink(wrapper_module, new_net, existing_module, 0, + existing_port, existing_port_info.pins()[ipin]); + } + } else { + VTR_ASSERT_SAFE(new_port_type == + ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT); + for (size_t ipin = 0; ipin < new_port_info.pins().size(); ++ipin) { + /* Create new net */ + ModuleNetId new_net = create_module_net(wrapper_module); + VTR_ASSERT(valid_module_net_id(wrapper_module, new_net)); + add_module_net_source(wrapper_module, new_net, existing_module, 0, + existing_port, new_port_info.pins()[ipin]); + add_module_net_sink(wrapper_module, new_net, wrapper_module, 0, + new_port, existing_port_info.pins()[ipin]); + } + } + } + + return wrapper_module; +} + /****************************************************************************** * Public Deconstructor ******************************************************************************/ void ModuleManager::clear_configurable_children(const ModuleId& parent_module) { VTR_ASSERT(valid_module_id(parent_module)); - configurable_children_[parent_module].clear(); - configurable_child_instances_[parent_module].clear(); - configurable_child_regions_[parent_module].clear(); - configurable_child_coordinates_[parent_module].clear(); + logical_configurable_children_[parent_module].clear(); + logical_configurable_child_instances_[parent_module].clear(); + physical_configurable_children_[parent_module].clear(); + physical_configurable_child_instances_[parent_module].clear(); + physical_configurable_child_regions_[parent_module].clear(); + physical_configurable_child_coordinates_[parent_module].clear(); + + logical2physical_configurable_children_[parent_module].clear(); + logical2physical_configurable_child_instance_names_[parent_module].clear(); } void ModuleManager::clear_config_region(const ModuleId& parent_module) { @@ -1212,6 +1484,15 @@ void ModuleManager::clear_io_children(const ModuleId& parent_module) { io_child_coordinates_[parent_module].clear(); } +void ModuleManager::clear_module_net_sinks(const ModuleId& parent_module, + const ModuleNetId& net) { + VTR_ASSERT(valid_module_net_id(parent_module, net)); + net_sink_ids_[parent_module][net].clear(); + net_sink_terminal_ids_[parent_module][net].clear(); + net_sink_instance_ids_[parent_module][net].clear(); + net_sink_pin_ids_[parent_module][net].clear(); +} + /****************************************************************************** * Private validators/invalidators ******************************************************************************/ diff --git a/openfpga/src/fabric/module_manager.h b/openfpga/src/fabric/module_manager.h index 2c8633b42..235719cbc 100644 --- a/openfpga/src/fabric/module_manager.h +++ b/openfpga/src/fabric/module_manager.h @@ -53,8 +53,9 @@ class ModuleManager { * port should be applied to modules */ enum e_module_usage_type { - MODULE_TOP, /* Top-level module */ - MODULE_CONFIG, /* Configuration modules, i.e., decoders, sram etc. */ + MODULE_TOP, /* Top-level module */ + MODULE_CONFIG, /* Configuration modules, i.e., decoders, sram etc. */ + MODULE_CONFIG_GROUP, /* Configuration modules, i.e., decoders, sram etc. */ MODULE_INTERC, /* Programmable interconnection, e.g., routing multiplexer etc. */ MODULE_GRID, /* Grids (programmable blocks) */ @@ -68,6 +69,15 @@ class ModuleManager { NUM_MODULE_USAGE_TYPES }; + /* Type of configurable child: + * - logical: represent a logical configurable block, which may not contain a + * physical memory inside + * - physical: represent a physical configurable block, which contains a + * physical memory inside + * - unified: a unified block whose physical memory is also the logical memory + */ + enum class e_config_child_type { LOGICAL, PHYSICAL, UNIFIED, NUM_TYPES }; + public: /* Public Constructors */ public: /* Type implementations */ /* @@ -156,6 +166,11 @@ class ModuleManager { public: /* Public aggregators */ /* Find all the modules */ module_range modules() const; + /** @brief find all the modules with a given usage. Note that this function is + * not optimized when the number of modules are large. In most cases, the + * number of modules are fairly small (less than 10k). */ + std::vector modules_by_usage( + const ModuleManager::e_module_usage_type& usage) const; /* Find all the ports belonging to a module */ module_port_range module_ports(const ModuleId& module) const; /* Find all the nets belonging to a module */ @@ -167,14 +182,27 @@ class ModuleManager { const ModuleId& parent_module, const ModuleId& child_module) const; /* Find all the configurable child modules under a parent module */ std::vector configurable_children( - const ModuleId& parent_module) const; + const ModuleId& parent_module, const e_config_child_type& type) const; /* Find all the instances of configurable child modules under a parent module */ std::vector configurable_child_instances( - const ModuleId& parent_module) const; + const ModuleId& parent_module, const e_config_child_type& type) const; /* Find the coordindate of a configurable child module under a parent module */ std::vector> configurable_child_coordinates( + const ModuleId& parent_module, const e_config_child_type& type) const; + + /* Find all the configurable child modules under a parent module + * Note that a physical configurable child module may be at + * another module; Only the logical child module is under the current parent + * module + */ + std::vector logical2physical_configurable_children( + const ModuleId& parent_module) const; + /* Find all the instance names of configurable child modules under a parent + * module + */ + std::vector logical2physical_configurable_child_instance_names( const ModuleId& parent_module) const; /* Find all the I/O child modules under a parent module */ @@ -195,16 +223,17 @@ class ModuleManager { /* Find all the regions */ region_range regions(const ModuleId& module) const; /* Find all the configurable child modules under a region of a parent module + * Note that we use logical children here */ std::vector region_configurable_children( const ModuleId& parent_module, const ConfigRegionId& region) const; /* Find all the instances of configurable child modules under a region of a - * parent module */ + * parent module; Note that we use logical children here */ std::vector region_configurable_child_instances( const ModuleId& parent_module, const ConfigRegionId& region) const; /* Find all the coordinates of configurable child modules under a region of a - * parent module */ + * parent module; Note that we use logical children here */ std::vector> region_configurable_child_coordinates( const ModuleId& parent_module, const ConfigRegionId& region) const; @@ -238,6 +267,9 @@ class ModuleManager { size_t instance_id(const ModuleId& parent_module, const ModuleId& child_module, const std::string& instance_name) const; + /** @brief Count the number of logical configurable children */ + size_t num_configurable_children(const ModuleId& parent_module, + const e_config_child_type& type) const; /* Find the type of a port */ ModuleManager::e_module_port_type port_type(const ModuleId& module, const ModulePortId& port) const; @@ -295,6 +327,11 @@ class ModuleManager { const ModuleId& sink_module, const size_t& instance_id, const ModulePortId& sink_port, const size_t& sink_pin); + /** @brief Check if the configurable children under a given module are unified + * or not. If unified, it means that the logical configurable children are the + * same as the physical configurable children */ + bool unified_configurable_children(const ModuleId& curr_module) const; + private: /* Private accessors */ size_t find_child_module_index_in_parent_module( const ModuleId& parent_module, const ModuleId& child_module) const; @@ -317,6 +354,8 @@ class ModuleManager { /* Set a port to be a wire */ void set_port_is_wire(const ModuleId& module, const std::string& port_name, const bool& is_wire); + void set_port_is_wire(const ModuleId& module, const ModulePortId& port_id, + const bool& is_wire); /* Set a port to be mappable to an I/O from users' implemenations */ void set_port_is_mappable_io(const ModuleId& module, const ModulePortId& port_id, @@ -325,6 +364,8 @@ class ModuleManager { void set_port_is_register(const ModuleId& module, const std::string& port_name, const bool& is_register); + void set_port_is_register(const ModuleId& module, const ModulePortId& port_id, + const bool& is_register); /* Set the preprocessing flag for a port */ void set_port_preproc_flag(const ModuleId& module, const ModulePortId& port, const std::string& preproc_flag); @@ -353,18 +394,29 @@ class ModuleManager { */ void add_configurable_child( const ModuleId& module, const ModuleId& child_module, - const size_t& child_instance, + const size_t& child_instance, const e_config_child_type& type, const vtr::Point coord = vtr::Point(-1, -1)); + /** @brief Create a pair of mapping from a logical configurable child to a + * physical configurable child */ + void set_logical2physical_configurable_child( + const ModuleId& parent_module, const size_t& logical_child_id, + const ModuleId& physical_child_module); + /** @brief Create a pair of mapping from a logical configurable child to a + * physical configurable child */ + void set_logical2physical_configurable_child_instance_name( + const ModuleId& parent_module, const size_t& logical_child_id, + const std::string& physical_child_instance_name); /* Reserved a number of configurable children for memory efficiency */ void reserve_configurable_child(const ModuleId& module, - const size_t& num_children); + const size_t& num_children, + const e_config_child_type& type); /* Create a new configurable region under a module */ ConfigRegionId add_config_region(const ModuleId& module); /* Add a configurable child module to a region * Note: - * - The child module must be added as a configurable child to the parent - * module before calling this function! + * - The child module must be added as a physical configurable child to the + * parent module before calling this function! */ void add_configurable_child_to_region(const ModuleId& parent_module, const ConfigRegionId& config_region, @@ -423,6 +475,26 @@ class ModuleManager { const ModulePortId& sink_port, const size_t& sink_pin); + /** @brief Create a wrapper module on an existing module. The wrapper module + * will herit all the ports with the same direction, width and names from the + * selected module. The wrapper module will contain the existing module. For + * example, + * + * Wrapper module + * +------------------------+ + * | existing module | + * | +------------------+ | + * | | | | + * a ->+->+ a b-+--+-> b + * | | | | + * | +------------------+ | + * +------------------------+ + */ + ModuleId create_wrapper_module(const ModuleId& existing_module, + const std::string& wrapper_module_name, + const std::string& instance_name, + const bool& add_nets); + public: /* Public deconstructors */ /* This is a strong function which will remove all the configurable children * under a given parent module @@ -445,6 +517,10 @@ class ModuleManager { */ void clear_io_children(const ModuleId& parent_module); + /* Remove all the sinks for a given net under a module */ + void clear_module_net_sinks(const ModuleId& parent_module, + const ModuleNetId& net); + public: /* Public validators/invalidators */ bool valid_module_id(const ModuleId& module) const; bool valid_module_port_id(const ModuleId& module, @@ -483,23 +559,48 @@ class ModuleManager { * is configured first, etc. Note that the sequence can be totally different * from the children_ list This is really dependent how the configuration * protocol is organized which should be made by users/designers + * Note that there could be two types of configurable children under a module + * - logical: only contains virtual/feedthough memory blocks. A logical + * configurable child can only contain logical subchild. Logical memory block + * is required for architecture bitstream generation, because it carries + * logical information (the location of memory to its programmable resources) + * - physical: contains physical memory blocks. Logical memory blocks are + * mapped to the physical memory block. A physical memory block may contain + * coordinates and configuration regions which are required for fabric + * bitstream generation. */ vtr::vector> - configurable_children_; /* Child modules with configurable memory bits that - this module contain */ + logical_configurable_children_; /* Child modules with configurable memory + bits that this module contain */ vtr::vector> - configurable_child_instances_; /* Instances of child modules with + logical_configurable_child_instances_; /* Instances of child modules with + configurable memory bits that this module + contain */ + vtr::vector> + logical2physical_configurable_children_; /* Child modules with configurable + memory bits that this module contain */ + vtr::vector> + logical2physical_configurable_child_instance_names_; /* Instances of child + modules with configurable memory bits that + this module contain */ + + vtr::vector> + physical_configurable_children_; /* Child modules with configurable memory + bits that this module contain */ + vtr::vector> + physical_configurable_child_instances_; /* Instances of child modules with configurable memory bits that this module contain */ vtr::vector> - configurable_child_regions_; /* Instances of child modules with configurable - memory bits that this module contain */ + physical_configurable_child_regions_; /* Instances of child modules with + configurable memory bits that this module + contain */ vtr::vector>> - configurable_child_coordinates_; /* Relative coorindates of child modules - with configurable memory bits that this - module contain */ + physical_configurable_child_coordinates_; /* Relative coorindates of child + modules with configurable memory bits + that this module contain */ - /* Configurable regions to group the configurable children + /* Configurable regions to group the physical configurable children * Note: * - Each child can only be added a group */ diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index e4bd1b79c..69e723f05 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -35,15 +35,19 @@ static size_t rec_estimate_device_bitstream_num_blocks( * actually configurable memory elements * We skip them in couting */ - if (0 == module_manager.configurable_children(top_module).size()) { + if (0 == module_manager.num_configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL)) { return 0; } size_t num_configurable_children = - module_manager.configurable_children(top_module).size(); + module_manager + .configurable_children(top_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); for (size_t ichild = 0; ichild < num_configurable_children; ++ichild) { - ModuleId child_module = - module_manager.configurable_children(top_module)[ichild]; + ModuleId child_module = module_manager.configurable_children( + top_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild]; num_blocks += rec_estimate_device_bitstream_num_blocks(module_manager, child_module); } @@ -68,7 +72,8 @@ static size_t rec_estimate_device_bitstream_num_bits( /* If a child module has no configurable children, this is a leaf node * We can count it in. Otherwise, we should go recursively. */ - if (0 == module_manager.configurable_children(parent_module).size()) { + if (0 == module_manager.num_configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)) { return 1; } @@ -105,7 +110,10 @@ static size_t rec_estimate_device_bitstream_num_bits( VTR_ASSERT_SAFE(parent_module != top_module); size_t num_configurable_children = - module_manager.configurable_children(parent_module).size(); + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); /* Frame-based configuration protocol will have 1 decoder * if there are more than 1 configurable children @@ -116,8 +124,8 @@ static size_t rec_estimate_device_bitstream_num_bits( } for (size_t ichild = 0; ichild < num_configurable_children; ++ichild) { - ModuleId child_module = - module_manager.configurable_children(parent_module)[ichild]; + ModuleId child_module = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[ichild]; num_bits += rec_estimate_device_bitstream_num_bits( module_manager, top_module, child_module, config_protocol); } @@ -155,12 +163,29 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, */ std::string top_block_name = generate_fpga_top_module_name(); ConfigBlockId top_block = bitstream_manager.add_block(top_block_name); - const ModuleId& top_module = - openfpga_ctx.module_graph().find_module(top_block_name); + ModuleId top_module = openfpga_ctx.module_graph().find_module(top_block_name); VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module)); + /* Create the core block when the fpga_core is added */ + size_t num_blocks_to_reserve = 0; + std::string core_block_name = generate_fpga_core_module_name(); + const ModuleId& core_module = + openfpga_ctx.module_graph().find_module(core_block_name); + if (openfpga_ctx.module_graph().valid_module_id(core_module)) { + std::string core_inst_name = + openfpga_ctx.module_graph().instance_name(top_module, core_module, 0); + ConfigBlockId core_block = bitstream_manager.add_block(core_inst_name); + bitstream_manager.add_child_block(top_block, core_block); + /* Now we use the core_block as the top-level block for the remaining + * functions */ + top_module = core_module; + top_block = core_block; + /* Count in fpga core as a block to reserve */ + num_blocks_to_reserve += 1; + } + /* Estimate the number of blocks to be added to the database */ - size_t num_blocks_to_reserve = rec_estimate_device_bitstream_num_blocks( + num_blocks_to_reserve += rec_estimate_device_bitstream_num_blocks( openfpga_ctx.module_graph(), top_module); bitstream_manager.reserve_blocks(num_blocks_to_reserve); VTR_LOGV(verbose, "Reserved %lu configurable blocks\n", @@ -176,24 +201,27 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, /* Reserve child blocks for the top level block */ bitstream_manager.reserve_child_blocks( top_block, count_module_manager_module_configurable_children( - openfpga_ctx.module_graph(), top_module)); + openfpga_ctx.module_graph(), top_module, + ModuleManager::e_config_child_type::PHYSICAL)); /* Create bitstream from grids */ VTR_LOGV(verbose, "Building grid bitstream...\n"); - build_grid_bitstream( - bitstream_manager, top_block, openfpga_ctx.module_graph(), - openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), - vpr_ctx.device().grid, vpr_ctx.atom(), openfpga_ctx.vpr_device_annotation(), - openfpga_ctx.vpr_clustering_annotation(), - openfpga_ctx.vpr_placement_annotation(), - openfpga_ctx.vpr_bitstream_annotation(), verbose); + build_grid_bitstream(bitstream_manager, top_block, + openfpga_ctx.module_graph(), openfpga_ctx.fabric_tile(), + openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), + vpr_ctx.device().grid, 0, vpr_ctx.atom(), + openfpga_ctx.vpr_device_annotation(), + openfpga_ctx.vpr_clustering_annotation(), + openfpga_ctx.vpr_placement_annotation(), + openfpga_ctx.vpr_bitstream_annotation(), verbose); VTR_LOGV(verbose, "Done\n"); /* Create bitstream from routing architectures */ VTR_LOGV(verbose, "Building routing bitstream...\n"); build_routing_bitstream( bitstream_manager, top_block, openfpga_ctx.module_graph(), - openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), vpr_ctx.atom(), + openfpga_ctx.fabric_tile(), openfpga_ctx.arch().circuit_lib, + openfpga_ctx.mux_lib(), vpr_ctx.atom(), openfpga_ctx.vpr_device_annotation(), openfpga_ctx.vpr_routing_annotation(), vpr_ctx.device().rr_graph, openfpga_ctx.device_rr_gsb(), openfpga_ctx.flow_manager().compress_routing(), verbose); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index 141237841..edf20681c 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -39,7 +39,7 @@ static void rec_build_module_fabric_dependent_chain_bitstream( const ModuleManager& module_manager, const ModuleId& top_module, const ModuleId& parent_module, const ConfigRegionId& config_region, FabricBitstream& fabric_bitstream, - const FabricBitRegionId& fabric_bitstream_region) { + const FabricBitRegionId& fabric_bitstream_region, const bool& verbose) { /* Depth-first search: if we have any children in the parent_block, * we dive to the next level first! */ @@ -69,17 +69,22 @@ static void rec_build_module_fabric_dependent_chain_bitstream( rec_build_module_fabric_dependent_chain_bitstream( bitstream_manager, child_block, module_manager, top_module, child_module, config_region, fabric_bitstream, - fabric_bitstream_region); + fabric_bitstream_region, verbose); } } else { for (size_t child_id = 0; child_id < - module_manager.configurable_children(parent_module).size(); + module_manager + .configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++child_id) { - ModuleId child_module = - module_manager.configurable_children(parent_module)[child_id]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[child_id]; + ModuleId child_module = module_manager.configurable_children( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[child_id]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[child_id]; /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name( parent_module, child_module, child_instance); @@ -87,6 +92,11 @@ static void rec_build_module_fabric_dependent_chain_bitstream( /* Find the child block that matches the instance name! */ ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + VTR_LOGV(verbose, + "Try to find a configurable block corresponding to module " + "'%s' in FPGA fabric under its parent block '%s'\n", + instance_name.c_str(), + bitstream_manager.block_name(parent_block).c_str()); /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); @@ -94,7 +104,7 @@ static void rec_build_module_fabric_dependent_chain_bitstream( rec_build_module_fabric_dependent_chain_bitstream( bitstream_manager, child_block, module_manager, top_module, child_module, config_region, fabric_bitstream, - fabric_bitstream_region); + fabric_bitstream_region, verbose); } } /* Ensure that there should be no configuration bits in the parent block */ @@ -191,7 +201,8 @@ static void rec_build_module_fabric_dependent_memory_bank_bitstream( * - no need to exclude decoders as they are not there */ std::vector configurable_children = - module_manager.configurable_children(parent_module); + module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL); size_t num_configurable_children = configurable_children.size(); @@ -206,8 +217,9 @@ static void rec_build_module_fabric_dependent_memory_bank_bitstream( for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { ModuleId child_module = configurable_children[child_id]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[child_id]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[child_id]; /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name( @@ -318,10 +330,11 @@ static void rec_build_module_fabric_dependent_frame_bitstream( config_region); } else { VTR_ASSERT(top_module != parent_module); - configurable_children = - module_manager.configurable_children(parent_module); + configurable_children = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL); configurable_child_instances = - module_manager.configurable_child_instances(parent_module); + module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL); } size_t num_configurable_children = configurable_children.size(); @@ -355,10 +368,13 @@ static void rec_build_module_fabric_dependent_frame_bitstream( /* The max address code size is the max address code size of all the * configurable children in all the regions */ - for (const ModuleId& child_module : - module_manager.configurable_children(parent_module)) { + for (const ModuleId& child_module : module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)) { /* Bypass any decoder module (which no configurable children */ - if (module_manager.configurable_children(child_module).empty()) { + if (module_manager + .configurable_children( + child_module, ModuleManager::e_config_child_type::PHYSICAL) + .empty()) { continue; } const ModulePortId& child_addr_port_id = @@ -488,8 +504,8 @@ static void rec_build_module_fabric_dependent_frame_bitstream( parent_modules.back(), config_region); } else { VTR_ASSERT(top_module != parent_modules.back()); - configurable_children = - module_manager.configurable_children(parent_modules.back()); + configurable_children = module_manager.configurable_children( + parent_modules.back(), ModuleManager::e_config_child_type::PHYSICAL); } ModuleId decoder_module = configurable_children.back(); @@ -534,7 +550,7 @@ static void build_module_fabric_dependent_bitstream( const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, const BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, const ModuleManager& module_manager, const ModuleId& top_module, - FabricBitstream& fabric_bitstream) { + FabricBitstream& fabric_bitstream, const bool& verbose) { switch (config_protocol.type()) { case CONFIG_MEM_STANDALONE: { /* Reserve bits before build-up */ @@ -546,7 +562,7 @@ static void build_module_fabric_dependent_bitstream( fabric_bitstream.add_region(); rec_build_module_fabric_dependent_chain_bitstream( bitstream_manager, top_block, module_manager, top_module, top_module, - config_region, fabric_bitstream, fabric_bitstream_region); + config_region, fabric_bitstream, fabric_bitstream_region, verbose); } break; @@ -561,7 +577,7 @@ static void build_module_fabric_dependent_bitstream( fabric_bitstream.add_region(); rec_build_module_fabric_dependent_chain_bitstream( bitstream_manager, top_block, module_manager, top_module, top_module, - config_region, fabric_bitstream, fabric_bitstream_region); + config_region, fabric_bitstream, fabric_bitstream_region, verbose); fabric_bitstream.reverse_region_bits(fabric_bitstream_region); } break; @@ -768,17 +784,30 @@ FabricBitstream build_fabric_dependent_bitstream( VTR_ASSERT(true == module_manager.valid_module_id(top_module)); /* Find the top block in bitstream manager, which has not parents */ - std::vector top_block = + std::vector top_blocks = find_bitstream_manager_top_blocks(bitstream_manager); /* Make sure we have only 1 top block and its name matches the top module */ - VTR_ASSERT(1 == top_block.size()); + VTR_ASSERT(1 == top_blocks.size()); VTR_ASSERT( - 0 == top_module_name.compare(bitstream_manager.block_name(top_block[0]))); + 0 == top_module_name.compare(bitstream_manager.block_name(top_blocks[0]))); + ConfigBlockId top_block = top_blocks[0]; + + /* Create the core block when the fpga_core is added */ + std::string core_block_name = generate_fpga_core_module_name(); + const ModuleId& core_module = module_manager.find_module(core_block_name); + if (module_manager.valid_module_id(core_module)) { + /* Now we use the core_block as the top-level block for the remaining + * functions */ + VTR_ASSERT(bitstream_manager.block_children(top_block).size() == 1); + ConfigBlockId core_block = bitstream_manager.block_children(top_block)[0]; + top_module = core_module; + top_block = core_block; + } /* Start build-up formally */ build_module_fabric_dependent_bitstream( - config_protocol, circuit_lib, bitstream_manager, top_block[0], - module_manager, top_module, fabric_bitstream); + config_protocol, circuit_lib, bitstream_manager, top_block, module_manager, + top_module, fabric_bitstream, verbose); VTR_LOGV(verbose, "Built %lu configuration bits for fabric\n", fabric_bitstream.num_bits()); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 97fe97d90..05b6a57b2 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -123,7 +123,8 @@ static void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( * - no need to exclude decoders as they are not there */ std::vector configurable_children = - module_manager.configurable_children(parent_module); + module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL); size_t num_configurable_children = configurable_children.size(); @@ -138,8 +139,9 @@ static void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { ModuleId child_module = configurable_children[child_id]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[child_id]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, + ModuleManager::e_config_child_type::PHYSICAL)[child_id]; /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name( @@ -174,6 +176,11 @@ static void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( bitstream_manager.block_bits(parent_block)) { FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit); + /* + If both BL and WL protocols are Flatten, we will have new way of + storing information in fabric_bitstream. This will save high + memory usage, as well as fast processing + */ /* The BL address to be decoded depends on the protocol * - flatten BLs: use 1-hot decoding * - BL decoders: fully encoded @@ -181,38 +188,57 @@ static void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream( */ size_t cur_bl_index = bl_start_index_per_tile.at(tile_coord.x()) + cur_mem_index[tile_coord] % num_bls_cur_tile; - std::vector bl_addr_bits_vec; - if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { - bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); - } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() || - BLWL_PROTOCOL_SHIFT_REGISTER == - config_protocol.bl_protocol_type()) { - bl_addr_bits_vec = - ito1hot_charvec(cur_bl_index, bl_addr_size, DONT_CARE_CHAR); + if (BLWL_PROTOCOL_FLATTEN != config_protocol.bl_protocol_type() || + BLWL_PROTOCOL_FLATTEN != config_protocol.wl_protocol_type()) { + // This is using old way + // We only do this kind of resource wasting storing if + // either protocol is not flatten + std::vector bl_addr_bits_vec; + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() || + BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.bl_protocol_type()) { + bl_addr_bits_vec = + ito1hot_charvec(cur_bl_index, bl_addr_size, DONT_CARE_CHAR); + } + /* Set BL address */ + fabric_bitstream.set_bit_bl_address( + fabric_bit, bl_addr_bits_vec, + BLWL_PROTOCOL_DECODER != config_protocol.bl_protocol_type()); } /* Find WL address */ size_t cur_wl_index = wl_start_index_per_tile.at(tile_coord.y()) + std::floor(cur_mem_index[tile_coord] / num_bls_cur_tile); - std::vector wl_addr_bits_vec; - if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { - wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); - } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type() || - BLWL_PROTOCOL_SHIFT_REGISTER == - config_protocol.wl_protocol_type()) { - wl_addr_bits_vec = ito1hot_charvec(cur_wl_index, wl_addr_size); + if (BLWL_PROTOCOL_FLATTEN != config_protocol.bl_protocol_type() || + BLWL_PROTOCOL_FLATTEN != config_protocol.wl_protocol_type()) { + // This is using old way + // We only do this kind of resource wasting storing if + // either protocol is not flatten + std::vector wl_addr_bits_vec; + if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { + wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type() || + BLWL_PROTOCOL_SHIFT_REGISTER == + config_protocol.wl_protocol_type()) { + wl_addr_bits_vec = ito1hot_charvec(cur_wl_index, wl_addr_size); + } + /* Set WL address */ + fabric_bitstream.set_bit_wl_address( + fabric_bit, wl_addr_bits_vec, + BLWL_PROTOCOL_DECODER != config_protocol.wl_protocol_type()); + } + if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() && + BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + // New way of storing information in compact way + // Only for Flatten protocol (can easily support shift register as well) + // Need to understand decoder to better assessment + fabric_bitstream.set_memory_bank_info( + fabric_bit, fabric_bitstream_region, cur_bl_index, cur_wl_index, + bl_addr_size, wl_addr_size, bitstream_manager.bit_value(config_bit)); } - - /* Set BL address */ - fabric_bitstream.set_bit_bl_address( - fabric_bit, bl_addr_bits_vec, - BLWL_PROTOCOL_DECODER != config_protocol.bl_protocol_type()); - - /* Set WL address */ - fabric_bitstream.set_bit_wl_address( - fabric_bit, wl_addr_bits_vec, - BLWL_PROTOCOL_DECODER != config_protocol.wl_protocol_type()); /* Set data input */ fabric_bitstream.set_bit_din(fabric_bit, diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp index 52f07e4db..df3f070aa 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.cpp @@ -50,10 +50,12 @@ static std::vector generate_mode_select_bitstream( *******************************************************************/ static void build_primitive_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& device_annotation, const PhysicalPb& physical_pb, - const PhysicalPbId& primitive_pb_id, t_pb_type* primitive_pb_type) { + const PhysicalPbId& primitive_pb_id, t_pb_type* primitive_pb_type, + const bool& verbose) { /* Ensure a valid physical pritimive pb */ if (nullptr == primitive_pb_type) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid primitive_pb_type!\n"); @@ -131,11 +133,34 @@ static void build_primitive_bitstream( mode_select_bitstream.size() == module_manager.module_port(mem_module, mem_out_port_id).get_width()); + /* If there is a feedthrough module, we should consider the scoreboard */ + std::string feedthru_mem_block_name = + generate_memory_module_name(circuit_lib, primitive_model, sram_models[0], + std::string(MEMORY_MODULE_POSTFIX), true); + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_mem_block_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + auto result = grouped_mem_inst_scoreboard.find(mem_block_name); + if (result == grouped_mem_inst_scoreboard.end()) { + /* Update scoreboard */ + grouped_mem_inst_scoreboard[mem_block_name] = 0; + } else { + grouped_mem_inst_scoreboard[mem_block_name]++; + mem_block_name = generate_instance_name( + mem_block_name, grouped_mem_inst_scoreboard[mem_block_name]); + } + } + /* Create a block for the bitstream which corresponds to the memory module * associated to the LUT */ ConfigBlockId mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(parent_configurable_block, mem_block); + VTR_LOGV(verbose, "Added %lu bits to '%s' under '%s'\n", + mode_select_bitstream.size(), + bitstream_manager.block_name(mem_block).c_str(), + bitstream_manager.block_name(parent_configurable_block).c_str()); + /* Add the bitstream to the bitstream manager */ bitstream_manager.add_block_bits(mem_block, mode_select_bitstream); } @@ -153,13 +178,14 @@ static void build_primitive_bitstream( *******************************************************************/ static void build_physical_block_pin_interc_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, const PhysicalPb& physical_pb, t_pb_graph_pin* des_pb_graph_pin, - t_mode* physical_mode) { + t_mode* physical_mode, const bool& verbose) { /* Identify the number of fan-in (Consider interconnection edges of only * selected mode) */ t_interconnect* cur_interc = @@ -258,9 +284,6 @@ static void build_physical_block_pin_interc_bitstream( * physical_block */ std::string mem_block_name = generate_pb_memory_instance_name( GRID_MEM_INSTANCE_PREFIX, des_pb_graph_pin, std::string("")); - ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); - bitstream_manager.add_child_block(parent_configurable_block, - mux_mem_block); /* Find the module in module manager and ensure the bitstream size * matches! */ @@ -275,6 +298,32 @@ static void build_physical_block_pin_interc_bitstream( module_manager.module_port(mux_mem_module, mux_mem_out_port_id) .get_width()); + /* If there is a feedthrough module, we should consider the scoreboard */ + std::string feedthru_mem_block_name = generate_mux_subckt_name( + circuit_lib, mux_model, datapath_mux_size, + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_mem_block_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + auto result = grouped_mem_inst_scoreboard.find(mem_block_name); + if (result == grouped_mem_inst_scoreboard.end()) { + /* Update scoreboard */ + grouped_mem_inst_scoreboard[mem_block_name] = 0; + } else { + grouped_mem_inst_scoreboard[mem_block_name]++; + mem_block_name = generate_instance_name( + mem_block_name, grouped_mem_inst_scoreboard[mem_block_name]); + } + } + ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); + bitstream_manager.add_child_block(parent_configurable_block, + mux_mem_block); + + VTR_LOGV(verbose, "Added %lu bits to '%s' under '%s'\n", + mux_bitstream.size(), + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(parent_configurable_block).c_str()); + /* Add the bistream to the bitstream manager */ bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); /* Record path ids, input and output nets */ @@ -324,13 +373,15 @@ static void build_physical_block_pin_interc_bitstream( *******************************************************************/ static void build_physical_block_interc_port_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, - const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode) { + const e_circuit_pb_port_type& pb_port_type, t_mode* physical_mode, + const bool& verbose) { switch (pb_port_type) { case CIRCUIT_PB_PORT_INPUT: for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; @@ -338,10 +389,11 @@ static void build_physical_block_interc_port_bitstream( for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, physical_pb, - &(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, + &(physical_pb_graph_node->input_pins[iport][ipin]), physical_mode, + verbose); } } break; @@ -351,10 +403,11 @@ static void build_physical_block_interc_port_bitstream( for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, physical_pb, - &(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, + &(physical_pb_graph_node->output_pins[iport][ipin]), physical_mode, + verbose); } } break; @@ -364,10 +417,11 @@ static void build_physical_block_interc_port_bitstream( for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) { build_physical_block_pin_interc_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, physical_pb, - &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, physical_pb, + &(physical_pb_graph_node->clock_pins[iport][ipin]), physical_mode, + verbose); } } break; @@ -383,13 +437,14 @@ static void build_physical_block_interc_port_bitstream( *******************************************************************/ static void build_physical_block_interc_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, t_pb_graph_node* physical_pb_graph_node, const PhysicalPb& physical_pb, - t_mode* physical_mode) { + t_mode* physical_mode, const bool& verbose) { /* Check if the pb_graph node is valid or not */ if (nullptr == physical_pb_graph_node) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid physical_pb_graph_node.\n"); @@ -407,9 +462,10 @@ static void build_physical_block_interc_bitstream( * Note: it is not applied to primitive pb_type! */ build_physical_block_interc_port_bitstream( - bitstream_manager, parent_configurable_block, module_manager, circuit_lib, - mux_lib, atom_ctx, device_annotation, bitstream_annotation, - physical_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_OUTPUT, physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, parent_configurable_block, + module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, physical_pb_graph_node, physical_pb, + CIRCUIT_PB_PORT_OUTPUT, physical_mode, verbose); /* We check input_pins of child_pb_graph_node and its the input_edges * Iterate over the interconnections between inputs of physical_pb_graph_node @@ -429,14 +485,16 @@ static void build_physical_block_interc_bitstream( /* For each child_pb_graph_node input pins*/ build_physical_block_interc_port_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, - child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, + physical_pb, CIRCUIT_PB_PORT_INPUT, physical_mode, verbose); /* For clock pins, we should do the same work */ build_physical_block_interc_port_bitstream( - bitstream_manager, parent_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, bitstream_annotation, - child_pb_graph_node, physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, + parent_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, child_pb_graph_node, + physical_pb, CIRCUIT_PB_PORT_CLOCK, physical_mode, verbose); } } } @@ -445,15 +503,14 @@ static void build_physical_block_interc_bitstream( * Generate bitstream for a LUT and add it to bitstream manager * This function supports both single-output and fracturable LUTs *******************************************************************/ -static void build_lut_bitstream(BitstreamManager& bitstream_manager, - const ConfigBlockId& parent_configurable_block, - const VprDeviceAnnotation& device_annotation, - const ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, - const PhysicalPb& physical_pb, - const PhysicalPbId& lut_pb_id, - t_pb_type* lut_pb_type) { +static void build_lut_bitstream( + BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, + const ConfigBlockId& parent_configurable_block, + const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const MuxLibrary& mux_lib, const PhysicalPb& physical_pb, + const PhysicalPbId& lut_pb_id, t_pb_type* lut_pb_type, const bool& verbose) { /* Ensure a valid physical pritimive pb */ if (nullptr == lut_pb_type) { VTR_LOGF_ERROR(__FILE__, __LINE__, "Invalid lut_pb_type!\n"); @@ -594,11 +651,33 @@ static void build_lut_bitstream(BitstreamManager& bitstream_manager, lut_bitstream.size() == module_manager.module_port(mem_module, mem_out_port_id).get_width()); + /* If there is a feedthrough module, we should consider the scoreboard */ + std::string feedthru_mem_block_name = + generate_memory_module_name(circuit_lib, lut_model, sram_models[0], + std::string(MEMORY_MODULE_POSTFIX), true); + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_mem_block_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + auto result = grouped_mem_inst_scoreboard.find(mem_block_name); + if (result == grouped_mem_inst_scoreboard.end()) { + /* Update scoreboard */ + grouped_mem_inst_scoreboard[mem_block_name] = 0; + } else { + grouped_mem_inst_scoreboard[mem_block_name]++; + mem_block_name = generate_instance_name( + mem_block_name, grouped_mem_inst_scoreboard[mem_block_name]); + } + } + /* Create a block for the bitstream which corresponds to the memory module * associated to the LUT */ ConfigBlockId mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(parent_configurable_block, mem_block); + VTR_LOGV(verbose, "Added %lu bits to '%s' under '%s'\n", lut_bitstream.size(), + bitstream_manager.block_name(mem_block).c_str(), + bitstream_manager.block_name(parent_configurable_block).c_str()); + /* Add the bitstream to the bitstream manager */ bitstream_manager.add_block_bits(mem_block, lut_bitstream); } @@ -616,13 +695,15 @@ static void build_lut_bitstream(BitstreamManager& bitstream_manager, *******************************************************************/ static void rec_build_physical_block_bitstream( BitstreamManager& bitstream_manager, + std::map& grouped_mem_inst_scoreboard, const ConfigBlockId& parent_configurable_block, const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprBitstreamAnnotation& bitstream_annotation, const e_side& border_side, const PhysicalPb& physical_pb, const PhysicalPbId& pb_id, - t_pb_graph_node* physical_pb_graph_node, const size_t& pb_graph_node_index) { + t_pb_graph_node* physical_pb_graph_node, const size_t& pb_graph_node_index, + const bool& verbose) { /* Get the physical pb_type that is linked to the pb_graph node */ t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type; @@ -636,7 +717,8 @@ static void rec_build_physical_block_bitstream( VTR_ASSERT(true == module_manager.valid_module_id(pb_module)); /* Skip module with no configurable children */ - if (0 == module_manager.configurable_children(pb_module).size()) { + if (0 == module_manager.num_configurable_children( + pb_module, ModuleManager::e_config_child_type::LOGICAL)) { return; } @@ -644,16 +726,21 @@ static void rec_build_physical_block_bitstream( * manager */ std::string pb_block_name = generate_physical_block_instance_name( physical_pb_type, pb_graph_node_index); - ConfigBlockId pb_configurable_block = - bitstream_manager.add_block(pb_block_name); - bitstream_manager.add_child_block(parent_configurable_block, - pb_configurable_block); - - /* Reserve child blocks for new created block */ - bitstream_manager.reserve_child_blocks( - parent_configurable_block, - count_module_manager_module_configurable_children(module_manager, - pb_module)); + /* If there are no physical memory blocks under the current module, use the + * previous module, which is the physical memory block */ + ConfigBlockId pb_configurable_block = parent_configurable_block; + if (0 < module_manager.num_configurable_children( + pb_module, ModuleManager::e_config_child_type::PHYSICAL)) { + pb_configurable_block = bitstream_manager.add_block(pb_block_name); + bitstream_manager.add_child_block(parent_configurable_block, + pb_configurable_block); + /* Reserve child blocks for new created block */ + bitstream_manager.reserve_child_blocks( + parent_configurable_block, + count_module_manager_module_configurable_children( + module_manager, pb_module, + ModuleManager::e_config_child_type::PHYSICAL)); + } /* Recursively finish all the child pb_types*/ if (false == is_primitive_pb_type(physical_pb_type)) { @@ -670,12 +757,12 @@ static void rec_build_physical_block_bitstream( } /* Go recursively */ rec_build_physical_block_bitstream( - bitstream_manager, pb_configurable_block, module_manager, circuit_lib, - mux_lib, atom_ctx, device_annotation, bitstream_annotation, - border_side, physical_pb, child_pb, + bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, + module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, border_side, physical_pb, child_pb, &(physical_pb_graph_node ->child_pb_graph_nodes[physical_mode->index][ipb][jpb]), - jpb); + jpb, verbose); } } } @@ -690,17 +777,19 @@ static void rec_build_physical_block_bitstream( /* Special case for LUT !!! * Mapped logical block information is stored in child_pbs of this pb!!! */ - build_lut_bitstream(bitstream_manager, pb_configurable_block, - device_annotation, module_manager, circuit_lib, - mux_lib, physical_pb, pb_id, physical_pb_type); + build_lut_bitstream(bitstream_manager, grouped_mem_inst_scoreboard, + pb_configurable_block, device_annotation, + module_manager, circuit_lib, mux_lib, physical_pb, + pb_id, physical_pb_type, verbose); break; case CIRCUIT_MODEL_FF: case CIRCUIT_MODEL_HARDLOGIC: case CIRCUIT_MODEL_IOPAD: /* For other types of blocks, we can apply a generic therapy */ build_primitive_bitstream( - bitstream_manager, pb_configurable_block, module_manager, circuit_lib, - device_annotation, physical_pb, pb_id, physical_pb_type); + bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, + module_manager, circuit_lib, device_annotation, physical_pb, pb_id, + physical_pb_type, verbose); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -714,9 +803,10 @@ static void rec_build_physical_block_bitstream( /* Generate the bitstream for the interconnection in this physical block */ build_physical_block_interc_bitstream( - bitstream_manager, pb_configurable_block, module_manager, circuit_lib, - mux_lib, atom_ctx, device_annotation, bitstream_annotation, - physical_pb_graph_node, physical_pb, physical_mode); + bitstream_manager, grouped_mem_inst_scoreboard, pb_configurable_block, + module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, + bitstream_annotation, physical_pb_graph_node, physical_pb, physical_mode, + verbose); } /******************************************************************** @@ -727,16 +817,18 @@ static void rec_build_physical_block_bitstream( *******************************************************************/ static void build_physical_block_bitstream( BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, - const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const ModuleManager& module_manager, const FabricTile& fabric_tile, + const FabricTileId& curr_tile, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, const VprBitstreamAnnotation& bitstream_annotation, const DeviceGrid& grids, - const vtr::Point& grid_coord, const e_side& border_side) { + const size_t& layer, const vtr::Point& grid_coord, + const e_side& border_side, const bool& verbose) { /* Create a block for the grid in bitstream manager */ - t_physical_tile_type_ptr grid_type = - grids[grid_coord.x()][grid_coord.y()].type; + t_physical_tile_type_ptr grid_type = grids.get_physical_type( + t_physical_tile_loc(grid_coord.x(), grid_coord.y(), layer)); std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); /* Early exit if this parent module has no configurable child modules */ @@ -747,13 +839,22 @@ static void build_physical_block_bitstream( VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); /* Skip module with no configurable children */ - if (0 == module_manager.configurable_children(grid_module).size()) { + if (0 == module_manager.num_configurable_children( + grid_module, ModuleManager::e_config_child_type::LOGICAL)) { return; } + vtr::Point grid_coord_in_unique_tile = grid_coord; + if (fabric_tile.valid_tile_id(curr_tile)) { + /* For tile modules, need to find the specific instance name under its + * unique tile */ + grid_coord_in_unique_tile = + fabric_tile.find_pb_coordinate_in_unique_tile(curr_tile, grid_coord); + } std::string grid_block_name = generate_grid_block_instance_name( grid_module_name_prefix, std::string(grid_type->name), - is_io_type(grid_type), border_side, grid_coord); + is_io_type(grid_type), border_side, grid_coord_in_unique_tile); + ConfigBlockId grid_configurable_block = bitstream_manager.add_block(grid_block_name); bitstream_manager.add_child_block(top_block, grid_configurable_block); @@ -761,7 +862,33 @@ static void build_physical_block_bitstream( /* Reserve child blocks for new created block */ bitstream_manager.reserve_child_blocks( grid_configurable_block, count_module_manager_module_configurable_children( - module_manager, grid_module)); + module_manager, grid_module, + ModuleManager::e_config_child_type::PHYSICAL)); + + /* Create a dedicated block for the non-unified configurable child */ + if (!module_manager.unified_configurable_children(grid_module)) { + VTR_ASSERT(1 == + module_manager + .configurable_children( + grid_module, ModuleManager::e_config_child_type::PHYSICAL) + .size()); + std::string phy_mem_instance_name = module_manager.instance_name( + grid_module, + module_manager.configurable_children( + grid_module, ModuleManager::e_config_child_type::PHYSICAL)[0], + module_manager.configurable_child_instances( + grid_module, ModuleManager::e_config_child_type::PHYSICAL)[0]); + ConfigBlockId grid_grouped_config_block = + bitstream_manager.add_block(phy_mem_instance_name); + VTR_LOGV( + verbose, + "Added grouped configurable memory block '%s' as a child to '%s'\n", + bitstream_manager.block_name(grid_grouped_config_block).c_str(), + bitstream_manager.block_name(grid_configurable_block).c_str()); + bitstream_manager.add_child_block(grid_configurable_block, + grid_grouped_config_block); + grid_configurable_block = grid_grouped_config_block; + } /* Iterate over the capacity of the grid * Now each physical tile may have a number of logical blocks @@ -771,6 +898,7 @@ static void build_physical_block_bitstream( * If you need different equivalent sites, you can always define * it as a mode under a */ + std::map grouped_mem_inst_scoreboard; for (size_t z = 0; z < place_annotation.grid_blocks(grid_coord).size(); ++z) { int sub_tile_index = device_annotation.physical_tile_z_to_subtile_index(grid_type, z); @@ -787,10 +915,11 @@ static void build_physical_block_bitstream( place_annotation.grid_blocks(grid_coord)[z]) { /* Recursively traverse the pb_graph and generate bitstream */ rec_build_physical_block_bitstream( - bitstream_manager, grid_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, border_side, PhysicalPb(), - PhysicalPbId::INVALID(), lb_type->pb_graph_head, z); + bitstream_manager, grouped_mem_inst_scoreboard, + grid_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, border_side, + PhysicalPb(), PhysicalPbId::INVALID(), lb_type->pb_graph_head, z, + verbose); } else { const PhysicalPb& phy_pb = cluster_annotation.physical_pb( place_annotation.grid_blocks(grid_coord)[z]); @@ -802,10 +931,10 @@ static void build_physical_block_bitstream( /* Recursively traverse the pb_graph and generate bitstream */ rec_build_physical_block_bitstream( - bitstream_manager, grid_configurable_block, module_manager, - circuit_lib, mux_lib, atom_ctx, device_annotation, - bitstream_annotation, border_side, phy_pb, top_pb_id, pb_graph_head, - z); + bitstream_manager, grouped_mem_inst_scoreboard, + grid_configurable_block, module_manager, circuit_lib, mux_lib, + atom_ctx, device_annotation, bitstream_annotation, border_side, + phy_pb, top_pb_id, pb_graph_head, z, verbose); } } } @@ -819,9 +948,10 @@ static void build_physical_block_bitstream( *******************************************************************/ void build_grid_bitstream( BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, - const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, const DeviceGrid& grids, - const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const FabricTile& fabric_tile, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const DeviceGrid& grids, const size_t& layer, const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose) { @@ -830,21 +960,42 @@ void build_grid_bitstream( /* Generate bitstream for the core logic block one by one */ for (size_t ix = 1; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + t_physical_tile_loc phy_tile_loc(ix, iy, layer); /* Bypass EMPTY grid */ - if (true == is_empty_type(grids[ix][iy].type)) { + if (true == is_empty_type(grids.get_physical_type(phy_tile_loc))) { continue; } /* Skip width > 1 or height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[ix][iy].width_offset) || - (0 < grids[ix][iy].height_offset)) { + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { continue; } /* Add a grid module to top_module*/ vtr::Point grid_coord(ix, iy); + /* TODO: If the fabric tile is not empty, find the tile module and create + * the block accordingly. Also to support future hierarchy changes, when + * creating the blocks, trace backward until reach the current top block. + * If any block is missing during the back tracing, create it. */ + ConfigBlockId parent_block = top_block; + FabricTileId curr_tile = + fabric_tile.find_tile_by_pb_coordinate(grid_coord); + if (fabric_tile.valid_tile_id(curr_tile)) { + vtr::Point tile_coord = fabric_tile.tile_coordinate(curr_tile); + std::string tile_inst_name = generate_tile_module_name(tile_coord); + parent_block = bitstream_manager.find_or_create_child_block( + top_block, tile_inst_name); + VTR_LOGV(verbose, + "Add configurable block '%s' as a child under configurable " + "block '%s'\n", + tile_inst_name.c_str(), + bitstream_manager.block_name(top_block).c_str()); + } + build_physical_block_bitstream( - bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, cluster_annotation, place_annotation, - bitstream_annotation, grids, grid_coord, NUM_SIDES); + bitstream_manager, parent_block, module_manager, fabric_tile, curr_tile, + circuit_lib, mux_lib, atom_ctx, device_annotation, cluster_annotation, + place_annotation, bitstream_annotation, grids, layer, grid_coord, + NUM_SIDES, verbose); } } VTR_LOGV(verbose, "Done\n"); @@ -858,20 +1009,41 @@ void build_grid_bitstream( /* Add instances of I/O grids to top_module */ for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { for (const vtr::Point& io_coordinate : io_coordinates[io_side]) { + t_physical_tile_loc phy_tile_loc(io_coordinate.x(), io_coordinate.y(), + layer); /* Bypass EMPTY grid */ - if (true == - is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { + if (true == is_empty_type(grids.get_physical_type(phy_tile_loc))) { continue; } /* Skip height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) || - (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { + if ((0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { continue; } + /* TODO: If the fabric tile is not empty, find the tile module and create + * the block accordingly. Also to support future hierarchy changes, when + * creating the blocks, trace backward until reach the current top block. + * If any block is missing during the back tracing, create it. */ + ConfigBlockId parent_block = top_block; + FabricTileId curr_tile = + fabric_tile.find_tile_by_pb_coordinate(io_coordinate); + if (fabric_tile.valid_tile_id(curr_tile)) { + vtr::Point tile_coord = fabric_tile.tile_coordinate(curr_tile); + std::string tile_inst_name = generate_tile_module_name(tile_coord); + parent_block = bitstream_manager.find_or_create_child_block( + top_block, tile_inst_name); + VTR_LOGV(verbose, + "Add configurable block '%s' as a child under configurable " + "block '%s'\n", + tile_inst_name.c_str(), + bitstream_manager.block_name(parent_block).c_str()); + } + build_physical_block_bitstream( - bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, cluster_annotation, place_annotation, - bitstream_annotation, grids, io_coordinate, io_side); + bitstream_manager, parent_block, module_manager, fabric_tile, curr_tile, + circuit_lib, mux_lib, atom_ctx, device_annotation, cluster_annotation, + place_annotation, bitstream_annotation, grids, layer, io_coordinate, + io_side, verbose); } } VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/fpga_bitstream/build_grid_bitstream.h b/openfpga/src/fpga_bitstream/build_grid_bitstream.h index 36597918a..a3f4f2603 100644 --- a/openfpga/src/fpga_bitstream/build_grid_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_grid_bitstream.h @@ -9,6 +9,7 @@ #include "bitstream_manager.h" #include "circuit_library.h" #include "device_grid.h" +#include "fabric_tile.h" #include "module_manager.h" #include "mux_library.h" #include "vpr_bitstream_annotation.h" @@ -26,9 +27,10 @@ namespace openfpga { void build_grid_bitstream( BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, - const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, const DeviceGrid& grids, - const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const FabricTile& fabric_tile, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const DeviceGrid& grids, const size_t& layer, const AtomContext& atom_ctx, + const VprDeviceAnnotation& device_annotation, const VprClusteringAnnotation& cluster_annotation, const VprPlacementAnnotation& place_annotation, const VprBitstreamAnnotation& bitstream_annotation, const bool& verbose); diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp index c2d2e18ae..0c1d7c31e 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.cpp @@ -37,7 +37,7 @@ static void build_switch_block_mux_bitstream( const MuxLibrary& mux_lib, const RRGraphView& rr_graph, const RRNodeId& cur_rr_node, const std::vector& drive_rr_nodes, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, - const VprRoutingAnnotation& routing_annotation) { + const VprRoutingAnnotation& routing_annotation, const bool& verbose) { /* Check current rr_node is CHANX or CHANY*/ VTR_ASSERT((CHANX == rr_graph.node_type(cur_rr_node)) || (CHANY == rr_graph.node_type(cur_rr_node))); @@ -102,6 +102,12 @@ static void build_switch_block_mux_bitstream( module_manager.module_port(mux_mem_module, mux_mem_out_port_id) .get_width()); + VTR_LOGV( + verbose, "Added %lu bits to '%s' under '%s'\n", mux_bitstream.size(), + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(bitstream_manager.block_parent(mux_mem_block)) + .c_str()); + /* Add the bistream to the bitstream manager */ bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); /* Record path ids, input and output nets */ @@ -150,7 +156,7 @@ static void build_switch_block_interc_bitstream( const MuxLibrary& mux_lib, const RRGraphView& rr_graph, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGSB& rr_gsb, - const e_side& chan_side, const size_t& chan_node_id) { + const e_side& chan_side, const size_t& chan_node_id, const bool& verbose) { std::vector driver_rr_nodes; /* Get the node */ @@ -179,11 +185,14 @@ static void build_switch_block_interc_bitstream( std::string("")); ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(sb_configurable_block, mux_mem_block); + VTR_LOGV(verbose, "Added '%s' under '%s'\n", + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(sb_configurable_block).c_str()); /* This is a routing multiplexer! Generate bitstream */ build_switch_block_mux_bitstream( bitstream_manager, mux_mem_block, module_manager, circuit_lib, mux_lib, rr_graph, cur_rr_node, driver_rr_nodes, atom_ctx, device_annotation, - routing_annotation); + routing_annotation, verbose); } /*Nothing should be done else*/ } @@ -204,7 +213,7 @@ static void build_switch_block_bitstream( const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, - const RRGSB& rr_gsb) { + const RRGSB& rr_gsb, const bool& verbose) { /* Iterate over all the multiplexers */ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { SideManager side_manager(side); @@ -222,7 +231,7 @@ static void build_switch_block_bitstream( build_switch_block_interc_bitstream( bitstream_manager, sb_config_block, module_manager, circuit_lib, mux_lib, rr_graph, atom_ctx, device_annotation, routing_annotation, - rr_gsb, side_manager.get_side(), itrack); + rr_gsb, side_manager.get_side(), itrack, verbose); } } } @@ -240,7 +249,8 @@ static void build_connection_block_mux_bitstream( const MuxLibrary& mux_lib, const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, - const RRGSB& rr_gsb, const e_side& cb_ipin_side, const size_t& ipin_index) { + const RRGSB& rr_gsb, const e_side& cb_ipin_side, const size_t& ipin_index, + const bool& verbose) { RRNodeId src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index); /* Find drive_rr_nodes*/ std::vector driver_rr_edges = @@ -308,6 +318,12 @@ static void build_connection_block_mux_bitstream( module_manager.module_port(mux_mem_module, mux_mem_out_port_id) .get_width()); + VTR_LOGV( + verbose, "Added %lu bits to '%s' under '%s'\n", mux_bitstream.size(), + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(bitstream_manager.block_parent(mux_mem_block)) + .c_str()); + /* Add the bistream to the bitstream manager */ bitstream_manager.add_block_bits(mux_mem_block, mux_bitstream); /* Record path ids, input and output nets */ @@ -381,11 +397,14 @@ static void build_connection_block_interc_bitstream( std::string("")); ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name); bitstream_manager.add_child_block(cb_configurable_block, mux_mem_block); + VTR_LOGV(verbose, "Added '%s' under '%s'\n", + bitstream_manager.block_name(mux_mem_block).c_str(), + bitstream_manager.block_name(cb_configurable_block).c_str()); /* This is a routing multiplexer! Generate bitstream */ build_connection_block_mux_bitstream( bitstream_manager, mux_mem_block, module_manager, circuit_lib, mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, rr_gsb, - cb_ipin_side, ipin_index); + cb_ipin_side, ipin_index, verbose); } /*Nothing should be done else*/ } @@ -433,9 +452,9 @@ static void build_connection_block_bitstream( static void build_connection_block_bitstreams( BitstreamManager& bitstream_manager, const ConfigBlockId& top_configurable_block, - const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const FabricTile& fabric_tile, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy, const t_rr_type& cb_type, const bool& verbose) { @@ -486,24 +505,77 @@ static void build_connection_block_bitstreams( VTR_ASSERT(true == module_manager.valid_module_id(cb_module)); /* Bypass empty blocks which have none configurable children */ - if (0 == count_module_manager_module_configurable_children(module_manager, - cb_module)) { + if (0 == count_module_manager_module_configurable_children( + module_manager, cb_module, + ModuleManager::e_config_child_type::LOGICAL) && + 0 == count_module_manager_module_configurable_children( + module_manager, cb_module, + ModuleManager::e_config_child_type::PHYSICAL)) { continue; } - /* Create a block for the bitstream which corresponds to the Switch block - */ - ConfigBlockId cb_configurable_block = bitstream_manager.add_block( - generate_connection_block_module_name(cb_type, cb_coord)); + /* TODO: If the fabric tile is not empty, find the tile module and create + * the block accordingly. Also to support future hierarchy changes, when + * creating the blocks, trace backward until reach the current top block. + * If any block is missing during the back tracing, create it. */ + ConfigBlockId parent_block = top_configurable_block; + FabricTileId curr_tile = fabric_tile.find_tile_by_cb_coordinate( + cb_type, vtr::Point(ix, iy)); + ConfigBlockId cb_configurable_block; + if (fabric_tile.valid_tile_id(curr_tile)) { + vtr::Point tile_coord = fabric_tile.tile_coordinate(curr_tile); + std::string tile_inst_name = generate_tile_module_name(tile_coord); + parent_block = bitstream_manager.find_or_create_child_block( + top_configurable_block, tile_inst_name); + /* For tile modules, need to find the specific instance name under its + * unique tile */ + vtr::Point cb_coord_in_unique_tile = + fabric_tile.find_cb_coordinate_in_unique_tile( + curr_tile, cb_type, vtr::Point(ix, iy)); + const RRGSB& unique_tile_cb_rr_gsb = + device_rr_gsb.get_gsb(cb_coord_in_unique_tile); + cb_configurable_block = + bitstream_manager.add_block(generate_connection_block_module_name( + cb_type, unique_tile_cb_rr_gsb.get_cb_coordinate(cb_type))); + } else { + /* Create a block for the bitstream which corresponds to the Switch + * block + */ + cb_configurable_block = bitstream_manager.add_block( + generate_connection_block_module_name(cb_type, cb_coord)); + } /* Set switch block as a child of top block */ - bitstream_manager.add_child_block(top_configurable_block, - cb_configurable_block); + bitstream_manager.add_child_block(parent_block, cb_configurable_block); /* Reserve child blocks for new created block */ bitstream_manager.reserve_child_blocks( cb_configurable_block, - count_module_manager_module_configurable_children(module_manager, - cb_module)); + count_module_manager_module_configurable_children( + module_manager, cb_module, + ModuleManager::e_config_child_type::PHYSICAL)); + + /* Create a dedicated block for the non-unified configurable child */ + if (!module_manager.unified_configurable_children(cb_module)) { + VTR_ASSERT(1 == + module_manager + .configurable_children( + cb_module, ModuleManager::e_config_child_type::PHYSICAL) + .size()); + std::string phy_mem_instance_name = module_manager.instance_name( + cb_module, + module_manager.configurable_children( + cb_module, ModuleManager::e_config_child_type::PHYSICAL)[0], + module_manager.configurable_child_instances( + cb_module, ModuleManager::e_config_child_type::PHYSICAL)[0]); + ConfigBlockId cb_grouped_config_block = + bitstream_manager.add_block(phy_mem_instance_name); + bitstream_manager.add_child_block(cb_configurable_block, + cb_grouped_config_block); + VTR_LOGV(verbose, "Added '%s' as a child to '%s'\n", + bitstream_manager.block_name(cb_grouped_config_block).c_str(), + bitstream_manager.block_name(cb_configurable_block).c_str()); + cb_configurable_block = cb_grouped_config_block; + } build_connection_block_bitstream( bitstream_manager, cb_configurable_block, module_manager, circuit_lib, @@ -524,9 +596,9 @@ static void build_connection_block_bitstreams( void build_routing_bitstream( BitstreamManager& bitstream_manager, const ConfigBlockId& top_configurable_block, - const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const FabricTile& fabric_tile, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy, const bool& verbose) { @@ -544,7 +616,7 @@ void build_routing_bitstream( * Some of them do NOT exist due to heterogeneous blocks (width > 1) * We will skip those modules */ - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { continue; } @@ -568,29 +640,77 @@ void build_routing_bitstream( VTR_ASSERT(true == module_manager.valid_module_id(sb_module)); /* Bypass empty blocks which have none configurable children */ - if (0 == count_module_manager_module_configurable_children(module_manager, - sb_module)) { + if (0 == count_module_manager_module_configurable_children( + module_manager, sb_module, + ModuleManager::e_config_child_type::LOGICAL) && + 0 == count_module_manager_module_configurable_children( + module_manager, sb_module, + ModuleManager::e_config_child_type::PHYSICAL)) { continue; } - /* Create a block for the bitstream which corresponds to the Switch block - */ - ConfigBlockId sb_configurable_block = bitstream_manager.add_block( - generate_switch_block_module_name(sb_coord)); + /* TODO: If the fabric tile is not empty, find the tile module and create + * the block accordingly. Also to support future hierarchy changes, when + * creating the blocks, trace backward until reach the current top block. + * If any block is missing during the back tracing, create it. */ + ConfigBlockId parent_block = top_configurable_block; + FabricTileId curr_tile = fabric_tile.find_tile_by_sb_coordinate(sb_coord); + ConfigBlockId sb_configurable_block; + if (fabric_tile.valid_tile_id(curr_tile)) { + vtr::Point tile_coord = fabric_tile.tile_coordinate(curr_tile); + std::string tile_inst_name = generate_tile_module_name(tile_coord); + parent_block = bitstream_manager.find_or_create_child_block( + top_configurable_block, tile_inst_name); + /* For tile modules, need to find the specific instance name under its + * unique tile */ + vtr::Point sb_coord_in_unique_tile = + fabric_tile.find_sb_coordinate_in_unique_tile(curr_tile, sb_coord); + sb_configurable_block = bitstream_manager.add_block( + generate_switch_block_module_name(sb_coord_in_unique_tile)); + } else { + /* Create a block for the bitstream which corresponds to the Switch + * block + */ + sb_configurable_block = bitstream_manager.add_block( + generate_switch_block_module_name(sb_coord)); + } /* Set switch block as a child of top block */ - bitstream_manager.add_child_block(top_configurable_block, - sb_configurable_block); + bitstream_manager.add_child_block(parent_block, sb_configurable_block); /* Reserve child blocks for new created block */ bitstream_manager.reserve_child_blocks( sb_configurable_block, - count_module_manager_module_configurable_children(module_manager, - sb_module)); + count_module_manager_module_configurable_children( + module_manager, sb_module, + ModuleManager::e_config_child_type::PHYSICAL)); - build_switch_block_bitstream(bitstream_manager, sb_configurable_block, - module_manager, circuit_lib, mux_lib, - atom_ctx, device_annotation, - routing_annotation, rr_graph, rr_gsb); + /* Create a dedicated block for the non-unified configurable child */ + if (!module_manager.unified_configurable_children(sb_module)) { + VTR_ASSERT(1 == + module_manager + .configurable_children( + sb_module, ModuleManager::e_config_child_type::PHYSICAL) + .size()); + std::string phy_mem_instance_name = module_manager.instance_name( + sb_module, + module_manager.configurable_children( + sb_module, ModuleManager::e_config_child_type::PHYSICAL)[0], + module_manager.configurable_child_instances( + sb_module, ModuleManager::e_config_child_type::PHYSICAL)[0]); + ConfigBlockId sb_grouped_config_block = + bitstream_manager.add_block(phy_mem_instance_name); + bitstream_manager.add_child_block(sb_configurable_block, + sb_grouped_config_block); + VTR_LOGV(verbose, "Added '%s' as a child to '%s'\n", + bitstream_manager.block_name(sb_grouped_config_block).c_str(), + bitstream_manager.block_name(sb_configurable_block).c_str()); + sb_configurable_block = sb_grouped_config_block; + } + + build_switch_block_bitstream( + bitstream_manager, sb_configurable_block, module_manager, circuit_lib, + mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, + rr_gsb, verbose); VTR_LOGV(verbose, "\tDone\n"); } @@ -605,17 +725,17 @@ void build_routing_bitstream( VTR_LOG("Generating bitstream for X-direction Connection blocks ..."); build_connection_block_bitstreams( - bitstream_manager, top_configurable_block, module_manager, circuit_lib, - mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, - device_rr_gsb, compact_routing_hierarchy, CHANX, verbose); + bitstream_manager, top_configurable_block, module_manager, fabric_tile, + circuit_lib, mux_lib, atom_ctx, device_annotation, routing_annotation, + rr_graph, device_rr_gsb, compact_routing_hierarchy, CHANX, verbose); VTR_LOG("Done\n"); VTR_LOG("Generating bitstream for Y-direction Connection blocks ..."); build_connection_block_bitstreams( - bitstream_manager, top_configurable_block, module_manager, circuit_lib, - mux_lib, atom_ctx, device_annotation, routing_annotation, rr_graph, - device_rr_gsb, compact_routing_hierarchy, CHANY, verbose); + bitstream_manager, top_configurable_block, module_manager, fabric_tile, + circuit_lib, mux_lib, atom_ctx, device_annotation, routing_annotation, + rr_graph, device_rr_gsb, compact_routing_hierarchy, CHANY, verbose); VTR_LOG("Done\n"); } diff --git a/openfpga/src/fpga_bitstream/build_routing_bitstream.h b/openfpga/src/fpga_bitstream/build_routing_bitstream.h index 433c8dbe5..b268acd79 100644 --- a/openfpga/src/fpga_bitstream/build_routing_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_routing_bitstream.h @@ -12,6 +12,7 @@ #include "bitstream_manager.h" #include "circuit_library.h" #include "device_rr_gsb.h" +#include "fabric_tile.h" #include "module_manager.h" #include "mux_library.h" #include "vpr_context.h" @@ -28,9 +29,9 @@ namespace openfpga { void build_routing_bitstream( BitstreamManager& bitstream_manager, const ConfigBlockId& top_configurable_block, - const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, - const MuxLibrary& mux_lib, const AtomContext& atom_ctx, - const VprDeviceAnnotation& device_annotation, + const ModuleManager& module_manager, const FabricTile& fabric_tile, + const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, + const AtomContext& atom_ctx, const VprDeviceAnnotation& device_annotation, const VprRoutingAnnotation& routing_annotation, const RRGraphView& rr_graph, const DeviceRRGSB& device_rr_gsb, const bool& compact_routing_hierarchy, const bool& verbose); diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 5649388b8..38baf450b 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -11,6 +11,128 @@ /* begin namespace openfpga */ namespace openfpga { +/************************************************** + * FabricBitstreamMemoryBank + *************************************************/ +void FabricBitstreamMemoryBank::add_bit(const fabric_size_t& bit_id, + const fabric_size_t& region_id, + const fabric_size_t& bl, + const fabric_size_t& wl, + const fabric_size_t& bl_addr_size, + const fabric_size_t& wl_addr_size, + bool bit) { + // Fabric Bit is added in sequential manner and each bit is unique + VTR_ASSERT((size_t)(bit_id) == fabric_bit_datas.size()); + // Region is added in sequntial manner but it is not unique from fabric bit + // perspective + VTR_ASSERT((size_t)(region_id) <= blwl_lengths.size()); + if ((size_t)(region_id) == blwl_lengths.size()) { + // Add if this is first time + blwl_lengths.push_back(fabric_blwl_length(bl_addr_size, wl_addr_size)); + } else { + // Otherwise if the region had been added, it must always be consistent + VTR_ASSERT(blwl_lengths[region_id].bl == bl_addr_size); + VTR_ASSERT(blwl_lengths[region_id].wl == wl_addr_size); + } + // The BL/WL index must be within respective length + VTR_ASSERT(bl < blwl_lengths[region_id].bl); + VTR_ASSERT(wl < blwl_lengths[region_id].wl); + // We might not need this at all to track the raw data + // But since it does not use a lot of memory, tracking for good + fabric_bit_datas.push_back(fabric_bit_data((fabric_size_t)(size_t)(region_id), + (fabric_size_t)(bl), + (fabric_size_t)(wl), bit)); + // This is real compact data + VTR_ASSERT(datas.size() == masks.size()); + while ((size_t)(region_id) >= datas.size()) { + datas.emplace_back(); + masks.emplace_back(); + } + VTR_ASSERT(datas[region_id].size() == masks[region_id].size()); + while ((size_t)(wl) >= datas[region_id].size()) { + datas[region_id].push_back(std::vector((bl_addr_size + 7) / 8, 0)); + masks[region_id].push_back(std::vector((bl_addr_size + 7) / 8, 0)); + } + // Same uniqie config bit cannot be set twice + VTR_ASSERT((masks[region_id][wl][bl >> 3] & (1 << (bl & 7))) == 0); + if (bit) { + // Mark the data value if bit (or din) is true + datas[region_id][wl][bl >> 3] |= (1 << (bl & 7)); + } + // Mark the mask to indicate we had used this bit + masks[region_id][wl][bl >> 3] |= (1 << (bl & 7)); +} + +void FabricBitstreamMemoryBank::fast_configuration( + const bool& fast, const bool& bit_value_to_skip) { + for (auto& wls : wls_to_skip) { + wls.clear(); + } + wls_to_skip.clear(); + for (size_t region = 0; region < datas.size(); region++) { + wls_to_skip.emplace_back(); + if (fast) { + for (fabric_size_t wl = 0; wl < blwl_lengths[region].wl; wl++) { + VTR_ASSERT((size_t)(wl) < datas[region].size()); + bool skip_wl = true; + for (fabric_size_t bl = 0; bl < blwl_lengths[region].bl && skip_wl; + bl++) { + // Only check the bit that being used (marked in the mask), + // otherwise it is just a don't care, we can skip + if (masks[region][wl][bl >> 3] & (1 << (bl & 7))) { + if (datas[region][wl][bl >> 3] & (1 << (bl & 7))) { + // If bit_value_to_skip=true, and yet the din (recorded in + // datas) also 1, then we can skip + skip_wl = bit_value_to_skip; + } else { + skip_wl = !bit_value_to_skip; + } + } + } + if (skip_wl) { + // Record down that for this region, we will skip this WL + wls_to_skip[region].push_back(wl); + } + } + } + } +} + +fabric_size_t FabricBitstreamMemoryBank::get_longest_effective_wl_count() + const { + // This function check effective WL count + // Where effective WL is the WL that we want to program after considering + // fast configuration from all the region, it return the longest + fabric_size_t longest_wl = 0; + for (size_t region = 0; region < datas.size(); region++) { + VTR_ASSERT((size_t)(region) < wls_to_skip.size()); + fabric_size_t current_wl = + (fabric_size_t)(datas[region].size() - wls_to_skip[region].size()); + if (current_wl > longest_wl) { + longest_wl = current_wl; + } + } + return longest_wl; +} + +fabric_size_t FabricBitstreamMemoryBank::get_total_bl_addr_size() const { + // Simply total up all the BL addr size + fabric_size_t bl = 0; + for (size_t region = 0; region < datas.size(); region++) { + bl += blwl_lengths[region].bl; + } + return bl; +} + +fabric_size_t FabricBitstreamMemoryBank::get_total_wl_addr_size() const { + // Simply total up all the WL addr size + fabric_size_t wl = 0; + for (size_t region = 0; region < datas.size(); region++) { + wl += blwl_lengths[region].wl; + } + return wl; +} + /************************************************** * Public Constructor *************************************************/ @@ -129,6 +251,15 @@ bool FabricBitstream::use_address() const { return use_address_; } bool FabricBitstream::use_wl_address() const { return use_wl_address_; } +const FabricBitstreamMemoryBank& FabricBitstream::memory_bank_info( + const bool& fast, const bool& bit_value_to_skip) const { + VTR_ASSERT(true == use_address_); + VTR_ASSERT(true == use_wl_address_); + (const_cast(&memory_bank_data_)) + ->fast_configuration(fast, bit_value_to_skip); + return memory_bank_data_; +} + /****************************************************************************** * Public Mutators ******************************************************************************/ @@ -243,6 +374,27 @@ void FabricBitstream::set_bl_address_length(const size_t& length) { set_address_length(length); } +void FabricBitstream::set_memory_bank_info(const FabricBitId& bit_id, + const FabricBitRegionId& region_id, + const size_t& bl, const size_t& wl, + const size_t& bl_addr_size, + const size_t& wl_addr_size, + bool bit) { + // Bit must be valid one + // We only support this in protocol that use BL and WL address + VTR_ASSERT(true == valid_bit_id(bit_id)); + VTR_ASSERT(true == use_address_); + VTR_ASSERT(true == use_wl_address_); + VTR_ASSERT(bl_addr_size); + VTR_ASSERT(wl_addr_size); + // All the basic checking had passed, we can add the data into + // memory_bank_data_ + memory_bank_data_.add_bit( + (fabric_size_t)(size_t)(bit_id), (fabric_size_t)(size_t)(region_id), + (fabric_size_t)(bl), (fabric_size_t)(wl), (fabric_size_t)(bl_addr_size), + (fabric_size_t)(wl_addr_size), bit); +} + void FabricBitstream::set_use_wl_address(const bool& enable) { /* Add a lock, only can be modified when num bits are zero*/ if (0 == num_bits_) { diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.h b/openfpga/src/fpga_bitstream/fabric_bitstream.h index 68a972636..67e92f9f8 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.h @@ -41,6 +41,85 @@ /* begin namespace openfpga */ namespace openfpga { +// Use uint32_t (maximum of 4Gigs) is good enough, we have BL and WL, +// combination of both hold up to 18 quintillion of configuration bits (+ dont +// care) +typedef uint32_t fabric_size_t; +struct fabric_bit_data { + fabric_bit_data(fabric_size_t r, fabric_size_t b, fabric_size_t w, bool bi) + : region(r), bl(b), wl(w), bit(bi) {} + const fabric_size_t region = 0; + const fabric_size_t bl = 0; + const fabric_size_t wl = 0; + const bool bit = false; +}; +struct fabric_blwl_length { + fabric_blwl_length(fabric_size_t b, fabric_size_t w) : bl(b), wl(w) {} + const fabric_size_t bl = 0; + const fabric_size_t wl = 0; +}; + +/* + This class arrange Memory Bank databae in a compact way +*/ +struct FabricBitstreamMemoryBank { + void add_bit(const fabric_size_t& bit_id, const fabric_size_t& region_id, + const fabric_size_t& bl, const fabric_size_t& wl, + const fabric_size_t& bl_addr_size, + const fabric_size_t& wl_addr_size, bool bit); + void fast_configuration(const bool& fast, const bool& bit_value_to_skip); + fabric_size_t get_longest_effective_wl_count() const; + fabric_size_t get_total_bl_addr_size() const; + fabric_size_t get_total_wl_addr_size() const; + + /************************* + * All the database (except fabric_bit_datas) is sorted by region + * 1. The very first layer of vector is region + * For the datas and masks + * 1. They are sorted by WL, hence second layer is WL + * 2. Last layer is BL data stored in vector of uint8_t + * 3. Each uint8_t will store up-to 8 configuration bit info + **************************/ + // Store the BL WL of each region + std::vector blwl_lengths; + // Store config ID raw data. Not used by bitstream generation + // Used by XML generation + /* + fabric_bit_datas[Bit #0] = (region, bl, wl) + fabric_bit_datas[Bit #1] = (region, bl, wl) + fabric_bit_datas[Bit #2] = (region, bl, wl) + */ + std::vector fabric_bit_datas; + // 100K LE FPGA only need few mega bytes + /* + datas represent the Din value of a given WL and BL (1bit) + datas[region #0][wl #0] = std::vector to represent BLs + where uint8_t #0 = MSB{ BL#7, BL#6, .... BL #1, BL #0 } LSB + where uint8_t #1 = MSB{ BL#15, BL#14, .... BL #9, BL #8 } LSB + datas[region #0][wl #1] = std::vector to represent BLs + datas[region #0][wl #2] = std::vector to represent BLs + ...... + datas[region #0][wl #n-1] = std::vector to represent BLs + ...... + datas[region #1][wl #0] = std::vector to represent BLs + datas[region #1][wl #1] = std::vector to represent BLs + ...... + */ + std::vector>> datas; + /* + masks has same structure as datas + but masks presents data that being used + for exampe: + if mask's uint8_t #0 value = 0x41 it means for this WL + a. BL #0 is being used, and its Din is recoreded in datas + b. BL #6 is being used, and its Din is recoreded in datas + c. Other BLs #1, 2, 3, 4, 5, 7 are don't care bit (not being used) + */ + std::vector>> masks; + // This track which WL to skip because of fast configuration + std::vector> wls_to_skip; +}; + class FabricBitstream { public: /* Type implementations */ /* @@ -144,6 +223,9 @@ class FabricBitstream { bool use_address() const; bool use_wl_address() const; + const FabricBitstreamMemoryBank& memory_bank_info( + const bool& fast = false, const bool& bit_value_to_skip = false) const; + public: /* Public Mutators */ /* Reserve config bits */ void reserve_bits(const size_t& num_bits); @@ -193,6 +275,18 @@ class FabricBitstream { void set_address_length(const size_t& length); void set_bl_address_length(const size_t& length); + /* + This is setting memory bank protocol in a more efficient way + Instead of building lengthy BL/WL bits of database (BL or Wl could be in + thousand bits of size), a small device like 100K LE (compared to other + vendors offer) might end up using tens of gig bytes. + */ + void set_memory_bank_info(const FabricBitId& bit_id, + const FabricBitRegionId& region_id, + const size_t& bl, const size_t& wl, + const size_t& bl_addr_size, + const size_t& wl_addr_size, bool bit); + /* Enable the use of WL-address related data * Same priniciple as the set_use_address() */ @@ -250,6 +344,9 @@ class FabricBitstream { /* Data input (Din) bits: this is designed for memory decoders */ vtr::vector bit_dins_; + + /* New way of dealing with memory bank protocol - fast and compact */ + FabricBitstreamMemoryBank memory_bank_data_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 9cb2a3f9c..4cde144d5 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -245,6 +245,194 @@ static int write_memory_bank_flatten_fabric_bitstream_to_text_file( return status; } +/******************************************************************** + * Write the fabric bitstream fitting a memory bank protocol + * to a plain text file in efficient method + * + * Old function is write_memory_bank_flatten_fabric_bitstream_to_text_file() + * + * As compared to original function, based on 100K LE FPGA: + * 1. Original function used 600 seconds and needs high memory usage + * 2. This new function only needs 1 second and 4M Bytes + * + * Old function only print WL in decremental order. It is not by intentional + * It is because of the map-key ordering + * In QL Memory Bank with Flatten BL/WL, data is stored by WL address, + * where we use WL string as map key + * WL #0 --- "1000000000000 .... 0000" + * WL #1 --- "0100000000000 .... 0000" + * WL #n-1 --- "0000000000000 .... 0001 + * From string comparison wise, WL #n-1 will be first, and WL #0 will be last + * The sequence of WL does not really matter, but preferrable in some ordering + * manner. Using map key as ordering cannot guarantee the determinstic + * + * This new way of writting fabric guarantee the WL order in 100% deterministc + * way: either incremental (default) or decremental + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +static int fast_write_memory_bank_flatten_fabric_bitstream_to_text_file( + std::fstream& fp, const bool& fast_configuration, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const bool& keep_dont_care_bits, const bool& wl_incremental_order) { + int status = 0; + + std::string dont_care_bit = "0"; + if (keep_dont_care_bits) { + dont_care_bit = "x"; + } + const FabricBitstreamMemoryBank& memory_bank = + fabric_bitstream.memory_bank_info(fast_configuration, bit_value_to_skip); + + fabric_size_t longest_effective_wl_count = + memory_bank.get_longest_effective_wl_count(); + /* Output information about how to intepret the bitstream */ + fp << "// Bitstream length: " << longest_effective_wl_count << std::endl; + fp << "// Bitstream width (LSB -> MSB): "; + fp << ""; + fp << ""; + fp << std::endl; + + // Step 1 + // Initialize wl_indexes for every region + // The intialization depends the ordering of WL + // It could either be 0 (if wl_incremental_order=true) or + // last WL index (if wl_incremental_order=false) + std::vector wl_indexes; + for (size_t region = 0; region < memory_bank.datas.size(); region++) { + if (wl_incremental_order) { + wl_indexes.push_back(0); + } else { + wl_indexes.push_back( + (fabric_size_t)(memory_bank.datas[region].size() - 1)); + } + } + // Step 2 + // Loop through total WL count that we would like to configure + for (size_t wl_index = 0; wl_index < longest_effective_wl_count; wl_index++) { + // Step 3 + // Write BL address + // We cascade all regions: 0, 1, 2 ... + for (size_t region = 0; region < memory_bank.datas.size(); region++) { + // Step 3a + // The sequence of configuration of each region WL is not the same + // since WL to skip for each region is not the same + // If it happen that current WL that we are going to program is + // one of the WLs (stored in wls_to_skip) that we had determined + // to skip, the we will increment or decrement to next + // depending on wl_incremental_order + const fabric_blwl_length& lengths = memory_bank.blwl_lengths[region]; + fabric_size_t current_wl = wl_indexes[region]; + while (std::find(memory_bank.wls_to_skip[region].begin(), + memory_bank.wls_to_skip[region].end(), + current_wl) != memory_bank.wls_to_skip[region].end()) { + // We would like to skip this + if (wl_incremental_order) { + wl_indexes[region]++; + } else { + wl_indexes[region]--; + } + current_wl = wl_indexes[region]; + } + // Step 3b + // If current WL still within the valid range, we will print BL + // Otherwise it is either + // overflow (wl_incremental_order=true) or + // underflow (to max fabric_blwl_length when wl_incremental_order=false) + // Since fabric_blwl_length is unsigned, hence underflow of -1 will be + // considered as overflow too + // If it is overflow/underflow, then we just print don't care + if (current_wl < memory_bank.datas[region].size()) { + const std::vector& data = + memory_bank.datas[region][current_wl]; + const std::vector& mask = + memory_bank.masks[region][current_wl]; + // Step 3c + // Real code to print BL data that we had stored + // mask tell you each BL is valid + // for invalid BL, we will print don't care + // data tell you the real din value + // (bl >> 3) - This is to find Byte index of the BL + // (1 << (bl & 7)) - This is to find Bit index of the BL + // within that Byte index + // When we '&' both, we can know if that BL is set or unset + /* + ----------------------------------------------------------------- + | bit (bl) | Byte index (bl >> 3) | Bit index (1 << (bl & 7)) | + |---------------------------------------------------------------- + | 0 | 0 | b0000_0001 (or 0x01) | + | 1 | 0 | b0000_0010 (or 0x02) | + | 2 | 0 | b0000_0100 (or 0x04) | + | 3 | 0 | b0000_1000 (or 0x08) | + | 4 | 0 | b0001_0000 (or 0x10) | + | 5 | 0 | b0010_0000 (or 0x20) | + | 6 | 0 | b0100_0000 (or 0x40) | + | 7 | 0 | b1000_0000 (or 0x80) | + | 8 | 1 | b0000_0001 (or 0x01) | + | ... | ... | ... | + ------------------------------------------------------------------ + Each BL can be uniquely represented by bit slice in byte array + */ + for (size_t bl = 0; bl < lengths.bl; bl++) { + if (mask[bl >> 3] & (1 << (bl & 7))) { + if (data[bl >> 3] & (1 << (bl & 7))) { + fp << "1"; + } else { + fp << "0"; + } + } else { + fp << dont_care_bit.c_str(); + } + } + } else { + /* However not all region has equal WL, for those that is shorter, + * print 'x' for all BL*/ + for (size_t bl = 0; bl < lengths.bl; bl++) { + fp << dont_care_bit.c_str(); + } + } + } + // Step 4 + // Write WL address + // We cascade all regions: 0, 1, 2 ... + for (size_t region = 0; region < memory_bank.datas.size(); region++) { + const fabric_blwl_length& lengths = memory_bank.blwl_lengths[region]; + fabric_size_t current_wl = wl_indexes[region]; + // Step 4a + // If current WL still within the valid range, we will print WL + // Otherwise it is overflow/underflow then we will print don't care + if (current_wl < memory_bank.datas[region].size()) { + // Step 4b + // One hot printing + for (size_t wl_temp = 0; wl_temp < lengths.wl; wl_temp++) { + if (wl_temp == current_wl) { + fp << "1"; + } else { + fp << "0"; + } + } + // Step 4b + // Increment or decrement to next depending on wl_incremental_order + if (wl_incremental_order) { + wl_indexes[region]++; + } else { + wl_indexes[region]--; + } + } else { + /* However not all region has equal WL, for those that is shorter, + * print 'x' for all WL */ + for (size_t wl_temp = 0; wl_temp < lengths.wl; wl_temp++) { + fp << dont_care_bit.c_str(); + } + } + } + fp << std::endl; + } + return status; +} + /******************************************************************** * Write the fabric bitstream fitting a memory bank protocol * to a plain text file @@ -393,7 +581,8 @@ int write_fabric_bitstream_to_text_file( const ConfigProtocol& config_protocol, const FabricGlobalPortInfo& global_ports, const std::string& fname, const bool& fast_configuration, const bool& keep_dont_care_bits, - const bool& include_time_stamp, const bool& verbose) { + const bool& wl_incremental_order, const bool& include_time_stamp, + const bool& verbose) { /* Ensure that we have a valid file name */ if (true == fname.empty()) { VTR_LOG_ERROR( @@ -454,6 +643,14 @@ int write_fabric_bitstream_to_text_file( if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { status = write_memory_bank_fabric_bitstream_to_text_file( fp, apply_fast_configuration, bit_value_to_skip, fabric_bitstream); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() && + BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + // If both BL and WL protocols are flatten, use new way to write the + // bitstream + status = fast_write_memory_bank_flatten_fabric_bitstream_to_text_file( + fp, apply_fast_configuration, bit_value_to_skip, fabric_bitstream, + keep_dont_care_bits, wl_incremental_order); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { status = write_memory_bank_flatten_fabric_bitstream_to_text_file( fp, apply_fast_configuration, bit_value_to_skip, fabric_bitstream, diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h index 0d8682739..59f4774de 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h @@ -27,7 +27,8 @@ int write_fabric_bitstream_to_text_file( const ConfigProtocol& config_protocol, const FabricGlobalPortInfo& global_ports, const std::string& fname, const bool& fast_configuration, const bool& keep_dont_care_bits, - const bool& include_time_stamp, const bool& verbose); + const bool& wl_incremental_order, const bool& include_time_stamp, + const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp index ec8a036fd..06f0c079e 100644 --- a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp @@ -71,7 +71,8 @@ static void write_fabric_bitstream_xml_file_head( static int write_fabric_config_bit_to_xml_file( std::fstream& fp, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, const FabricBitId& fabric_bit, - const e_config_protocol_type& config_type, const int& xml_hierarchy_depth) { + const e_config_protocol_type& config_type, bool fast_xml, + const int& xml_hierarchy_depth, std::string& bl_addr, std::string& wl_addr) { if (false == valid_file_stream(fp)) { return 1; } @@ -106,22 +107,60 @@ static int write_fabric_config_bit_to_xml_file( case CONFIG_MEM_STANDALONE: case CONFIG_MEM_SCAN_CHAIN: break; - case CONFIG_MEM_QL_MEMORY_BANK: - case CONFIG_MEM_MEMORY_BANK: { - /* Bit line address */ - write_tab_to_file(fp, xml_hierarchy_depth + 1); - fp << "\n"; + case CONFIG_MEM_MEMORY_BANK: + case CONFIG_MEM_QL_MEMORY_BANK: { + if (fast_xml) { + // New way of printing XML + // This is fast (less than 100s) as compared to original 1300s seen in + // 100K LE FPFA + const FabricBitstreamMemoryBank& memory_bank = + fabric_bitstream.memory_bank_info(); + /* Bit line address */ + write_tab_to_file(fp, xml_hierarchy_depth + 1); + const fabric_bit_data& bit = + memory_bank.fabric_bit_datas[(size_t)(fabric_bit)]; + const fabric_blwl_length& lengths = + memory_bank.blwl_lengths[bit.region]; + if (bl_addr.size() == 0) { + VTR_ASSERT(wl_addr.size() == 0); + bl_addr.resize(lengths.bl); + wl_addr.resize(lengths.wl); + bl_addr.assign(lengths.bl, 'x'); + wl_addr.assign(lengths.wl, '0'); + } else { + VTR_ASSERT((fabric_size_t)(bl_addr.size()) == lengths.bl); + VTR_ASSERT((fabric_size_t)(wl_addr.size()) == lengths.wl); + } + fp << "\n"; + /* Word line address */ + write_tab_to_file(fp, xml_hierarchy_depth + 1); + fp << "\n"; + } else { + /* Bit line address */ + write_tab_to_file(fp, xml_hierarchy_depth + 1); + fp << "\n"; - write_tab_to_file(fp, xml_hierarchy_depth + 1); - fp << "\n"; } - fp << "\"/>\n"; break; } case CONFIG_MEM_FRAME_BASED: { @@ -156,13 +195,25 @@ static int write_fabric_regional_config_bit_to_xml_file( std::fstream& fp, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, const FabricBitRegionId& fabric_region, - const e_config_protocol_type& config_type, const int& xml_hierarchy_depth) { + const e_config_protocol_type& config_type, bool fast_xml, + const int& xml_hierarchy_depth) { if (false == valid_file_stream(fp)) { return 1; } int status = 0; - + // Use string to print, instead of char by char + // This is for Flatten BL/WL protocol + // You will find this much more faster than char by char + // We do not need to build the string for every BL/WL + // It is one-hot and sequal addr + // We start with all '0' (WL) or 'x' (BL) + // By setting "1' and resettting ('0' or 'x') at approriate bit position + // We could create one-hot string much faster + // Use FPGA 100K as example: old way needs 1300seconds to write 85Gig XML + // New way only needs 80seconds to write identical XML + std::string bl_addr = ""; + std::string wl_addr = ""; write_tab_to_file(fp, xml_hierarchy_depth); fp << "\n"; + size_t bit_index = 0; + size_t total_bits = fabric_bitstream.region_bits(fabric_region).size(); + size_t percentage = 0; for (const FabricBitId& fabric_bit : fabric_bitstream.region_bits(fabric_region)) { status = write_fabric_config_bit_to_xml_file( fp, bitstream_manager, fabric_bitstream, fabric_bit, config_type, - xml_hierarchy_depth + 1); + fast_xml, xml_hierarchy_depth + 1, bl_addr, wl_addr); if (1 == status) { return status; } + // Misc to print percentage of the process + bit_index++; + size_t temp = (bit_index * 100) / total_bits; + if (temp != percentage) { + VTR_LOG(" Progress: %lu%\r", percentage); + percentage = temp; + } } write_tab_to_file(fp, xml_hierarchy_depth); @@ -231,6 +292,8 @@ int write_fabric_bitstream_to_xml_file( for (const FabricBitRegionId& region : fabric_bitstream.regions()) { status = write_fabric_regional_config_bit_to_xml_file( fp, bitstream_manager, fabric_bitstream, region, config_protocol.type(), + BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() && + BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type(), xml_hierarchy_depth + 1); if (1 == status) { break; diff --git a/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.cpp index 1aeeef090..2de04a881 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_grid_writer.cpp @@ -603,15 +603,15 @@ static void print_analysis_sdc_disable_unused_grid( /* Validate file stream */ valid_file_stream(fp); - t_physical_tile_type_ptr grid_type = - grids[grid_coordinate.x()][grid_coordinate.y()].type; + t_physical_tile_loc phy_tile_loc(grid_coordinate.x(), grid_coordinate.y(), 0); + t_physical_tile_type_ptr grid_type = grids.get_physical_type(phy_tile_loc); /* Bypass conditions for grids : * 1. EMPTY type, which is by nature unused * 2. Offset > 0, which has already been processed when offset = 0 */ if ((true == is_empty_type(grid_type)) || - (0 < grids[grid_coordinate.x()][grid_coordinate.y()].width_offset) || - (0 < grids[grid_coordinate.x()][grid_coordinate.y()].height_offset)) { + (0 < grids.get_width_offset(phy_tile_loc)) || + (0 < grids.get_height_offset(phy_tile_loc))) { return; } diff --git a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp index b9e4c974b..8d3163262 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_routing_writer.cpp @@ -579,7 +579,7 @@ void print_analysis_sdc_disable_unused_sbs( * We will skip those modules */ const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { continue; } diff --git a/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp index 00281eebb..65a0d3efa 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp @@ -258,6 +258,15 @@ void print_analysis_sdc(const AnalysisSdcOption& option, ModuleId top_module = openfpga_ctx.module_graph().find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == openfpga_ctx.module_graph().valid_module_id(top_module)); + /* Use the core module as the top when the fpga_core is added */ + std::string core_block_name = generate_fpga_core_module_name(); + const ModuleId& core_module = + openfpga_ctx.module_graph().find_module(core_block_name); + if (openfpga_ctx.module_graph().valid_module_id(core_module)) { + /* Now we use the core_block as the top-level block for the remaining + * functions */ + top_module = core_module; + } /* Create clock and set I/O ports with input/output delays * FIXME: Now different I/Os have different delays due to multiple clock diff --git a/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp b/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp index 1eadf6fda..9d6d21def 100644 --- a/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/configuration_chain_sdc_writer.cpp @@ -49,13 +49,17 @@ static void rec_print_pnr_sdc_constrain_configurable_chain( ModuleId& previous_module) { /* For each configurable child, we will go one level down in priority */ for (size_t child_index = 0; - child_index < module_manager.configurable_children(parent_module).size(); + child_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++child_index) { std::string child_module_path = parent_module_path; - ModuleId child_module_id = - module_manager.configurable_children(parent_module)[child_index]; - size_t child_instance_id = - module_manager.configurable_child_instances(parent_module)[child_index]; + ModuleId child_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[child_index]; + size_t child_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[child_index]; std::string child_instance_name; if (true == module_manager @@ -79,7 +83,10 @@ static void rec_print_pnr_sdc_constrain_configurable_chain( /* If there is no configurable children any more, this is a leaf module, print * a SDC command for disable timing */ - if (0 < module_manager.configurable_children(parent_module).size()) { + if (0 < module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size()) { return; } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp index 3732815f7..1f56da15e 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp @@ -211,7 +211,7 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing( for (size_t ix = 0; ix < sb_range.x(); ++ix) { for (size_t iy = 0; iy < sb_range.y(); ++iy) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { continue; } @@ -248,7 +248,7 @@ void print_pnr_sdc_compact_routing_constrain_sb_timing( for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) { const RRGSB& rr_gsb = device_rr_gsb.get_sb_unique_module(isb); - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { continue; } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp index b7b272641..ab2a25aee 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp @@ -13,6 +13,7 @@ #include /* Headers from vtrutil library */ +#include "command_exit_codes.h" #include "vtr_assert.h" #include "vtr_log.h" #include "vtr_time.h" @@ -86,7 +87,8 @@ static void print_pnr_sdc_constrain_configurable_memory_outputs( static void print_pnr_sdc_flatten_routing_disable_switch_block_outputs( const std::string& sdc_dir, const bool& flatten_names, const bool& include_time_stamp, const ModuleManager& module_manager, - const ModuleId& top_module, const DeviceRRGSB& device_rr_gsb) { + const ModuleId& top_module, const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph) { /* Create the file name for Verilog netlist */ std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME)); @@ -123,7 +125,7 @@ static void print_pnr_sdc_flatten_routing_disable_switch_block_outputs( for (size_t iy = 0; iy < sb_range.y(); ++iy) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { continue; } @@ -211,7 +213,8 @@ static void print_pnr_sdc_flatten_routing_disable_switch_block_outputs( static void print_pnr_sdc_compact_routing_disable_switch_block_outputs( const std::string& sdc_dir, const bool& flatten_names, const bool& include_time_stamp, const ModuleManager& module_manager, - const ModuleId& top_module, const DeviceRRGSB& device_rr_gsb) { + const ModuleId& top_module, const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph) { /* Create the file name for Verilog netlist */ std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME)); @@ -245,7 +248,7 @@ static void print_pnr_sdc_compact_routing_disable_switch_block_outputs( for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) { const RRGSB& rr_gsb = device_rr_gsb.get_sb_unique_module(isb); - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { continue; } @@ -338,19 +341,32 @@ static void print_pnr_sdc_compact_routing_disable_switch_block_outputs( * 3. Design constraints for Connection Blocks * 4. Design constraints for breaking the combinational loops in FPGA fabric *******************************************************************/ -void print_pnr_sdc(const PnrSdcOption& sdc_options, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const DeviceRRGSB& device_rr_gsb, - const ModuleManager& module_manager, - const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, - const FabricGlobalPortInfo& global_ports, - const SimulationSetting& sim_setting, - const bool& compact_routing_hierarchy) { +int print_pnr_sdc( + const PnrSdcOption& sdc_options, const DeviceContext& device_ctx, + const VprDeviceAnnotation& device_annotation, const FabricTile& fabric_tile, + const DeviceRRGSB& device_rr_gsb, const ModuleManager& module_manager, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const FabricGlobalPortInfo& global_ports, + const SimulationSetting& sim_setting, const bool& compact_routing_hierarchy) { + /* Fabric tile is not supported yet, error out */ + if (!fabric_tile.empty()) { + VTR_LOG_ERROR("Tile-based modules are not supported yet!\n"); + return CMD_EXEC_FATAL_ERROR; + } + std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.find_module(top_module_name); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + /* Use the core module as the top when the fpga_core is added */ + std::string core_block_name = generate_fpga_core_module_name(); + const ModuleId& core_module = module_manager.find_module(core_block_name); + if (module_manager.valid_module_id(core_module)) { + /* Now we use the core_block as the top-level block for the remaining + * functions */ + top_module = core_module; + } + /* Constrain global ports */ if (true == sdc_options.constrain_global_port()) { print_pnr_sdc_global_ports(sdc_options, module_manager, top_module, @@ -377,12 +393,14 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options, if (true == compact_routing_hierarchy) { print_pnr_sdc_compact_routing_disable_switch_block_outputs( sdc_options.sdc_dir(), sdc_options.flatten_names(), - sdc_options.time_stamp(), module_manager, top_module, device_rr_gsb); + sdc_options.time_stamp(), module_manager, top_module, device_rr_gsb, + device_ctx.rr_graph); } else { VTR_ASSERT_SAFE(false == compact_routing_hierarchy); print_pnr_sdc_flatten_routing_disable_switch_block_outputs( sdc_options.sdc_dir(), sdc_options.flatten_names(), - sdc_options.time_stamp(), module_manager, top_module, device_rr_gsb); + sdc_options.time_stamp(), module_manager, top_module, device_rr_gsb, + device_ctx.rr_graph); } } @@ -405,7 +423,8 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options, (true == sdc_options.output_hierarchy()) && (true == compact_routing_hierarchy)) { print_pnr_sdc_routing_sb_hierarchy(sdc_options.sdc_dir(), module_manager, - top_module, device_rr_gsb); + top_module, device_rr_gsb, + device_ctx.rr_graph); } /* Output routing constraints for Connection Blocks */ @@ -444,6 +463,8 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options, print_pnr_sdc_grid_hierarchy(sdc_options.sdc_dir(), device_ctx, device_annotation, module_manager, top_module); } + + return CMD_EXEC_SUCCESS; } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_writer.h b/openfpga/src/fpga_sdc/pnr_sdc_writer.h index 00c1642eb..abf995866 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_writer.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_writer.h @@ -10,6 +10,7 @@ #include "circuit_library.h" #include "device_rr_gsb.h" #include "fabric_global_port_info.h" +#include "fabric_tile.h" #include "module_manager.h" #include "mux_library.h" #include "pnr_sdc_option.h" @@ -24,15 +25,13 @@ /* begin namespace openfpga */ namespace openfpga { -void print_pnr_sdc(const PnrSdcOption& sdc_options, - const DeviceContext& device_ctx, - const VprDeviceAnnotation& device_annotation, - const DeviceRRGSB& device_rr_gsb, - const ModuleManager& module_manager, - const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, - const FabricGlobalPortInfo& global_ports, - const SimulationSetting& sim_setting, - const bool& compact_routing_hierarchy); +int print_pnr_sdc( + const PnrSdcOption& sdc_options, const DeviceContext& device_ctx, + const VprDeviceAnnotation& device_annotation, const FabricTile& fabric_tile, + const DeviceRRGSB& device_rr_gsb, const ModuleManager& module_manager, + const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, + const FabricGlobalPortInfo& global_ports, + const SimulationSetting& sim_setting, const bool& compact_routing_hierarchy); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/sdc_hierarchy_writer.cpp b/openfpga/src/fpga_sdc/sdc_hierarchy_writer.cpp index e9d46fa4a..f2ae08864 100644 --- a/openfpga/src/fpga_sdc/sdc_hierarchy_writer.cpp +++ b/openfpga/src/fpga_sdc/sdc_hierarchy_writer.cpp @@ -31,7 +31,8 @@ namespace openfpga { void print_pnr_sdc_routing_sb_hierarchy(const std::string& sdc_dir, const ModuleManager& module_manager, const ModuleId& top_module, - const DeviceRRGSB& device_rr_gsb) { + const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph) { std::string fname(sdc_dir + std::string(SDC_SB_HIERARCHY_FILE_NAME)); std::string timer_message = @@ -59,7 +60,7 @@ void print_pnr_sdc_routing_sb_hierarchy(const std::string& sdc_dir, for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) { const RRGSB& rr_gsb = device_rr_gsb.get_sb_unique_module(isb); - if (false == rr_gsb.is_sb_exist()) { + if (false == rr_gsb.is_sb_exist(rr_graph)) { continue; } diff --git a/openfpga/src/fpga_sdc/sdc_hierarchy_writer.h b/openfpga/src/fpga_sdc/sdc_hierarchy_writer.h index 39c5fd565..c429d5e62 100644 --- a/openfpga/src/fpga_sdc/sdc_hierarchy_writer.h +++ b/openfpga/src/fpga_sdc/sdc_hierarchy_writer.h @@ -17,7 +17,8 @@ namespace openfpga { void print_pnr_sdc_routing_sb_hierarchy(const std::string& sdc_dir, const ModuleManager& module_manager, const ModuleId& top_module, - const DeviceRRGSB& device_rr_gsb); + const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph); void print_pnr_sdc_routing_cb_hierarchy(const std::string& sdc_dir, const ModuleManager& module_manager, diff --git a/openfpga/src/fpga_sdc/sdc_memory_utils.cpp b/openfpga/src/fpga_sdc/sdc_memory_utils.cpp index 12d45b887..7d8df9541 100644 --- a/openfpga/src/fpga_sdc/sdc_memory_utils.cpp +++ b/openfpga/src/fpga_sdc/sdc_memory_utils.cpp @@ -45,13 +45,17 @@ void rec_print_pnr_sdc_disable_configurable_memory_module_output( /* For each configurable child, we will go one level down in priority */ for (size_t child_index = 0; - child_index < module_manager.configurable_children(parent_module).size(); + child_index < + module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); ++child_index) { std::string child_module_path = parent_module_path; - ModuleId child_module_id = - module_manager.configurable_children(parent_module)[child_index]; - size_t child_instance_id = - module_manager.configurable_child_instances(parent_module)[child_index]; + ModuleId child_module_id = module_manager.configurable_children( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[child_index]; + size_t child_instance_id = module_manager.configurable_child_instances( + parent_module, ModuleManager::e_config_child_type::PHYSICAL)[child_index]; std::string child_instance_name; if (true == module_manager @@ -96,7 +100,10 @@ void rec_print_pnr_sdc_disable_configurable_memory_module_output( /* If there is no configurable children any more, this is a leaf module, print * a SDC command for disable timing */ - if (0 < module_manager.configurable_children(parent_module).size()) { + if (0 < module_manager + .configurable_children(parent_module, + ModuleManager::e_config_child_type::PHYSICAL) + .size()) { return; } diff --git a/openfpga/src/fpga_spice/spice_api.cpp b/openfpga/src/fpga_spice/spice_api.cpp index 99c346cbf..7fa744de9 100644 --- a/openfpga/src/fpga_spice/spice_api.cpp +++ b/openfpga/src/fpga_spice/spice_api.cpp @@ -95,7 +95,8 @@ int fpga_fabric_spice(const ModuleManager& module_manager, } else { VTR_ASSERT(false == options.compress_routing()); print_spice_flatten_routing_modules(netlist_manager, module_manager, - device_rr_gsb, rr_dir_path); + device_rr_gsb, device_ctx.rr_graph, + rr_dir_path); } /* Generate grids */ diff --git a/openfpga/src/fpga_spice/spice_routing.cpp b/openfpga/src/fpga_spice/spice_routing.cpp index ec29dbfd2..bb59b86cf 100644 --- a/openfpga/src/fpga_spice/spice_routing.cpp +++ b/openfpga/src/fpga_spice/spice_routing.cpp @@ -259,6 +259,7 @@ static void print_spice_flatten_connection_block_modules( void print_spice_flatten_routing_modules(NetlistManager& netlist_manager, const ModuleManager& module_manager, const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph, const std::string& subckt_dir) { /* Create a vector to contain all the Verilog netlist names that have been * generated in this function */ @@ -270,7 +271,7 @@ void print_spice_flatten_routing_modules(NetlistManager& netlist_manager, for (size_t ix = 0; ix < sb_range.x(); ++ix) { for (size_t iy = 0; iy < sb_range.y(); ++iy) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - if (true != rr_gsb.is_sb_exist()) { + if (true != rr_gsb.is_sb_exist(rr_graph)) { continue; } print_spice_routing_switch_box_unique_module( diff --git a/openfpga/src/fpga_spice/spice_routing.h b/openfpga/src/fpga_spice/spice_routing.h index c14a3d68b..ed4d2e476 100644 --- a/openfpga/src/fpga_spice/spice_routing.h +++ b/openfpga/src/fpga_spice/spice_routing.h @@ -9,6 +9,7 @@ #include "module_manager.h" #include "mux_library.h" #include "netlist_manager.h" +#include "rr_graph_view.h" /******************************************************************** * Function declaration @@ -20,6 +21,7 @@ namespace openfpga { void print_spice_flatten_routing_modules(NetlistManager& netlist_manager, const ModuleManager& module_manager, const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph, const std::string& subckt_dir); void print_spice_unique_routing_modules(NetlistManager& netlist_manager, diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index 3fa929afc..1dbf64dc9 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -12,15 +12,18 @@ /* Headers from openfpgautil library */ #include "device_rr_gsb.h" #include "openfpga_digest.h" +#include "openfpga_naming.h" #include "openfpga_reserved_words.h" #include "verilog_auxiliary_netlists.h" #include "verilog_constants.h" #include "verilog_formal_random_top_testbench.h" #include "verilog_grid.h" +#include "verilog_mock_fpga_wrapper.h" #include "verilog_preconfig_top_module.h" #include "verilog_routing.h" #include "verilog_simulation_info_writer.h" #include "verilog_submodule.h" +#include "verilog_tile.h" #include "verilog_top_module.h" #include "verilog_top_testbench.h" @@ -51,15 +54,18 @@ namespace openfpga { * We should think clearly about how to handle them for both Verilog and SPICE *generators! ********************************************************************/ -void fpga_fabric_verilog( +int fpga_fabric_verilog( ModuleManager &module_manager, NetlistManager &netlist_manager, const MemoryBankShiftRegisterBanks &blwl_sr_banks, const CircuitLibrary &circuit_lib, const MuxLibrary &mux_lib, const DecoderLibrary &decoder_lib, const DeviceContext &device_ctx, const VprDeviceAnnotation &device_annotation, - const DeviceRRGSB &device_rr_gsb, const FabricVerilogOption &options) { + const DeviceRRGSB &device_rr_gsb, const FabricTile &fabric_tile, + const FabricVerilogOption &options) { vtr::ScopedStartFinishTimer timer("Write Verilog netlists for FPGA fabric\n"); + int status_code = CMD_EXEC_SUCCESS; + std::string src_dir_path = format_dir_path(options.output_directory()); /* Create directories */ @@ -81,6 +87,13 @@ void fpga_fabric_verilog( std::string rr_dir_path = src_dir_path + std::string(DEFAULT_RR_DIR_NAME); create_directory(rr_dir_path); + /* Sub directory under SRC directory to contain all the tile netlists + */ + std::string tile_dir_path = src_dir_path + std::string(DEFAULT_TILE_DIR_NAME); + if (!fabric_tile.empty()) { + create_directory(tile_dir_path); + } + /* Print Verilog files containing preprocessing flags */ print_verilog_preprocessing_flags_netlist(std::string(src_dir_path), options); @@ -104,7 +117,8 @@ void fpga_fabric_verilog( VTR_ASSERT(false == options.compress_routing()); print_verilog_flatten_routing_modules( netlist_manager, const_cast(module_manager), - device_rr_gsb, rr_dir_path, std::string(DEFAULT_RR_DIR_NAME), options); + device_rr_gsb, device_ctx.rr_graph, rr_dir_path, + std::string(DEFAULT_RR_DIR_NAME), options); } /* Generate grids */ @@ -113,7 +127,20 @@ void fpga_fabric_verilog( device_ctx, device_annotation, lb_dir_path, std::string(DEFAULT_LB_DIR_NAME), options, options.verbose_output()); + /* Generate tiles */ + if (!fabric_tile.empty()) { + status_code = print_verilog_tiles( + netlist_manager, const_cast(module_manager), + tile_dir_path, fabric_tile, std::string(DEFAULT_TILE_DIR_NAME), options); + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + /* Generate FPGA fabric */ + print_verilog_core_module(netlist_manager, + const_cast(module_manager), + src_dir_path, options); print_verilog_top_module(netlist_manager, const_cast(module_manager), src_dir_path, options); @@ -127,6 +154,8 @@ void fpga_fabric_verilog( */ VTR_LOGV(options.verbose_output(), "Written %lu Verilog modules in total\n", module_manager.num_modules()); + + return CMD_EXEC_SUCCESS; } /******************************************************************** @@ -143,6 +172,7 @@ int fpga_verilog_full_testbench( const AtomContext &atom_ctx, const PlacementContext &place_ctx, const PinConstraints &pin_constraints, const BusGroup &bus_group, const std::string &bitstream_file, const IoLocationMap &io_location_map, + const IoNameMap &io_name_map, const FabricGlobalPortInfo &fabric_global_port_info, const VprNetlistAnnotation &netlist_annotation, const CircuitLibrary &circuit_lib, @@ -169,7 +199,7 @@ int fpga_verilog_full_testbench( print_verilog_full_testbench( module_manager, bitstream_manager, fabric_bitstream, blwl_sr_banks, circuit_lib, config_protocol, fabric_global_port_info, atom_ctx, place_ctx, - pin_constraints, bus_group, bitstream_file, io_location_map, + pin_constraints, bus_group, bitstream_file, io_location_map, io_name_map, netlist_annotation, netlist_name, top_testbench_file_path, simulation_setting, options); @@ -192,6 +222,7 @@ int fpga_verilog_preconfigured_fabric_wrapper( const BitstreamManager &bitstream_manager, const AtomContext &atom_ctx, const PlacementContext &place_ctx, const PinConstraints &pin_constraints, const BusGroup &bus_group, const IoLocationMap &io_location_map, + const IoNameMap &io_name_map, const FabricGlobalPortInfo &fabric_global_port_info, const VprNetlistAnnotation &netlist_annotation, const CircuitLibrary &circuit_lib, const ConfigProtocol &config_protocol, @@ -216,12 +247,67 @@ int fpga_verilog_preconfigured_fabric_wrapper( status = print_verilog_preconfig_top_module( module_manager, bitstream_manager, config_protocol, circuit_lib, fabric_global_port_info, atom_ctx, place_ctx, pin_constraints, bus_group, - io_location_map, netlist_annotation, netlist_name, + io_location_map, io_name_map, netlist_annotation, netlist_name, formal_verification_top_netlist_file_path, options); return status; } +/******************************************************************** + * A top-level function of FPGA-Verilog which focuses on a wrapper module, + * which encapsulate the application HDL into a mock FPGA module + ********************************************************************/ +int fpga_verilog_mock_fpga_wrapper( + const ModuleManager &module_manager, const AtomContext &atom_ctx, + const PlacementContext &place_ctx, const PinConstraints &pin_constraints, + const BusGroup &bus_group, const IoLocationMap &io_location_map, + const IoNameMap &io_name_map, + const FabricGlobalPortInfo &fabric_global_port_info, + const VprNetlistAnnotation &netlist_annotation, + const VerilogTestbenchOption &options) { + vtr::ScopedStartFinishTimer timer( + "Write a wrapper module to mock a mapped FPGA fabric\n"); + + std::string src_dir_path = format_dir_path(options.output_directory()); + + std::string netlist_name = atom_ctx.nlist.netlist_name(); + + int status = CMD_EXEC_SUCCESS; + + NetlistManager netlist_manager; + + /* Create directories */ + create_directory(src_dir_path); + + /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and + * pre-configured testbench for verification */ + std::string netlist_file_name = + generate_fpga_top_netlist_name(std::string(VERILOG_NETLIST_FILE_POSTFIX)); + std::string netlist_file_path = src_dir_path + netlist_file_name; + status = print_verilog_mock_fpga_wrapper( + module_manager, fabric_global_port_info, atom_ctx, place_ctx, + pin_constraints, bus_group, io_location_map, io_name_map, + netlist_annotation, netlist_name, netlist_file_path, options); + + /* Add fname to the netlist name list */ + NetlistId nlist_id = NetlistId::INVALID(); + if (options.use_relative_path()) { + nlist_id = netlist_manager.add_netlist(netlist_file_name); + } else { + nlist_id = netlist_manager.add_netlist(netlist_file_path); + } + VTR_ASSERT(nlist_id); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::TOP_MODULE_NETLIST); + + /* Generate an netlist including all the fabric-related netlists */ + print_verilog_mock_fabric_include_netlist(netlist_manager, src_dir_path, + options.use_relative_path(), + options.time_stamp()); + + return status; +} + /******************************************************************** * A top-level function of FPGA-Verilog which focuses on fabric Verilog *generation This function will generate diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index 79ce6759d..bea3ba4d7 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -16,8 +16,10 @@ #include "device_rr_gsb.h" #include "fabric_bitstream.h" #include "fabric_global_port_info.h" +#include "fabric_tile.h" #include "fabric_verilog_options.h" #include "io_location_map.h" +#include "io_name_map.h" #include "memory_bank_shift_register_banks.h" #include "module_manager.h" #include "mux_library.h" @@ -36,13 +38,14 @@ /* begin namespace openfpga */ namespace openfpga { -void fpga_fabric_verilog( +int fpga_fabric_verilog( ModuleManager& module_manager, NetlistManager& netlist_manager, const MemoryBankShiftRegisterBanks& blwl_sr_banks, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const DecoderLibrary& decoder_lib, const DeviceContext& device_ctx, const VprDeviceAnnotation& device_annotation, - const DeviceRRGSB& device_rr_gsb, const FabricVerilogOption& options); + const DeviceRRGSB& device_rr_gsb, const FabricTile& fabric_tile, + const FabricVerilogOption& options); int fpga_verilog_full_testbench( const ModuleManager& module_manager, @@ -52,6 +55,7 @@ int fpga_verilog_full_testbench( const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, const BusGroup& bus_group, const std::string& bitstream_file, const IoLocationMap& io_location_map, + const IoNameMap& io_name_map, const FabricGlobalPortInfo& fabric_global_port_info, const VprNetlistAnnotation& netlist_annotation, const CircuitLibrary& circuit_lib, @@ -63,11 +67,21 @@ int fpga_verilog_preconfigured_fabric_wrapper( const BitstreamManager& bitstream_manager, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, const BusGroup& bus_group, const IoLocationMap& io_location_map, + const IoNameMap& io_name_map, const FabricGlobalPortInfo& fabric_global_port_info, const VprNetlistAnnotation& netlist_annotation, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, const VerilogTestbenchOption& options); +int fpga_verilog_mock_fpga_wrapper( + const ModuleManager& module_manager, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const PinConstraints& pin_constraints, + const BusGroup& bus_group, const IoLocationMap& io_location_map, + const IoNameMap& io_name_map, + const FabricGlobalPortInfo& fabric_global_port_info, + const VprNetlistAnnotation& netlist_annotation, + const VerilogTestbenchOption& options); + int fpga_verilog_preconfigured_testbench( const ModuleManager& module_manager, const AtomContext& atom_ctx, const PinConstraints& pin_constraints, const BusGroup& bus_group, diff --git a/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.cpp b/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.cpp index aa600ddba..8501ac6aa 100644 --- a/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.cpp +++ b/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.cpp @@ -23,6 +23,48 @@ namespace openfpga { * Local constant variables *******************************************************************/ +/******************************************************************** + * Print a file that includes all the fabric netlists + * that have been generated and user-defined. + * This does NOT include any testbenches! + * Some netlists are open to compile under specific preprocessing flags + *******************************************************************/ +void print_verilog_mock_fabric_include_netlist( + const NetlistManager& netlist_manager, const std::string& src_dir_path, + const bool& use_relative_path, const bool& include_time_stamp) { + /* If we force the use of relative path, the src dir path should NOT be + * included in any output */ + std::string src_dir = src_dir_path; + if (use_relative_path) { + src_dir.clear(); + } + std::string verilog_fpath = + src_dir_path + std::string(FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME); + + /* Create the file stream */ + std::fstream fp; + fp.open(verilog_fpath, std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + check_file_stream(verilog_fpath.c_str(), fp); + + /* Print the title */ + print_verilog_file_header(fp, std::string("Mock Fabric Netlist Summary"), + include_time_stamp); + + /* Include FPGA top module */ + print_verilog_comment( + fp, std::string("------ Include fabric top-level netlists -----")); + for (const NetlistId& nlist_id : + netlist_manager.netlists_by_type(NetlistManager::TOP_MODULE_NETLIST)) { + print_verilog_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); + } + fp << std::endl; + + /* Close the file stream */ + fp.close(); +} + /******************************************************************** * Print a file that includes all the fabric netlists * that have been generated and user-defined. @@ -96,6 +138,15 @@ void print_verilog_fabric_include_netlist(const NetlistManager& netlist_manager, } fp << std::endl; + /* Include all the tile modules */ + print_verilog_comment( + fp, std::string("------ Include tile module netlists -----")); + for (const NetlistId& nlist_id : + netlist_manager.netlists_by_type(NetlistManager::TILE_MODULE_NETLIST)) { + print_verilog_include_netlist(fp, netlist_manager.netlist_name(nlist_id)); + } + fp << std::endl; + /* Include FPGA top module */ print_verilog_comment( fp, std::string("------ Include fabric top-level netlists -----")); diff --git a/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.h b/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.h index 553c8c3a4..493f2c4af 100644 --- a/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.h +++ b/openfpga/src/fpga_verilog/verilog_auxiliary_netlists.h @@ -18,6 +18,10 @@ /* begin namespace openfpga */ namespace openfpga { +void print_verilog_mock_fabric_include_netlist( + const NetlistManager& netlist_manager, const std::string& src_dir_path, + const bool& use_relative_path, const bool& include_time_stamp); + void print_verilog_fabric_include_netlist(const NetlistManager& netlist_manager, const std::string& src_dir_path, const CircuitLibrary& circuit_lib, diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp index c72eb6786..629d1759b 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp @@ -116,8 +116,9 @@ static void print_verilog_top_random_testbench_benchmark_instance( print_verilog_testbench_benchmark_instance( fp, reference_verilog_top_name, std::string(BENCHMARK_INSTANCE_NAME), std::string(), std::string(), std::string(), - std::string(BENCHMARK_PORT_POSTFIX), std::vector(), atom_ctx, - netlist_annotation, pin_constraints, bus_group, explicit_port_mapping); + std::string(BENCHMARK_PORT_POSTFIX), std::vector(), false, + atom_ctx, netlist_annotation, pin_constraints, bus_group, + explicit_port_mapping); print_verilog_comment( fp, std::string("----- End reference Benchmark Instanication -------")); @@ -147,7 +148,7 @@ static void print_verilog_random_testbench_fpga_instance( std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX)), std::string(FPGA_INSTANCE_NAME), std::string(), std::string(), std::string(), std::string(FPGA_PORT_POSTFIX), std::vector(), - atom_ctx, netlist_annotation, pin_constraints, bus_group, + false, atom_ctx, netlist_annotation, pin_constraints, bus_group, explicit_port_mapping); print_verilog_comment( diff --git a/openfpga/src/fpga_verilog/verilog_memory.cpp b/openfpga/src/fpga_verilog/verilog_memory.cpp index ef6903cd5..365ace6a5 100644 --- a/openfpga/src/fpga_verilog/verilog_memory.cpp +++ b/openfpga/src/fpga_verilog/verilog_memory.cpp @@ -17,6 +17,7 @@ #include "mux_utils.h" #include "openfpga_digest.h" #include "openfpga_naming.h" +#include "openfpga_reserved_words.h" #include "verilog_constants.h" #include "verilog_memory.h" #include "verilog_module_writer.h" @@ -51,7 +52,7 @@ static void print_verilog_mux_memory_module( circuit_lib, mux_model, find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()), - std::string(VERILOG_MEM_POSTFIX)); + std::string(MEMORY_MODULE_POSTFIX)); ModuleId mem_module = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); /* Write the module content in Verilog format */ @@ -63,6 +64,28 @@ static void print_verilog_mux_memory_module( /* Add an empty line as a splitter */ fp << std::endl; + + /* Print feedthrough memory if exists */ + std::string feedthru_module_name = generate_mux_subckt_name( + circuit_lib, mux_model, + find_mux_num_datapath_inputs(circuit_lib, mux_model, + mux_graph.num_inputs()), + std::string(MEMORY_FEEDTHROUGH_MODULE_POSTFIX)); + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_module_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + VTR_ASSERT(true == module_manager.valid_module_id(feedthru_mem_module)); + /* Write the module content in Verilog format */ + write_verilog_module_to_file( + fp, module_manager, feedthru_mem_module, + options.explicit_port_mapping() || + circuit_lib.dump_explicit_port_map(mux_model), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; + } + break; } case CIRCUIT_MODEL_DESIGN_RRAM: @@ -174,7 +197,7 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager, /* Create the module name for the memory block */ std::string module_name = generate_memory_module_name( - circuit_lib, model, sram_models[0], std::string(VERILOG_MEM_POSTFIX)); + circuit_lib, model, sram_models[0], std::string(MEMORY_MODULE_POSTFIX)); ModuleId mem_module = module_manager.find_module(module_name); VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); @@ -186,6 +209,36 @@ void print_verilog_submodule_memories(const ModuleManager& module_manager, /* Add an empty line as a splitter */ fp << std::endl; + + /* Create the module name for the memory block */ + std::string feedthru_module_name = + generate_memory_module_name(circuit_lib, model, sram_models[0], + std::string(MEMORY_MODULE_POSTFIX), true); + + ModuleId feedthru_mem_module = + module_manager.find_module(feedthru_module_name); + if (module_manager.valid_module_id(feedthru_mem_module)) { + /* Write the module content in Verilog format */ + write_verilog_module_to_file(fp, module_manager, feedthru_mem_module, + options.explicit_port_mapping() || + circuit_lib.dump_explicit_port_map(model), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; + } + } + + /* Include memory group modules */ + for (ModuleId mem_group_module : module_manager.modules_by_usage( + ModuleManager::e_module_usage_type::MODULE_CONFIG_GROUP)) { + /* Write the module content in Verilog format */ + write_verilog_module_to_file(fp, module_manager, mem_group_module, + options.explicit_port_mapping(), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; } /* Close the file stream */ diff --git a/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.cpp b/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.cpp new file mode 100644 index 000000000..018ab3d77 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.cpp @@ -0,0 +1,558 @@ +/******************************************************************** + * This file includes functions that are used to generate + * a Verilog module of a pre-configured FPGA fabric + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpgautil library */ +#include "bitstream_manager_utils.h" +#include "fabric_global_port_info_utils.h" +#include "module_manager_utils.h" +#include "openfpga_atom_netlist_utils.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "verilog_constants.h" +#include "verilog_mock_fpga_wrapper.h" +#include "verilog_testbench_utils.h" +#include "verilog_writer_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Local variables used only in this file + *******************************************************************/ +constexpr const char* APPINST_PORT_POSTFIX = "_bench"; +constexpr const char* APP_INSTANCE_NAME = "MAPPED_DESIGN"; + +/******************************************************************** + * This function adds stimuli to I/Os of FPGA fabric + * 1. For mapped I/Os, this function will wire them to the input ports + * of the pre-configured FPGA top module + * 2. For unmapped I/Os, this function will assign a constant value + * by default + *******************************************************************/ +static void print_verilog_mock_fpga_wrapper_connect_ios( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const AtomContext& atom_ctx, + const PlacementContext& place_ctx, const IoLocationMap& io_location_map, + const IoNameMap& io_name_map, const PinConstraints& pin_constraints, + const FabricGlobalPortInfo& global_ports, + const VprNetlistAnnotation& netlist_annotation, + const std::string& net_name_postfix, + const std::string& io_input_port_name_postfix, + const std::string& io_output_port_name_postfix, + const std::vector& clock_port_names, + const size_t& unused_io_value) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Only mappable i/o ports can be considered */ + std::vector module_io_ports; + for (const ModuleManager::e_module_port_type& module_io_port_type : + MODULE_IO_PORT_TYPES) { + for (const ModulePortId& gpio_port_id : + module_manager.module_port_ids_by_type(top_module, + module_io_port_type)) { + /* Only care mappable I/O */ + if (false == + module_manager.port_is_mappable_io(top_module, gpio_port_id)) { + continue; + } + module_io_ports.push_back(gpio_port_id); + } + } + + /* Keep tracking which I/Os have been used */ + std::map> io_used; + for (const ModulePortId& module_io_port_id : module_io_ports) { + const BasicPort& module_io_port = + module_manager.module_port(top_module, module_io_port_id); + io_used[module_io_port_id] = + std::vector(module_io_port.get_width(), false); + } + + /* Type mapping between VPR block and Module port */ + std::map + atom_block_type_to_module_port_type; + atom_block_type_to_module_port_type[AtomBlockType::INPAD] = + ModuleManager::MODULE_GPIN_PORT; + atom_block_type_to_module_port_type[AtomBlockType::OUTPAD] = + ModuleManager::MODULE_GPOUT_PORT; + + /* See if this I/O should be wired to a benchmark input/output */ + /* Add signals from blif benchmark and short-wire them to FPGA I/O PADs + * This brings convenience to checking functionality + */ + print_verilog_comment( + fp, std::string("----- Link FPGA I/Os to Benchmark I/Os -----")); + + for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) { + /* Bypass non-I/O atom blocks ! */ + if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && + (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) { + continue; + } + + /* If there is a GPIO port, use it directly + * Otherwise, should find a GPIN for INPAD + * or should find a GPOUT for OUTPAD + */ + std::pair mapped_module_io_info = + std::make_pair(ModulePortId::INVALID(), -1); + for (const ModulePortId& module_io_port_id : module_io_ports) { + const BasicPort& module_io_port = + module_manager.module_port(top_module, module_io_port_id); + + /* Find the index of the mapped GPIO in top-level FPGA fabric */ + size_t temp_io_index = io_location_map.io_index( + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y, + place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile, + module_io_port.get_name()); + + /* Bypass invalid index (not mapped to this GPIO port) */ + if (size_t(-1) == temp_io_index) { + continue; + } + + /* If the port is an GPIO port, just use it */ + if (ModuleManager::MODULE_GPIO_PORT == + module_manager.port_type(top_module, module_io_port_id)) { + mapped_module_io_info = + std::make_pair(module_io_port_id, temp_io_index); + break; + } + + /* If this is an INPAD, we can use an GPIN port (if available) */ + if (atom_block_type_to_module_port_type[atom_ctx.nlist.block_type( + atom_blk)] == + module_manager.port_type(top_module, module_io_port_id)) { + mapped_module_io_info = + std::make_pair(module_io_port_id, temp_io_index); + break; + } + } + + /* We must find a valid one */ + VTR_ASSERT(true == module_manager.valid_module_port_id( + top_module, mapped_module_io_info.first)); + VTR_ASSERT(size_t(-1) != mapped_module_io_info.second); + + /* Ensure that IO index is in range */ + BasicPort module_mapped_io_port = + module_manager.module_port(top_module, mapped_module_io_info.first); + size_t io_index = mapped_module_io_info.second; + + /* Set the port pin index */ + VTR_ASSERT(io_index < module_mapped_io_port.get_width()); + module_mapped_io_port.set_name(module_mapped_io_port.get_name() + + net_name_postfix); + module_mapped_io_port.set_width(io_index, io_index); + + /* The block may be renamed as it contains special characters which violate + * Verilog syntax */ + std::string block_name = atom_ctx.nlist.block_name(atom_blk); + if (true == netlist_annotation.is_block_renamed(atom_blk)) { + block_name = netlist_annotation.block_name(atom_blk); + } + /* Note that VPR added a prefix to the name of output blocks + * We can remove this when specified through input argument + */ + if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) { + block_name = remove_atom_block_name_prefix(block_name); + } + + /* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always + * has a size of 1 In addition, the input and output ports may have + * different postfix in naming due to verification context! Here, we give + * full customization on naming + */ + BasicPort benchmark_io_port; + + benchmark_io_port.set_width(1); + + if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) { + /* If the port is a clock, skip it */ + if (clock_port_names.end() != std::find(clock_port_names.begin(), + clock_port_names.end(), + block_name)) { + continue; + } + /* For global ports, use wires; otherwise, use registers*/ + if (true == port_is_fabric_global_reset_port( + global_ports, module_manager, + pin_constraints.net_pin(block_name))) { + continue; + } + + benchmark_io_port.set_name( + std::string(block_name + io_input_port_name_postfix)); + print_verilog_comment( + fp, std::string("----- Blif Benchmark input " + block_name + + " is mapped to FPGA IOPAD " + + module_mapped_io_port.to_verilog_string() + " -----")); + /* Consider possible I/O naming rules */ + BasicPort renamed_module_mapped_io_port = + io_name_map.fpga_top_port(module_mapped_io_port); + if (renamed_module_mapped_io_port.is_valid()) { + print_verilog_wire_connection(fp, benchmark_io_port, + renamed_module_mapped_io_port, false); + } else { + print_verilog_wire_connection(fp, benchmark_io_port, + module_mapped_io_port, false); + } + } else { + VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)); + benchmark_io_port.set_name( + std::string(block_name + io_output_port_name_postfix)); + print_verilog_comment( + fp, std::string("----- Blif Benchmark output " + block_name + + " is mapped to FPGA IOPAD " + + module_mapped_io_port.to_verilog_string() + " -----")); + /* Consider possible I/O naming rules */ + BasicPort renamed_module_mapped_io_port = + io_name_map.fpga_top_port(module_mapped_io_port); + if (renamed_module_mapped_io_port.is_valid()) { + print_verilog_wire_connection(fp, renamed_module_mapped_io_port, + benchmark_io_port, false); + } else { + print_verilog_wire_connection(fp, module_mapped_io_port, + benchmark_io_port, false); + } + } + + /* Mark this I/O has been used/wired */ + io_used[mapped_module_io_info.first][io_index] = true; + + /* Add an empty line as a splitter */ + fp << std::endl; + } + + /* Wire the unused iopads to a constant */ + print_verilog_comment( + fp, std::string("----- Wire unused FPGA I/Os to constants -----")); + for (const ModulePortId& module_io_port_id : module_io_ports) { + for (size_t io_index = 0; io_index < io_used[module_io_port_id].size(); + ++io_index) { + /* Bypass used iopads */ + if (true == io_used[module_io_port_id][io_index]) { + continue; + } + + /* Bypass unused output pads */ + if (ModuleManager::MODULE_GPOUT_PORT != + module_manager.port_type(top_module, module_io_port_id)) { + continue; + } + + /* Wire to a contant */ + BasicPort module_unused_io_port = + module_manager.module_port(top_module, module_io_port_id); + /* Set the port pin index */ + module_unused_io_port.set_name(module_unused_io_port.get_name() + + net_name_postfix); + module_unused_io_port.set_width(io_index, io_index); + + std::vector default_values(module_unused_io_port.get_width(), + unused_io_value); + /* Consider possible I/O naming rules */ + BasicPort renamed_module_unused_io_port = + io_name_map.fpga_top_port(module_unused_io_port); + if (renamed_module_unused_io_port.is_valid()) { + print_verilog_wire_constant_values(fp, renamed_module_unused_io_port, + default_values); + } else { + print_verilog_wire_constant_values(fp, module_unused_io_port, + default_values); + } + } + + /* Add an empty line as a splitter */ + fp << std::endl; + } +} + +/******************************************************************** + * Connect global ports of FPGA top module to constants except: + * 1. operating clock, which should be wired to the clock port of + * this pre-configured FPGA top module + *******************************************************************/ +static int print_verilog_mock_fpga_wrapper_connect_global_ports( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const PinConstraints& pin_constraints, + const FabricGlobalPortInfo& fabric_global_ports, const IoNameMap& io_name_map, + const std::vector& benchmark_clock_port_names) { + /* Validate the file stream */ + valid_file_stream(fp); + + print_verilog_comment( + fp, + std::string( + "----- Begin Connect Global ports to FPGA top-level interface -----")); + + for (const FabricGlobalPortId& global_port_id : + fabric_global_ports.global_ports()) { + ModulePortId module_global_port_id = + fabric_global_ports.global_module_port(global_port_id); + VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT == + module_manager.port_type(top_module, module_global_port_id)); + BasicPort module_global_port = + module_manager.module_port(top_module, module_global_port_id); + /* Now, for operating clock port, we should wire it to the clock of + * benchmark! */ + if ((true == fabric_global_ports.global_port_is_clock(global_port_id)) && + (false == fabric_global_ports.global_port_is_prog(global_port_id))) { + /* Wiring to each pin of the global port: benchmark clock is always 1-bit + */ + for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); + ++pin_id) { + BasicPort module_clock_pin(module_global_port.get_name(), + module_global_port.pins()[pin_id], + module_global_port.pins()[pin_id]); + + /* If the clock port name is in the pin constraints, we should wire it + * to the constrained pin */ + std::string constrained_net_name = pin_constraints.pin_net(BasicPort( + module_global_port.get_name(), module_global_port.pins()[pin_id], + module_global_port.pins()[pin_id])); + + /* If constrained to an open net or there is no clock in the benchmark, + * we assign it to a default value */ + if ((true == pin_constraints.unmapped_net(constrained_net_name)) || + (true == benchmark_clock_port_names.empty())) { + continue; + } + + std::string clock_name_to_connect; + if (!pin_constraints.unconstrained_net(constrained_net_name)) { + clock_name_to_connect = constrained_net_name; + } else { + /* Otherwise, we must have a clear one-to-one clock net + * corresponding!!! */ + if (benchmark_clock_port_names.size() != + module_global_port.get_width()) { + VTR_LOG_ERROR( + "Unable to map %lu benchmark clocks to %lu clock pins of " + "FPGA!\nRequire clear pin constraints!\n", + benchmark_clock_port_names.size(), + module_global_port.get_width()); + return CMD_EXEC_FATAL_ERROR; + } + clock_name_to_connect = benchmark_clock_port_names[pin_id]; + } + clock_name_to_connect += std::string(APPINST_PORT_POSTFIX); + + BasicPort benchmark_clock_pin(clock_name_to_connect, 1); + /* If io naming is applicable, just consider the renaming port */ + BasicPort actual_module_clock_pin = + io_name_map.fpga_top_port(module_clock_pin); + if (!actual_module_clock_pin.is_valid()) { + print_verilog_wire_connection(fp, benchmark_clock_pin, + module_clock_pin, false); + } else { + print_verilog_wire_connection(fp, benchmark_clock_pin, + actual_module_clock_pin, false); + } + } + /* Finish, go to the next */ + continue; + } + + /* For other ports, give an default value */ + for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); + ++pin_id) { + BasicPort module_global_pin(module_global_port.get_name(), + module_global_port.pins()[pin_id], + module_global_port.pins()[pin_id]); + + /* If the global port name is in the pin constraints, we should wire it to + * the constrained pin */ + std::string constrained_net_name = + pin_constraints.pin_net(module_global_pin); + if (constrained_net_name.empty()) { + continue; + } + constrained_net_name += std::string(APPINST_PORT_POSTFIX); + + module_global_pin.set_name(module_global_port.get_name()); + + /* - If constrained to a given net in the benchmark, we connect the global + * pin to the net + * - If constrained to an open net in the benchmark, we assign it to a + * default value + */ + if ((false == pin_constraints.unconstrained_net(constrained_net_name)) && + (false == pin_constraints.unmapped_net(constrained_net_name))) { + BasicPort benchmark_pin(constrained_net_name, 1); + /* If io naming is applicable, just consider the renaming port */ + BasicPort actual_module_global_pin = + io_name_map.fpga_top_port(module_global_pin); + if (!actual_module_global_pin.is_valid()) { + print_verilog_wire_connection(fp, benchmark_pin, module_global_pin, + false); + } else { + print_verilog_wire_connection(fp, benchmark_pin, + actual_module_global_pin, false); + } + } + } + } + + print_verilog_comment( + fp, std::string( + "----- End Connect Global ports to FPGA top-level interface -----")); + + /* Add an empty line as a splitter */ + fp << std::endl; + + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Top-level function to generate a Verilog module of + * a mock FPGA wrapper which contains an benchmark instance. + * + * Mock FPGA wrapper + * +-------------------------------------------- + * | + * | Benchmark instance + * | +-------------------------------+ + * | | | + * fpga_clock----->|--------->|benchmark_clock | + * | | | + * fpga_inputs---->|--------->|benchmark_inputs | + * | | | + * fpga_outputs<---|<---------|benchmark_output | + * | | | + * | +-------------------------------+ + * | + * +------------------------------------------- + * + * Note: we do NOT put this module in the module manager. + * Because, it is not a standard module, where we just wrap an instance of + *application HDL (supposed to be implemented on FPGA). + *******************************************************************/ +int print_verilog_mock_fpga_wrapper( + const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, + const AtomContext& atom_ctx, const PlacementContext& place_ctx, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const IoLocationMap& io_location_map, const IoNameMap& io_name_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& circuit_name, const std::string& verilog_fname, + const VerilogTestbenchOption& options) { + std::string timer_message = + std::string("Write mock FPGA wrapper in Verilog format for design '") + + circuit_name + std::string("'"); + + int status = CMD_EXEC_SUCCESS; + + /* Start time count */ + vtr::ScopedStartFinishTimer timer(timer_message); + + /* Create the file stream */ + std::fstream fp; + fp.open(verilog_fname, std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + check_file_stream(verilog_fname.c_str(), fp); + + /* Generate a brief description on the Verilog file*/ + std::string title = + std::string("Verilog netlist for mock FPGA fabric by design: ") + + circuit_name; + print_verilog_file_header(fp, title, options.time_stamp()); + + /* Find the top_module */ + ModuleId top_module = module_manager.find_module(options.dut_module()); + if (!module_manager.valid_module_id(top_module)) { + VTR_LOG_ERROR( + "Unable to find the DUT module '%s'. Please check if you create " + "dedicated module when building the fabric!\n", + options.dut_module().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Note that we always need the core module as it contains the original port + * names before possible renaming at top-level module. If there is no core + * module, it means that the current top module is the core module */ + ModuleId core_module = + module_manager.find_module(generate_fpga_core_module_name()); + if (!module_manager.valid_module_id(core_module)) { + core_module = top_module; + } + + /* Precheck on the top module and decide if we need to consider I/O naming + * - If we do have a fpga_core module added, and dut is fpga_top, we need a + * I/O naming + * - If we do NOT have a fpga_core module added, and dut is fpga_top, we do + * NOT need a I/O naming + * - If we do have a fpga_core module added, and dut is fpga_core, we do NOT + * need a I/O naming + * - If we do NOT have a fpga_core module added, and dut is fpga_core, it + * should error out earlier. + */ + bool require_io_naming = false; + if (top_module != core_module) { + require_io_naming = true; + } + + /* Print module declaration */ + print_verilog_module_declaration(fp, module_manager, top_module, + options.default_net_type()); + + /* Find clock ports in benchmark */ + std::vector benchmark_clock_port_names = + find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); + + /* Print local wires */ + print_verilog_testbench_shared_input_ports( + fp, module_manager, global_ports, pin_constraints, atom_ctx, + netlist_annotation, benchmark_clock_port_names, true, + std::string(APPINST_PORT_POSTFIX), false); + + print_verilog_testbench_shared_benchmark_output_ports( + fp, atom_ctx, netlist_annotation, std::string(APPINST_PORT_POSTFIX)); + + /* Instanciate application HDL module */ + print_verilog_testbench_benchmark_instance( + fp, circuit_name, std::string(APP_INSTANCE_NAME), std::string(), + std::string(), std::string(APPINST_PORT_POSTFIX), + std::string(APPINST_PORT_POSTFIX), benchmark_clock_port_names, true, + atom_ctx, netlist_annotation, pin_constraints, bus_group, + options.explicit_port_mapping()); + + /* Connect FPGA top module global ports to constant or benchmark global + * signals! */ + status = print_verilog_mock_fpga_wrapper_connect_global_ports( + fp, module_manager, core_module, pin_constraints, global_ports, + require_io_naming ? io_name_map : IoNameMap(), benchmark_clock_port_names); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + + /* Connect I/Os to benchmark I/Os or constant driver */ + print_verilog_mock_fpga_wrapper_connect_ios( + fp, module_manager, core_module, atom_ctx, place_ctx, io_location_map, + require_io_naming ? io_name_map : IoNameMap(), pin_constraints, + global_ports, netlist_annotation, std::string(), + std::string(APPINST_PORT_POSTFIX), std::string(APPINST_PORT_POSTFIX), + benchmark_clock_port_names, (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); + + /* Testbench ends*/ + print_verilog_module_end(fp, title); + + /* Close the file stream */ + fp.close(); + + return status; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.h b/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.h new file mode 100644 index 000000000..4632811a6 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.h @@ -0,0 +1,41 @@ +#ifndef VERILOG_MOCK_FPGA_WRAPPER_H +#define VERILOG_MOCK_FPGA_WRAPPER_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include + +#include "bitstream_manager.h" +#include "bus_group.h" +#include "circuit_library.h" +#include "config_protocol.h" +#include "fabric_global_port_info.h" +#include "io_location_map.h" +#include "io_name_map.h" +#include "module_manager.h" +#include "pin_constraints.h" +#include "verilog_testbench_options.h" +#include "vpr_context.h" +#include "vpr_netlist_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int print_verilog_mock_fpga_wrapper( + const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, + const AtomContext& atom_ctx, const PlacementContext& place_ctx, + const PinConstraints& pin_constraints, const BusGroup& bus_group, + const IoLocationMap& io_location_map, const IoNameMap& io_name_map, + const VprNetlistAnnotation& netlist_annotation, + const std::string& circuit_name, const std::string& verilog_fname, + const VerilogTestbenchOption& options); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index c0d3ef4d7..18e6c5e2d 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -306,9 +306,8 @@ static int print_verilog_preconfig_top_module_connect_global_ports( * while uses 'force' syntax to impost the bitstream at mem_inv port *******************************************************************/ static void print_verilog_preconfig_top_module_force_bitstream( - std::fstream &fp, const ModuleManager &module_manager, - const ModuleId &top_module, const BitstreamManager &bitstream_manager, - const bool &output_datab_bits) { + std::fstream &fp, const std::string &top_block_name, + const BitstreamManager &bitstream_manager, const bool &output_datab_bits) { /* Validate the file stream */ valid_file_stream(fp); @@ -325,14 +324,11 @@ static void print_verilog_preconfig_top_module_force_bitstream( } /* Build the hierarchical path of the configuration bit in modules */ std::vector block_hierarchy = - find_bitstream_manager_block_hierarchy(bitstream_manager, - config_block_id); - /* Drop the first block, which is the top module, it should be replaced by - * the instance name here */ + find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id, + top_block_name); /* Ensure that this is the module we want to drop! */ - VTR_ASSERT(0 == - module_manager.module_name(top_module) - .compare(bitstream_manager.block_name(block_hierarchy[0]))); + VTR_ASSERT(top_block_name == + bitstream_manager.block_name(block_hierarchy[0])); block_hierarchy.erase(block_hierarchy.begin()); /* Build the full hierarchy path */ std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME); @@ -386,9 +382,8 @@ static void print_verilog_preconfig_top_module_force_bitstream( * This function uses '$deposit' syntax to do so *******************************************************************/ static void print_verilog_preconfig_top_module_deposit_bitstream( - std::fstream &fp, const ModuleManager &module_manager, - const ModuleId &top_module, const BitstreamManager &bitstream_manager, - const bool &output_datab_bits) { + std::fstream &fp, const std::string &top_block_name, + const BitstreamManager &bitstream_manager, const bool &output_datab_bits) { /* Validate the file stream */ valid_file_stream(fp); @@ -405,15 +400,15 @@ static void print_verilog_preconfig_top_module_deposit_bitstream( } /* Build the hierarchical path of the configuration bit in modules */ std::vector block_hierarchy = - find_bitstream_manager_block_hierarchy(bitstream_manager, - config_block_id); + find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id, + top_block_name); /* Drop the first block, which is the top module, it should be replaced by * the instance name here */ /* Ensure that this is the module we want to drop! */ - VTR_ASSERT(0 == - module_manager.module_name(top_module) - .compare(bitstream_manager.block_name(block_hierarchy[0]))); + VTR_ASSERT(top_block_name == + bitstream_manager.block_name(block_hierarchy[0])); block_hierarchy.erase(block_hierarchy.begin()); + /* Build the full hierarchy path */ std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME); for (const ConfigBlockId &temp_block : block_hierarchy) { @@ -470,9 +465,9 @@ static void print_verilog_preconfig_top_module_deposit_bitstream( * 2. Mentor Modelsim prefers using '$deposit' syntax to do so *******************************************************************/ static void print_verilog_preconfig_top_module_load_bitstream( - std::fstream &fp, const ModuleManager &module_manager, - const ModuleId &top_module, const CircuitLibrary &circuit_lib, - const CircuitModelId &mem_model, const BitstreamManager &bitstream_manager, + std::fstream &fp, const std::string &top_block_name, + const CircuitLibrary &circuit_lib, const CircuitModelId &mem_model, + const BitstreamManager &bitstream_manager, const e_embedded_bitstream_hdl_type &embedded_bitstream_hdl_type) { /* Skip the datab port if there is only 1 output port in memory model * Currently, it assumes that the data output port is always defined while @@ -494,11 +489,11 @@ static void print_verilog_preconfig_top_module_load_bitstream( /* Use assign syntax for Icarus simulator */ if (EMBEDDED_BITSTREAM_HDL_IVERILOG == embedded_bitstream_hdl_type) { print_verilog_preconfig_top_module_force_bitstream( - fp, module_manager, top_module, bitstream_manager, output_datab_bits); + fp, top_block_name, bitstream_manager, output_datab_bits); /* Use deposit syntax for other simulators */ } else if (EMBEDDED_BITSTREAM_HDL_MODELSIM == embedded_bitstream_hdl_type) { print_verilog_preconfig_top_module_deposit_bitstream( - fp, module_manager, top_module, bitstream_manager, output_datab_bits); + fp, top_block_name, bitstream_manager, output_datab_bits); } print_verilog_comment( @@ -545,7 +540,7 @@ int print_verilog_preconfig_top_module( const FabricGlobalPortInfo &global_ports, const AtomContext &atom_ctx, const PlacementContext &place_ctx, const PinConstraints &pin_constraints, const BusGroup &bus_group, const IoLocationMap &io_location_map, - const VprNetlistAnnotation &netlist_annotation, + const IoNameMap &io_name_map, const VprNetlistAnnotation &netlist_annotation, const std::string &circuit_name, const std::string &verilog_fname, const VerilogTestbenchOption &options) { std::string timer_message = @@ -577,20 +572,33 @@ int print_verilog_preconfig_top_module( print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation, bus_group); - /* Find the top_module */ - ModuleId top_module = - module_manager.find_module(generate_fpga_top_module_name()); - VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + /* Spot the dut module */ + ModuleId top_module = module_manager.find_module(options.dut_module()); + if (!module_manager.valid_module_id(top_module)) { + VTR_LOG_ERROR( + "Unable to find the DUT module '%s'. Please check if you create " + "dedicated module when building the fabric!\n", + options.dut_module().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Note that we always need the core module as it contains the original port + * names before possible renaming at top-level module. If there is no core + * module, it means that the current top module is the core module */ + ModuleId core_module = + module_manager.find_module(generate_fpga_core_module_name()); + if (!module_manager.valid_module_id(core_module)) { + core_module = top_module; + } /* Print internal wires */ print_verilog_preconfig_top_module_internal_wires(fp, module_manager, - top_module); + core_module); /* Instanciate FPGA top-level module */ print_verilog_testbench_fpga_instance( - fp, module_manager, top_module, + fp, module_manager, top_module, core_module, std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME), - std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), io_name_map, options.explicit_port_mapping()); /* Find clock ports in benchmark */ @@ -600,7 +608,7 @@ int print_verilog_preconfig_top_module( /* Connect FPGA top module global ports to constant or benchmark global * signals! */ status = print_verilog_preconfig_top_module_connect_global_ports( - fp, module_manager, top_module, pin_constraints, global_ports, + fp, module_manager, core_module, pin_constraints, global_ports, benchmark_clock_port_names); if (CMD_EXEC_FATAL_ERROR == status) { return status; @@ -608,7 +616,7 @@ int print_verilog_preconfig_top_module( /* Connect I/Os to benchmark I/Os or constant driver */ print_verilog_testbench_connect_fpga_ios( - fp, module_manager, top_module, atom_ctx, place_ctx, io_location_map, + fp, module_manager, core_module, atom_ctx, place_ctx, io_location_map, netlist_annotation, bus_group, std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), std::string(), std::string(), std::vector(), @@ -618,10 +626,20 @@ int print_verilog_preconfig_top_module( CircuitModelId sram_model = config_protocol.memory_model(); VTR_ASSERT(true == circuit_lib.valid_model_id(sram_model)); + /* If we do have the core module, and the dut is specified as core module, the + * hierarchy path when adding should be the instance name of the core module + */ + std::string inst_name = generate_fpga_top_module_name(); + if (options.dut_module() == generate_fpga_core_module_name()) { + ModuleId parent_module = + module_manager.find_module(generate_fpga_top_module_name()); + inst_name = module_manager.instance_name(parent_module, core_module, 0); + } + /* Assign FPGA internal SRAM/Memory ports to bitstream values, only output * when needed */ print_verilog_preconfig_top_module_load_bitstream( - fp, module_manager, top_module, circuit_lib, sram_model, bitstream_manager, + fp, inst_name, circuit_lib, sram_model, bitstream_manager, options.embedded_bitstream_hdl_type()); /* Add signal initialization: diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h index a309f9fae..59501a15f 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h @@ -13,6 +13,7 @@ #include "config_protocol.h" #include "fabric_global_port_info.h" #include "io_location_map.h" +#include "io_name_map.h" #include "module_manager.h" #include "pin_constraints.h" #include "verilog_testbench_options.h" @@ -33,7 +34,7 @@ int print_verilog_preconfig_top_module( const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, const BusGroup& bus_group, const IoLocationMap& io_location_map, - const VprNetlistAnnotation& netlist_annotation, + const IoNameMap& io_name_map, const VprNetlistAnnotation& netlist_annotation, const std::string& circuit_name, const std::string& verilog_fname, const VerilogTestbenchOption& options); diff --git a/openfpga/src/fpga_verilog/verilog_routing.cpp b/openfpga/src/fpga_verilog/verilog_routing.cpp index fe93a9fd4..1cf57dabb 100644 --- a/openfpga/src/fpga_verilog/verilog_routing.cpp +++ b/openfpga/src/fpga_verilog/verilog_routing.cpp @@ -280,6 +280,7 @@ static void print_verilog_flatten_connection_block_modules( void print_verilog_flatten_routing_modules(NetlistManager& netlist_manager, const ModuleManager& module_manager, const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph, const std::string& subckt_dir, const std::string& subckt_dir_name, const FabricVerilogOption& options) { @@ -293,7 +294,7 @@ void print_verilog_flatten_routing_modules(NetlistManager& netlist_manager, for (size_t ix = 0; ix < sb_range.x(); ++ix) { for (size_t iy = 0; iy < sb_range.y(); ++iy) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); - if (true != rr_gsb.is_sb_exist()) { + if (true != rr_gsb.is_sb_exist(rr_graph)) { continue; } print_verilog_routing_switch_box_unique_module( diff --git a/openfpga/src/fpga_verilog/verilog_routing.h b/openfpga/src/fpga_verilog/verilog_routing.h index f33c44d43..2766c1b2a 100644 --- a/openfpga/src/fpga_verilog/verilog_routing.h +++ b/openfpga/src/fpga_verilog/verilog_routing.h @@ -10,6 +10,7 @@ #include "module_manager.h" #include "mux_library.h" #include "netlist_manager.h" +#include "rr_graph_view.h" /******************************************************************** * Function declaration @@ -21,6 +22,7 @@ namespace openfpga { void print_verilog_flatten_routing_modules(NetlistManager& netlist_manager, const ModuleManager& module_manager, const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph, const std::string& subckt_dir, const std::string& subckt_dir_name, const FabricVerilogOption& options); diff --git a/openfpga/src/fpga_verilog/verilog_testbench_options.cpp b/openfpga/src/fpga_verilog/verilog_testbench_options.cpp index 885ddc744..5e4709419 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_options.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_options.cpp @@ -3,6 +3,7 @@ ******************************************************************************/ #include "verilog_testbench_options.h" +#include "openfpga_naming.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -14,6 +15,7 @@ namespace openfpga { *************************************************/ VerilogTestbenchOption::VerilogTestbenchOption() { output_directory_.clear(); + dut_module_ = "fpga_top"; fabric_netlist_file_path_.clear(); reference_benchmark_file_path_.clear(); print_preconfig_top_testbench_ = false; @@ -37,6 +39,8 @@ std::string VerilogTestbenchOption::output_directory() const { return output_directory_; } +std::string VerilogTestbenchOption::dut_module() const { return dut_module_; } + std::string VerilogTestbenchOption::fabric_netlist_file_path() const { return fabric_netlist_file_path_; } @@ -108,6 +112,19 @@ void VerilogTestbenchOption::set_output_directory( output_directory_ = output_dir; } +void VerilogTestbenchOption::set_dut_module(const std::string& dut_module) { + /* Precheck: only accept two legal names */ + if (dut_module != generate_fpga_top_module_name() && + dut_module != generate_fpga_core_module_name()) { + VTR_LOG_ERROR( + "Invalid module name '%s' for Design Under Test (DUT)! Expect [%s|%s]\n", + dut_module.c_str(), generate_fpga_top_module_name().c_str(), + generate_fpga_core_module_name().c_str()); + exit(1); + } + dut_module_ = dut_module; +} + void VerilogTestbenchOption::set_fabric_netlist_file_path( const std::string& fabric_netlist_file_path) { fabric_netlist_file_path_ = fabric_netlist_file_path; diff --git a/openfpga/src/fpga_verilog/verilog_testbench_options.h b/openfpga/src/fpga_verilog/verilog_testbench_options.h index 7610f95b9..aafa15d71 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_options.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_options.h @@ -37,6 +37,7 @@ class VerilogTestbenchOption { public: /* Public accessors */ std::string output_directory() const; + std::string dut_module() const; std::string fabric_netlist_file_path() const; std::string reference_benchmark_file_path() const; bool fast_configuration() const; @@ -60,6 +61,7 @@ class VerilogTestbenchOption { public: /* Public mutators */ void set_output_directory(const std::string& output_dir); + void set_dut_module(const std::string& dut_module); /* The reference verilog file path is the key parameters that will have an * impact on other options: * - print_preconfig_top_testbench @@ -93,6 +95,7 @@ class VerilogTestbenchOption { private: /* Internal Data */ std::string output_directory_; + std::string dut_module_; std::string fabric_netlist_file_path_; std::string reference_benchmark_file_path_; bool fast_configuration_; diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index 8c91e50d0..e3895c28d 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -34,12 +34,11 @@ namespace openfpga { .out(out_postfix>) ); *******************************************************************/ -void print_verilog_testbench_fpga_instance(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const std::string& top_instance_name, - const std::string& net_postfix, - const bool& explicit_port_mapping) { +void print_verilog_testbench_fpga_instance( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const ModuleId& core_module, + const std::string& top_instance_name, const std::string& net_postfix, + const IoNameMap& io_name_map, const bool& explicit_port_mapping) { /* Validate the file stream */ valid_file_stream(fp); @@ -47,15 +46,63 @@ void print_verilog_testbench_fpga_instance(std::fstream& fp, print_verilog_comment( fp, std::string("----- FPGA top-level module to be capsulated -----")); + /* Precheck on the top module and decide if we need to consider I/O naming + * - If we do have a fpga_core module added, and dut is fpga_top, we need a + * I/O naming + * - If we do NOT have a fpga_core module added, and dut is fpga_top, we do + * NOT need a I/O naming + * - If we do have a fpga_core module added, and dut is fpga_core, we do NOT + * need a I/O naming + * - If we do NOT have a fpga_core module added, and dut is fpga_core, it + * should error out earlier. + */ + bool require_io_naming = false; + if (top_module != core_module) { + require_io_naming = true; + } + /* Create an empty port-to-port name mapping, because we use default names */ std::map port2port_name_map; - if (!net_postfix.empty()) { + if (!require_io_naming) { + if (!net_postfix.empty()) { + for (const ModulePortId& module_port_id : + module_manager.module_ports(top_module)) { + BasicPort module_port = + module_manager.module_port(top_module, module_port_id); + BasicPort net_port = module_port; + net_port.set_name(module_port.get_name() + net_postfix); + port2port_name_map[module_port.get_name()] = net_port; + } + } + } else { + VTR_ASSERT_SAFE(require_io_naming); + /* We walk through the ports under top module. Find renamed ports at + * core-level and use them as net names */ for (const ModulePortId& module_port_id : module_manager.module_ports(top_module)) { BasicPort module_port = module_manager.module_port(top_module, module_port_id); - BasicPort net_port = module_port; - net_port.set_name(module_port.get_name() + net_postfix); + /* Bypass dummy port: the port does not exist at core module */ + if (io_name_map.fpga_top_port_is_dummy(module_port)) { + ModulePortId core_module_port = + module_manager.find_module_port(core_module, module_port.get_name()); + if (!module_manager.valid_module_port_id(core_module, + core_module_port)) { + /* Print the wire for the dummy port */ + fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" + << std::endl; + continue; + } + } + /* Not a dummy port, if it is renamed, use the new name. Otherwise, keep + * the old name */ + BasicPort net_port = io_name_map.fpga_core_port(module_port); + if (net_port.is_valid()) { + net_port.set_name(net_port.get_name() + net_postfix); + } else { + net_port = module_port; + net_port.set_name(module_port.get_name() + net_postfix); + } port2port_name_map[module_port.get_name()] = net_port; } } @@ -78,7 +125,8 @@ void print_verilog_testbench_benchmark_instance( const std::string& module_input_port_postfix, const std::string& module_output_port_postfix, const std::string& input_port_postfix, const std::string& output_port_postfix, - const std::vector& clock_port_names, const AtomContext& atom_ctx, + const std::vector& clock_port_names, + const bool& include_clock_port_postfix, const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, const PinConstraints& pin_constraints, const BusGroup& bus_group, const bool& use_explicit_port_map) { @@ -183,6 +231,8 @@ void print_verilog_testbench_benchmark_instance( clock_port_names.end(), port_names[iport])) { fp << input_port_postfix; + } else if (include_clock_port_postfix) { + fp << input_port_postfix; } pin_counter++; @@ -206,6 +256,8 @@ void print_verilog_testbench_benchmark_instance( clock_port_names.end(), port_names[iport])) { fp << input_port_postfix; + } else if (include_clock_port_postfix) { + fp << input_port_postfix; } } @@ -914,20 +966,16 @@ void print_verilog_testbench_random_stimuli( * which are * 1. the shared input ports (registers) to drive both * FPGA fabric and benchmark instance - * 2. the output ports (wires) for both FPGA fabric and benchmark instance - * 3. the checking flag ports to evaluate if outputs matches under the * same input vectors *******************************************************************/ -void print_verilog_testbench_shared_ports( +void print_verilog_testbench_shared_input_ports( std::fstream& fp, const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, const PinConstraints& pin_constraints, const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, const std::vector& clock_port_names, - const std::string& shared_input_port_postfix, - const std::string& benchmark_output_port_postfix, - const std::string& fpga_output_port_postfix, - const std::string& check_flag_port_postfix, const bool& no_self_checking) { + const bool& include_clock_ports, const std::string& shared_input_port_postfix, + const bool& use_reg_port) { /* Validate the file stream */ valid_file_stream(fp); @@ -950,7 +998,9 @@ void print_verilog_testbench_shared_ports( if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), block_name)) { - continue; + if (!include_clock_ports) { + continue; + } } /* Each logical block assumes a single-width port */ @@ -959,8 +1009,13 @@ void print_verilog_testbench_shared_ports( if (false == port_is_fabric_global_reset_port(global_ports, module_manager, pin_constraints.net_pin(block_name))) { - fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, input_port) << ";" - << std::endl; + if (use_reg_port) { + fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, input_port) << ";" + << std::endl; + } else { + fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, input_port) + << ";" << std::endl; + } } else { fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, input_port) << ";" << std::endl; @@ -969,6 +1024,19 @@ void print_verilog_testbench_shared_ports( /* Add an empty line as splitter */ fp << std::endl; +} + +/******************************************************************** + * Print Verilog declaration of shared ports appear in testbenches + * which are + * 2. the output ports (wires) for FPGA fabric + *******************************************************************/ +void print_verilog_testbench_shared_fpga_output_ports( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::string& fpga_output_port_postfix) { + /* Validate the file stream */ + valid_file_stream(fp); /* Instantiate wires for FPGA fabric outputs */ print_verilog_comment(fp, std::string("----- FPGA fabric outputs -------")); @@ -996,10 +1064,19 @@ void print_verilog_testbench_shared_ports( /* Add an empty line as splitter */ fp << std::endl; +} - if (no_self_checking) { - return; - } +/******************************************************************** + * Print Verilog declaration of shared ports appear in testbenches + * which are + * 2. the output ports (wires) for benchmark instance + *******************************************************************/ +void print_verilog_testbench_shared_benchmark_output_ports( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::string& benchmark_output_port_postfix) { + /* Validate the file stream */ + valid_file_stream(fp); /* Instantiate wire for benchmark output */ print_verilog_comment(fp, std::string("----- Benchmark outputs -------")); @@ -1026,6 +1103,23 @@ void print_verilog_testbench_shared_ports( /* Add an empty line as splitter */ fp << std::endl; +} + +/******************************************************************** + * Print Verilog declaration of shared ports appear in testbenches + * which are + * 1. the shared input ports (registers) to drive both + * FPGA fabric and benchmark instance + * 2. the output ports (wires) for both FPGA fabric and benchmark instance + * 3. the checking flag ports to evaluate if outputs matches under the + * same input vectors + *******************************************************************/ +void print_verilog_testbench_shared_check_flags( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::string& check_flag_port_postfix) { + /* Validate the file stream */ + valid_file_stream(fp); /* Instantiate register for output comparison */ print_verilog_comment( @@ -1054,6 +1148,44 @@ void print_verilog_testbench_shared_ports( fp << std::endl; } +/******************************************************************** + * Print Verilog declaration of shared ports appear in testbenches + * which are + * 1. the shared input ports (registers) to drive both + * FPGA fabric and benchmark instance + * 2. the output ports (wires) for both FPGA fabric and benchmark instance + * 3. the checking flag ports to evaluate if outputs matches under the + * same input vectors + *******************************************************************/ +void print_verilog_testbench_shared_ports( + std::fstream& fp, const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::vector& clock_port_names, + const std::string& shared_input_port_postfix, + const std::string& benchmark_output_port_postfix, + const std::string& fpga_output_port_postfix, + const std::string& check_flag_port_postfix, const bool& no_self_checking) { + print_verilog_testbench_shared_input_ports( + fp, module_manager, global_ports, pin_constraints, atom_ctx, + netlist_annotation, clock_port_names, false, shared_input_port_postfix, + true); + + print_verilog_testbench_shared_fpga_output_ports( + fp, atom_ctx, netlist_annotation, fpga_output_port_postfix); + + if (no_self_checking) { + return; + } + + print_verilog_testbench_shared_benchmark_output_ports( + fp, atom_ctx, netlist_annotation, benchmark_output_port_postfix); + + print_verilog_testbench_shared_check_flags(fp, atom_ctx, netlist_annotation, + check_flag_port_postfix); +} + /******************************************************************** * Print signal initialization which * deposit initial values for the input ports of primitive circuit models diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.h b/openfpga/src/fpga_verilog/verilog_testbench_utils.h index 2aedd18e3..87059645f 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.h @@ -12,6 +12,7 @@ #include "circuit_library.h" #include "fabric_global_port_info.h" #include "io_location_map.h" +#include "io_name_map.h" #include "module_manager.h" #include "pin_constraints.h" #include "simulation_setting.h" @@ -25,12 +26,11 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_testbench_fpga_instance(std::fstream& fp, - const ModuleManager& module_manager, - const ModuleId& top_module, - const std::string& top_instance_name, - const std::string& net_postfix, - const bool& explicit_port_mapping); +void print_verilog_testbench_fpga_instance( + std::fstream& fp, const ModuleManager& module_manager, + const ModuleId& top_module, const ModuleId& core_module, + const std::string& top_instance_name, const std::string& net_postfix, + const IoNameMap& io_name_map, const bool& explicit_port_mapping); void print_verilog_testbench_benchmark_instance( std::fstream& fp, const std::string& module_name, @@ -38,7 +38,8 @@ void print_verilog_testbench_benchmark_instance( const std::string& module_input_port_postfix, const std::string& module_output_port_postfix, const std::string& input_port_postfix, const std::string& output_port_postfix, - const std::vector& clock_port_names, const AtomContext& atom_ctx, + const std::vector& clock_port_names, + const bool& include_clock_port_postfix, const AtomContext& atom_ctx, const VprNetlistAnnotation& netlist_annotation, const PinConstraints& pin_constraints, const BusGroup& bus_group, const bool& use_explicit_port_map); @@ -90,6 +91,30 @@ void print_verilog_testbench_random_stimuli( const std::string& check_flag_port_postfix, const std::vector& clock_ports, const bool& no_self_checking); +void print_verilog_testbench_shared_input_ports( + std::fstream& fp, const ModuleManager& module_manager, + const FabricGlobalPortInfo& global_ports, + const PinConstraints& pin_constraints, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::vector& clock_port_names, + const bool& include_clock_ports, const std::string& shared_input_port_postfix, + const bool& use_reg_port); + +void print_verilog_testbench_shared_fpga_output_ports( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::string& fpga_output_port_postfix); + +void print_verilog_testbench_shared_benchmark_output_ports( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::string& benchmark_output_port_postfix); + +void print_verilog_testbench_shared_check_flags( + std::fstream& fp, const AtomContext& atom_ctx, + const VprNetlistAnnotation& netlist_annotation, + const std::string& check_flag_port_postfix); + void print_verilog_testbench_shared_ports( std::fstream& fp, const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, diff --git a/openfpga/src/fpga_verilog/verilog_tile.cpp b/openfpga/src/fpga_verilog/verilog_tile.cpp new file mode 100644 index 000000000..400695554 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_tile.cpp @@ -0,0 +1,113 @@ +/******************************************************************** + * This file includes functions that are used to print the top-level + * module for the FPGA fabric in Verilog format + *******************************************************************/ +#include "verilog_tile.h" + +#include +#include +#include + +#include "command_exit_codes.h" +#include "openfpga_digest.h" +#include "openfpga_naming.h" +#include "verilog_constants.h" +#include "verilog_module_writer.h" +#include "verilog_writer_utils.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Print the tile module for the FPGA fabric in Verilog format + *******************************************************************/ +static int print_verilog_tile_module_netlist( + NetlistManager& netlist_manager, const ModuleManager& module_manager, + const std::string& verilog_dir, const FabricTile& fabric_tile, + const FabricTileId& fabric_tile_id, const std::string& subckt_dir_name, + const FabricVerilogOption& options) { + /* Create a module as the top-level fabric, and add it to the module manager + */ + vtr::Point tile_coord = fabric_tile.tile_coordinate(fabric_tile_id); + std::string tile_module_name = generate_tile_module_name(tile_coord); + ModuleId tile_module = module_manager.find_module(tile_module_name); + if (!module_manager.valid_module_id(tile_module)) { + return CMD_EXEC_FATAL_ERROR; + } + + /* Start printing out Verilog netlists */ + /* Create the file name for Verilog netlist */ + std::string verilog_fname(generate_tile_module_netlist_name( + tile_module_name, std::string(VERILOG_NETLIST_FILE_POSTFIX))); + std::string verilog_fpath(verilog_dir + verilog_fname); + + VTR_LOG("Writing Verilog netlist '%s' for tile module '%s'...", + verilog_fpath.c_str(), tile_module_name.c_str()); + + /* Create the file stream */ + std::fstream fp; + fp.open(verilog_fpath, std::fstream::out | std::fstream::trunc); + + check_file_stream(verilog_fpath.c_str(), fp); + + print_verilog_file_header(fp, std::string("Tile Verilog module for FPGA"), + options.time_stamp()); + + /* Write the module content in Verilog format */ + write_verilog_module_to_file(fp, module_manager, tile_module, + options.explicit_port_mapping(), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; + + /* Close file handler */ + fp.close(); + + /* Add fname to the netlist name list */ + NetlistId nlist_id = NetlistId::INVALID(); + if (options.use_relative_path()) { + nlist_id = netlist_manager.add_netlist(subckt_dir_name + verilog_fname); + } else { + nlist_id = netlist_manager.add_netlist(verilog_fpath); + } + + VTR_ASSERT(nlist_id); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::TILE_MODULE_NETLIST); + + VTR_LOG("Done\n"); + + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Print all the tile modules for the FPGA fabric in Verilog format + *******************************************************************/ +int print_verilog_tiles(NetlistManager& netlist_manager, + const ModuleManager& module_manager, + const std::string& verilog_dir, + const FabricTile& fabric_tile, + const std::string& subckt_dir_name, + const FabricVerilogOption& options) { + vtr::ScopedStartFinishTimer timer("Build tile modules for the FPGA fabric"); + + int status_code = CMD_EXEC_SUCCESS; + + /* Build a module for each unique tile */ + for (FabricTileId fabric_tile_id : fabric_tile.unique_tiles()) { + status_code = print_verilog_tile_module_netlist( + netlist_manager, module_manager, verilog_dir, fabric_tile, fabric_tile_id, + subckt_dir_name, options); + if (status_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + + return status_code; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_tile.h b/openfpga/src/fpga_verilog/verilog_tile.h new file mode 100644 index 000000000..03dac11ae --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_tile.h @@ -0,0 +1,30 @@ +#ifndef VERILOG_TILE_H +#define VERILOG_TILE_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "fabric_tile.h" +#include "fabric_verilog_options.h" +#include "module_manager.h" +#include "netlist_manager.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int print_verilog_tiles(NetlistManager& netlist_manager, + const ModuleManager& module_manager, + const std::string& verilog_dir, + const FabricTile& fabric_tile, + const std::string& subckt_dir_name, + const FabricVerilogOption& options); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_verilog/verilog_top_module.cpp b/openfpga/src/fpga_verilog/verilog_top_module.cpp index 0fb6b0d0c..fc87412ca 100644 --- a/openfpga/src/fpga_verilog/verilog_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_module.cpp @@ -21,6 +21,66 @@ /* begin namespace openfpga */ namespace openfpga { +/******************************************************************** + * Print the wrapper module for the FPGA fabric in Verilog format + *******************************************************************/ +void print_verilog_core_module(NetlistManager& netlist_manager, + const ModuleManager& module_manager, + const std::string& verilog_dir, + const FabricVerilogOption& options) { + /* Create a module as the top-level fabric, and add it to the module manager + */ + std::string core_module_name = generate_fpga_core_module_name(); + ModuleId core_module = module_manager.find_module(core_module_name); + /* It could happen that the module does not exist, just return with no errors + */ + if (!module_manager.valid_module_id(core_module)) { + return; + } + + /* Start printing out Verilog netlists */ + /* Create the file name for Verilog netlist */ + std::string verilog_fname( + generate_fpga_core_netlist_name(std::string(VERILOG_NETLIST_FILE_POSTFIX))); + std::string verilog_fpath(verilog_dir + verilog_fname); + + VTR_LOG("Writing Verilog netlist for wrapper module of FPGA fabric '%s'...", + verilog_fpath.c_str()); + + /* Create the file stream */ + std::fstream fp; + fp.open(verilog_fpath, std::fstream::out | std::fstream::trunc); + + check_file_stream(verilog_fpath.c_str(), fp); + + print_verilog_file_header(fp, std::string("Wrapper Verilog module for FPGA"), + options.time_stamp()); + + /* Write the module content in Verilog format */ + write_verilog_module_to_file(fp, module_manager, core_module, + options.explicit_port_mapping(), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; + + /* Close file handler */ + fp.close(); + + /* Add fname to the netlist name list */ + NetlistId nlist_id = NetlistId::INVALID(); + if (options.use_relative_path()) { + nlist_id = netlist_manager.add_netlist(verilog_fname); + } else { + nlist_id = netlist_manager.add_netlist(verilog_fpath); + } + VTR_ASSERT(nlist_id); + netlist_manager.set_netlist_type(nlist_id, + NetlistManager::TOP_MODULE_NETLIST); + + VTR_LOG("Done\n"); +} + /******************************************************************** * Print the top-level module for the FPGA fabric in Verilog format * This function will diff --git a/openfpga/src/fpga_verilog/verilog_top_module.h b/openfpga/src/fpga_verilog/verilog_top_module.h index b4b0bab20..c10dd5e89 100644 --- a/openfpga/src/fpga_verilog/verilog_top_module.h +++ b/openfpga/src/fpga_verilog/verilog_top_module.h @@ -17,6 +17,11 @@ /* begin namespace openfpga */ namespace openfpga { +void print_verilog_core_module(NetlistManager& netlist_manager, + const ModuleManager& module_manager, + const std::string& verilog_dir, + const FabricVerilogOption& options); + void print_verilog_top_module(NetlistManager& netlist_manager, const ModuleManager& module_manager, const std::string& verilog_dir, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index b98a44007..a1c16baf5 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1061,6 +1061,17 @@ static size_t calculate_num_config_clock_cycles( (float)full_num_config_clock_cycles - 1.)); } + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() && + BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + // Only support new fast way if both BL/WL protocols are flatten + // Based on 100K LE FPGA, we are wasting a lot of time to build + // MemoryBankFlattenFabricBitstream + // just to get the effective WL addr size. So wasteful of the resource + const FabricBitstreamMemoryBank& memory_bank = + fabric_bitstream.memory_bank_info(fast_configuration, + bit_value_to_skip); + num_config_clock_cycles = + 1 + memory_bank.get_longest_effective_wl_count(); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { num_config_clock_cycles = 1 + build_memory_bank_flatten_fabric_bitstream( @@ -1146,7 +1157,7 @@ static void print_verilog_top_testbench_benchmark_instance( std::string(TOP_TESTBENCH_REFERENCE_INSTANCE_NAME), std::string(), std::string(), std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), clock_port_names, - atom_ctx, netlist_annotation, pin_constraints, bus_group, + false, atom_ctx, netlist_annotation, pin_constraints, bus_group, explicit_port_mapping); print_verilog_comment( @@ -2435,7 +2446,7 @@ int print_verilog_full_testbench( const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, const BusGroup& bus_group, const std::string& bitstream_file, - const IoLocationMap& io_location_map, + const IoLocationMap& io_location_map, const IoNameMap& io_name_map, const VprNetlistAnnotation& netlist_annotation, const std::string& circuit_name, const std::string& verilog_fname, const SimulationSetting& simulation_parameters, @@ -2465,10 +2476,23 @@ int print_verilog_full_testbench( circuit_name; print_verilog_file_header(fp, title, options.time_stamp()); - /* Find the top_module */ - ModuleId top_module = - module_manager.find_module(generate_fpga_top_module_name()); - VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + /* Spot the dut module */ + ModuleId top_module = module_manager.find_module(options.dut_module()); + if (!module_manager.valid_module_id(top_module)) { + VTR_LOG_ERROR( + "Unable to find the DUT module '%s'. Please check if you create " + "dedicated module when building the fabric!\n", + options.dut_module().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Note that we always need the core module as it contains the original port + * names before possible renaming at top-level module. If there is no core + * module, it means that the current top module is the core module */ + ModuleId core_module = + module_manager.find_module(generate_fpga_core_module_name()); + if (!module_manager.valid_module_id(core_module)) { + core_module = top_module; + } /* Preparation: find all the clock ports */ std::vector clock_port_names = @@ -2492,7 +2516,7 @@ int print_verilog_full_testbench( /* Start of testbench */ print_verilog_top_testbench_ports( - fp, module_manager, top_module, atom_ctx, netlist_annotation, + fp, module_manager, core_module, atom_ctx, netlist_annotation, clock_port_names, global_ports, pin_constraints, simulation_parameters, config_protocol, circuit_name, options); @@ -2522,7 +2546,7 @@ int print_verilog_full_testbench( /* Generate stimuli for programming interface */ int status = CMD_EXEC_SUCCESS; status = print_verilog_top_testbench_configuration_protocol_stimulus( - fp, config_protocol, simulation_parameters, module_manager, top_module, + fp, config_protocol, simulation_parameters, module_manager, core_module, fast_configuration, bit_value_to_skip, fabric_bitstream, blwl_sr_banks, prog_clock_period, VERILOG_SIM_TIMESCALE); @@ -2557,19 +2581,19 @@ int print_verilog_full_testbench( /* Generate stimuli for global ports or connect them to existed signals */ print_verilog_top_testbench_global_ports_stimuli( - fp, module_manager, top_module, pin_constraints, config_protocol, + fp, module_manager, core_module, pin_constraints, config_protocol, global_ports, simulation_parameters, active_global_prog_reset, active_global_prog_set); /* Instanciate FPGA top-level module */ print_verilog_testbench_fpga_instance( - fp, module_manager, top_module, - std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), std::string(), + fp, module_manager, top_module, core_module, + std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), std::string(), io_name_map, explicit_port_mapping); /* Connect I/Os to benchmark I/Os or constant driver */ print_verilog_testbench_connect_fpga_ios( - fp, module_manager, top_module, atom_ctx, place_ctx, io_location_map, + fp, module_manager, core_module, atom_ctx, place_ctx, io_location_map, netlist_annotation, BusGroup(), std::string(), std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX), std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), clock_port_names, @@ -2585,7 +2609,7 @@ int print_verilog_full_testbench( /* load bitstream to FPGA fabric in a configuration phase */ print_verilog_full_testbench_bitstream( fp, bitstream_file, config_protocol, apply_fast_configuration, - bit_value_to_skip, module_manager, top_module, bitstream_manager, + bit_value_to_skip, module_manager, core_module, bitstream_manager, fabric_bitstream, blwl_sr_banks); /* Add signal initialization: diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.h b/openfpga/src/fpga_verilog/verilog_top_testbench.h index dfe24a6c9..0e9b4865c 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.h @@ -14,6 +14,7 @@ #include "fabric_bitstream.h" #include "fabric_global_port_info.h" #include "io_location_map.h" +#include "io_name_map.h" #include "memory_bank_shift_register_banks.h" #include "module_manager.h" #include "pin_constraints.h" @@ -38,7 +39,7 @@ int print_verilog_full_testbench( const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, const BusGroup& bus_group, const std::string& bitstream_file, - const IoLocationMap& io_location_map, + const IoLocationMap& io_location_map, const IoNameMap& io_name_map, const VprNetlistAnnotation& netlist_annotation, const std::string& circuit_name, const std::string& verilog_fname, const SimulationSetting& simulation_parameters, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 8b70ef3fb..d4a211e89 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -565,9 +565,12 @@ static void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream( valid_file_stream(fp); /* Reorganize the fabric bitstream by the same address across regions */ - MemoryBankFlattenFabricBitstream fabric_bits_by_addr = - build_memory_bank_flatten_fabric_bitstream( - fabric_bitstream, fast_configuration, bit_value_to_skip); + // New way to get the effective WL addr size. + // Based on 100K LE FPGA, we are wasting a lot of time to build + // MemoryBankFlattenFabricBitstream just to get size(). So wasteful of the + // resource + const FabricBitstreamMemoryBank& memory_bank = + fabric_bitstream.memory_bank_info(fast_configuration, bit_value_to_skip); /* Feed address and data input pair one by one * Note: the first cycle is reserved for programming reset @@ -604,7 +607,7 @@ static void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream( /* Define a constant for the bitstream length */ print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), - fabric_bits_by_addr.size()); + memory_bank.get_longest_effective_wl_count()); print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), bl_port_width + wl_port_width); diff --git a/openfpga/src/tile_direct/build_tile_direct.cpp b/openfpga/src/tile_direct/build_tile_direct.cpp index 7ea380d8c..73b5fd77a 100644 --- a/openfpga/src/tile_direct/build_tile_direct.cpp +++ b/openfpga/src/tile_direct/build_tile_direct.cpp @@ -168,7 +168,9 @@ static vtr::Point find_grid_coordinate_given_type( continue; } if (wanted_grid_type_name == - std::string(grids[coord.x()][coord.y()].type->name)) { + std::string( + grids.get_physical_type(t_physical_tile_loc(coord.x(), coord.y(), 0)) + ->name)) { return coord; } } @@ -401,13 +403,16 @@ static void build_inner_column_row_tile_direct( /* Walk through the device fabric and find the grid that fit the source */ for (size_t x = 0; x < device_ctx.grid.width(); ++x) { for (size_t y = 0; y < device_ctx.grid.height(); ++y) { + t_physical_tile_loc from_phy_tile_loc(x, y, 0); + t_physical_tile_type_ptr from_phy_tile_type = + device_ctx.grid.get_physical_type(from_phy_tile_loc); /* Bypass empty grid */ - if (true == is_empty_type(device_ctx.grid[x][y].type)) { + if (true == is_empty_type(from_phy_tile_type)) { continue; } /* Bypass the grid that does not fit the from_tile name */ - if (from_tile_name != std::string(device_ctx.grid[x][y].type->name)) { + if (from_tile_name != std::string(from_phy_tile_type->name)) { continue; } @@ -418,8 +423,10 @@ static void build_inner_column_row_tile_direct( for (const e_side& from_side : {TOP, RIGHT, BOTTOM, LEFT}) { /* Try to find the pin in this tile */ std::vector from_pins = find_physical_tile_pin_id( - device_ctx.grid[x][y].type, device_ctx.grid[x][y].width_offset, - device_ctx.grid[x][y].height_offset, from_tile_port, from_side); + from_phy_tile_type, + device_ctx.grid.get_width_offset(from_phy_tile_loc), + device_ctx.grid.get_height_offset(from_phy_tile_loc), from_tile_port, + from_side); /* If nothing found, we can continue */ if (0 == from_pins.size()) { continue; @@ -435,10 +442,12 @@ static void build_inner_column_row_tile_direct( continue; } + t_physical_tile_loc to_phy_tile_loc(to_grid_coord.x(), + to_grid_coord.y(), 0); + t_physical_tile_type_ptr to_phy_tile_type = + device_ctx.grid.get_physical_type(to_phy_tile_loc); /* Bypass the grid that does not fit the from_tile name */ - if (to_tile_name != - std::string(device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()] - .type->name)) { + if (to_tile_name != std::string(to_phy_tile_type->name)) { continue; } @@ -449,10 +458,9 @@ static void build_inner_column_row_tile_direct( for (const e_side& to_side : {TOP, RIGHT, BOTTOM, LEFT}) { /* Try to find the pin in this tile */ std::vector to_pins = find_physical_tile_pin_id( - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset, - to_tile_port, to_side); + to_phy_tile_type, device_ctx.grid.get_width_offset(to_phy_tile_loc), + device_ctx.grid.get_height_offset(to_phy_tile_loc), to_tile_port, + to_side); /* If nothing found, we can continue */ if (0 == to_pins.size()) { continue; @@ -589,13 +597,13 @@ static void build_inter_column_row_tile_direct( */ for (const e_side& from_side : {TOP, RIGHT, BOTTOM, LEFT}) { /* Try to find the pin in this tile */ + t_physical_tile_loc from_phy_tile_loc(from_grid_coord.x(), + from_grid_coord.y(), 0); std::vector from_pins = find_physical_tile_pin_id( - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].type, - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()] - .width_offset, - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()] - .height_offset, - from_tile_port, from_side); + device_ctx.grid.get_physical_type(from_phy_tile_loc), + device_ctx.grid.get_width_offset(from_phy_tile_loc), + device_ctx.grid.get_height_offset(from_phy_tile_loc), from_tile_port, + from_side); /* If nothing found, we can continue */ if (0 == from_pins.size()) { continue; @@ -619,11 +627,13 @@ static void build_inter_column_row_tile_direct( */ for (const e_side& to_side : {TOP, RIGHT, BOTTOM, LEFT}) { /* Try to find the pin in this tile */ + t_physical_tile_loc to_phy_tile_loc(to_grid_coord.x(), + to_grid_coord.y(), 0); std::vector to_pins = find_physical_tile_pin_id( - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset, - to_tile_port, to_side); + device_ctx.grid.get_physical_type(to_phy_tile_loc), + device_ctx.grid.get_width_offset(to_phy_tile_loc), + device_ctx.grid.get_height_offset(to_phy_tile_loc), to_tile_port, + to_side); /* If nothing found, we can continue */ if (0 == to_pins.size()) { continue; @@ -698,11 +708,13 @@ static void build_inter_column_row_tile_direct( */ for (const e_side& from_side : {TOP, RIGHT, BOTTOM, LEFT}) { /* Try to find the pin in this tile */ + t_physical_tile_loc from_phy_tile_loc(from_grid_coord.x(), + from_grid_coord.y(), 0); std::vector from_pins = find_physical_tile_pin_id( - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].type, - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].width_offset, - device_ctx.grid[from_grid_coord.x()][from_grid_coord.y()].height_offset, - from_tile_port, from_side); + device_ctx.grid.get_physical_type(from_phy_tile_loc), + device_ctx.grid.get_width_offset(from_phy_tile_loc), + device_ctx.grid.get_height_offset(from_phy_tile_loc), from_tile_port, + from_side); /* If nothing found, we can continue */ if (0 == from_pins.size()) { continue; @@ -726,11 +738,13 @@ static void build_inter_column_row_tile_direct( */ for (const e_side& to_side : {TOP, RIGHT, BOTTOM, LEFT}) { /* Try to find the pin in this tile */ + t_physical_tile_loc to_phy_tile_loc(to_grid_coord.x(), + to_grid_coord.y(), 0); std::vector to_pins = find_physical_tile_pin_id( - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].type, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].width_offset, - device_ctx.grid[to_grid_coord.x()][to_grid_coord.y()].height_offset, - to_tile_port, to_side); + device_ctx.grid.get_physical_type(to_phy_tile_loc), + device_ctx.grid.get_width_offset(to_phy_tile_loc), + device_ctx.grid.get_height_offset(to_phy_tile_loc), to_tile_port, + to_side); /* If nothing found, we can continue */ if (0 == to_pins.size()) { continue; diff --git a/openfpga/src/utils/check_tile_annotation.cpp b/openfpga/src/utils/check_tile_annotation.cpp index 6117e3109..929a3b24e 100644 --- a/openfpga/src/utils/check_tile_annotation.cpp +++ b/openfpga/src/utils/check_tile_annotation.cpp @@ -128,7 +128,6 @@ static int check_tile_annotation_conflicts_with_physical_tile( ++tile_info_id) { /* Must find a valid physical tile in the same name */ size_t found_matched_physical_tile = 0; - size_t found_matched_physical_tile_port = 0; std::string required_tile_name = tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id]; @@ -146,6 +145,7 @@ static int check_tile_annotation_conflicts_with_physical_tile( /* Must found a valid port where both port name and port size must * match!!! */ for (const t_sub_tile& sub_tile : physical_tile.sub_tiles) { + size_t found_matched_physical_tile_port = 0; for (const t_physical_tile_port& tile_port : sub_tile.ports) { if (std::string(tile_port.name) != required_tile_port.get_name()) { continue; @@ -167,7 +167,8 @@ static int check_tile_annotation_conflicts_with_physical_tile( } /* Check if port property matches */ - int grid_pin_index = tile_port.absolute_first_pin_index; + int grid_pin_index = sub_tile.sub_tile_to_tile_pin_indices + [tile_port.absolute_first_pin_index]; if (tile_port.is_clock != tile_annotation.global_port_is_clock(tile_global_port)) { @@ -215,6 +216,28 @@ static int check_tile_annotation_conflicts_with_physical_tile( found_matched_physical_tile_port++; } + if (0 == found_matched_physical_tile_port) { + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not " + "match " + "any physical tile port!\n", + required_tile_name.c_str(), required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } + if (1 < found_matched_physical_tile_port) { + VTR_LOGF_ERROR( + __FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more " + "than " + "1 physical tile port!\n", + required_tile_name.c_str(), required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } } } @@ -228,17 +251,6 @@ static int check_tile_annotation_conflicts_with_physical_tile( tile_annotation.global_port_name(tile_global_port).c_str()); num_err++; } - if (0 == found_matched_physical_tile_port) { - VTR_LOGF_ERROR( - __FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match " - "any physical tile port!\n", - required_tile_name.c_str(), required_tile_port.get_name().c_str(), - required_tile_port.get_lsb(), required_tile_port.get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str()); - num_err++; - } - /* If we found more than 1 match, error out */ if (1 < found_matched_physical_tile) { VTR_LOGF_ERROR( @@ -249,16 +261,6 @@ static int check_tile_annotation_conflicts_with_physical_tile( tile_annotation.global_port_name(tile_global_port).c_str()); num_err++; } - if (1 < found_matched_physical_tile_port) { - VTR_LOGF_ERROR( - __FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than " - "1 physical tile port!\n", - required_tile_name.c_str(), required_tile_port.get_name().c_str(), - required_tile_port.get_lsb(), required_tile_port.get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str()); - num_err++; - } } } diff --git a/openfpga/src/utils/circuit_library_utils.cpp b/openfpga/src/utils/circuit_library_utils.cpp index abcac433c..729050e06 100644 --- a/openfpga/src/utils/circuit_library_utils.cpp +++ b/openfpga/src/utils/circuit_library_utils.cpp @@ -188,6 +188,7 @@ size_t find_circuit_num_config_bits( } switch (config_protocol_type) { + case CONFIG_MEM_FEEDTHROUGH: case CONFIG_MEM_STANDALONE: case CONFIG_MEM_SCAN_CHAIN: case CONFIG_MEM_QL_MEMORY_BANK: diff --git a/openfpga/src/utils/device_rr_gsb_utils.cpp b/openfpga/src/utils/device_rr_gsb_utils.cpp index 31d1669ec..4f1fb8e00 100644 --- a/openfpga/src/utils/device_rr_gsb_utils.cpp +++ b/openfpga/src/utils/device_rr_gsb_utils.cpp @@ -34,12 +34,13 @@ size_t find_device_rr_gsb_num_cb_modules(const DeviceRRGSB& device_rr_gsb, * This function aims to find out the number of switch block * modules in the device rr_gsb array *******************************************************************/ -size_t find_device_rr_gsb_num_sb_modules(const DeviceRRGSB& device_rr_gsb) { +size_t find_device_rr_gsb_num_sb_modules(const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph) { size_t counter = 0; for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { const RRGSB& rr_gsb = device_rr_gsb.get_gsb(x, y); - if (true == rr_gsb.is_sb_exist()) { + if (true == rr_gsb.is_sb_exist(rr_graph)) { counter++; } } @@ -51,11 +52,13 @@ size_t find_device_rr_gsb_num_sb_modules(const DeviceRRGSB& device_rr_gsb) { /******************************************************************** * This function aims to find out the number of GSBs *******************************************************************/ -size_t find_device_rr_gsb_num_gsb_modules(const DeviceRRGSB& device_rr_gsb) { +size_t find_device_rr_gsb_num_gsb_modules(const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph) { size_t counter = 0; for (size_t x = 0; x < device_rr_gsb.get_gsb_range().x(); ++x) { for (size_t y = 0; y < device_rr_gsb.get_gsb_range().y(); ++y) { - if (true == device_rr_gsb.is_gsb_exist(vtr::Point(x, y))) { + if (true == + device_rr_gsb.is_gsb_exist(rr_graph, vtr::Point(x, y))) { counter++; } } diff --git a/openfpga/src/utils/device_rr_gsb_utils.h b/openfpga/src/utils/device_rr_gsb_utils.h index 0b7424b4f..453e93d61 100644 --- a/openfpga/src/utils/device_rr_gsb_utils.h +++ b/openfpga/src/utils/device_rr_gsb_utils.h @@ -8,6 +8,7 @@ #include #include "device_rr_gsb.h" +#include "rr_graph_view.h" /******************************************************************** * Function declaration @@ -19,9 +20,11 @@ namespace openfpga { size_t find_device_rr_gsb_num_cb_modules(const DeviceRRGSB& device_rr_gsb, const t_rr_type& cb_type); -size_t find_device_rr_gsb_num_sb_modules(const DeviceRRGSB& device_rr_gsb); +size_t find_device_rr_gsb_num_sb_modules(const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph); -size_t find_device_rr_gsb_num_gsb_modules(const DeviceRRGSB& device_rr_gsb); +size_t find_device_rr_gsb_num_gsb_modules(const DeviceRRGSB& device_rr_gsb, + const RRGraphView& rr_graph); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/fabric_global_port_info_utils.cpp b/openfpga/src/utils/fabric_global_port_info_utils.cpp index 533df628f..aaba4b123 100644 --- a/openfpga/src/utils/fabric_global_port_info_utils.cpp +++ b/openfpga/src/utils/fabric_global_port_info_utils.cpp @@ -74,10 +74,16 @@ bool port_is_fabric_global_reset_port( const FabricGlobalPortInfo& fabric_global_port_info, const ModuleManager& module_manager, const BasicPort& port) { /* Find the top_module: the fabric global ports are always part of the ports - * of the top module */ + * of the top/core module. If there is a core module, we should consider core + * only */ ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + ModuleId core_module = + module_manager.find_module(generate_fpga_core_module_name()); + if (module_manager.valid_module_id(core_module)) { + top_module = core_module; + } for (const FabricGlobalPortId& fabric_global_port_id : fabric_global_port_info.global_ports()) { @@ -107,10 +113,16 @@ FabricGlobalPortId find_fabric_global_port( const FabricGlobalPortInfo& fabric_global_port_info, const ModuleManager& module_manager, const BasicPort& port) { /* Find the top_module: the fabric global ports are always part of the ports - * of the top module */ + * of the top/core module. If there is a core module, we should consider core + * only */ ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + ModuleId core_module = + module_manager.find_module(generate_fpga_core_module_name()); + if (module_manager.valid_module_id(core_module)) { + top_module = core_module; + } for (const FabricGlobalPortId& fabric_global_port_id : fabric_global_port_info.global_ports()) { diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index df144e669..0abf95b07 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -2,9 +2,9 @@ * This file includes functions that are used for * generating ports for memory modules *********************************************************************/ -/* Headers from vtrutil library */ #include "memory_utils.h" +#include "command_exit_codes.h" #include "decoder_library_utils.h" #include "openfpga_naming.h" #include "vtr_assert.h" @@ -342,6 +342,12 @@ std::vector generate_sram_port_names( std::vector model_port_types; switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: + /* Feed through wires are all inputs */ + model_port_types.push_back(CIRCUIT_MODEL_PORT_BL); /* Indicate mem port */ + model_port_types.push_back( + CIRCUIT_MODEL_PORT_BLB); /* Indicate mem_inv port */ + break; case CONFIG_MEM_SCAN_CHAIN: model_port_types.push_back(CIRCUIT_MODEL_PORT_INPUT); model_port_types.push_back(CIRCUIT_MODEL_PORT_OUTPUT); @@ -400,6 +406,7 @@ size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type, size_t sram_port_size = num_config_bits; switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: case CONFIG_MEM_STANDALONE: break; case CONFIG_MEM_SCAN_CHAIN: @@ -490,4 +497,55 @@ size_t estimate_num_configurable_children_to_skip_by_config_protocol( return num_child_to_skip; } +int rec_find_physical_memory_children( + const ModuleManager& module_manager, const ModuleId& curr_module, + std::vector& physical_memory_children, + std::vector& physical_memory_instance_names, + const bool& verbose) { + if (module_manager + .configurable_children(curr_module, + ModuleManager::e_config_child_type::LOGICAL) + .empty()) { + return CMD_EXEC_SUCCESS; + } + for (size_t ichild = 0; + ichild < module_manager + .configurable_children( + curr_module, ModuleManager::e_config_child_type::LOGICAL) + .size(); + ++ichild) { + ModuleId logical_child = module_manager.configurable_children( + curr_module, ModuleManager::e_config_child_type::LOGICAL)[ichild]; + if (module_manager + .configurable_children(logical_child, + ModuleManager::e_config_child_type::LOGICAL) + .empty()) { + /* This is a leaf node, get the physical memory module */ + physical_memory_children.push_back( + module_manager.logical2physical_configurable_children( + curr_module)[ichild]); + physical_memory_instance_names.push_back( + module_manager.logical2physical_configurable_child_instance_names( + curr_module)[ichild]); + VTR_LOGV( + verbose, + "Collecting physical memory module '%s' with an instance name " + "'%s'...\n", + module_manager + .module_name(module_manager.logical2physical_configurable_children( + curr_module)[ichild]) + .c_str(), + module_manager + .logical2physical_configurable_child_instance_names( + curr_module)[ichild] + .c_str()); + } else { + rec_find_physical_memory_children( + module_manager, logical_child, physical_memory_children, + physical_memory_instance_names, verbose); + } + } + return CMD_EXEC_SUCCESS; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/utils/memory_utils.h b/openfpga/src/utils/memory_utils.h index 59cf08953..184d0be74 100644 --- a/openfpga/src/utils/memory_utils.h +++ b/openfpga/src/utils/memory_utils.h @@ -4,6 +4,7 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ +#include #include #include "circuit_types.h" @@ -53,6 +54,18 @@ size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, size_t estimate_num_configurable_children_to_skip_by_config_protocol( const ConfigProtocol& config_protocol, size_t curr_region_num_config_child); +/** + * @brief Find the physical memory child modules with a given root module + * This function will walk through the module tree in a recursive way until + * reaching the leaf node (which require configurable memories) Return a list of + * modules + */ +int rec_find_physical_memory_children( + const ModuleManager& module_manager, const ModuleId& curr_module, + std::vector& physical_memory_children, + std::vector& physical_memory_instance_names, + const bool& verbose); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/utils/module_manager_memory_utils.cpp b/openfpga/src/utils/module_manager_memory_utils.cpp new file mode 100644 index 000000000..cf033e9ed --- /dev/null +++ b/openfpga/src/utils/module_manager_memory_utils.cpp @@ -0,0 +1,592 @@ +/****************************************************************************** + * This files includes most utilized functions + * for data structures for module management. + ******************************************************************************/ + +#include +#include +#include + +/* Headers from vtrutil library */ +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from openfpgautil library */ +#include "build_decoder_modules.h" +#include "circuit_library_utils.h" +#include "decoder_library_utils.h" +#include "memory_utils.h" +#include "module_manager_memory_utils.h" +#include "module_manager_utils.h" +#include "openfpga_naming.h" +#include "openfpga_port.h" +#include "openfpga_reserved_words.h" +#include "pb_type_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Compare the configurable children list with a given list of fabric sub-keys + * Return true if exact naming-matches are found + * When searching for matching, we consider + * - alias is treated as No. 1 reference + * - the pair as No. 2 reference + *******************************************************************/ +static bool submodule_memory_modules_match_fabric_key( + ModuleManager& module_manager, const ModuleId& module_id, + const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id) { + /* If the length does not match, conclusion is easy to be made */ + size_t len_module_memory = + module_manager + .configurable_children(module_id, + ModuleManager::e_config_child_type::PHYSICAL) + .size(); + size_t len_fabric_sub_key = fabric_key.sub_keys(key_module_id).size(); + if (len_module_memory != len_fabric_sub_key) { + return false; + } + /* Now walk through the child one by one */ + for (size_t ikey = 0; ikey < len_module_memory; ++ikey) { + FabricSubKeyId key_id = fabric_key.sub_keys(key_module_id)[ikey]; + std::pair inst_info(ModuleId::INVALID(), 0); + /* Try to match the alias */ + if (!fabric_key.sub_key_alias(key_id).empty()) { + if (!fabric_key.sub_key_name(key_id).empty()) { + inst_info.first = + module_manager.find_module(fabric_key.sub_key_name(key_id)); + inst_info.second = module_manager.instance_id( + module_id, inst_info.first, fabric_key.sub_key_alias(key_id)); + } else { + inst_info = find_module_manager_instance_module_info( + module_manager, module_id, fabric_key.sub_key_alias(key_id)); + } + } else { + inst_info.first = + module_manager.find_module(fabric_key.sub_key_name(key_id)); + inst_info.second = fabric_key.sub_key_value(key_id); + } + if (inst_info.first != + module_manager.configurable_children( + module_id, ModuleManager::e_config_child_type::PHYSICAL)[ikey] || + inst_info.second != + module_manager.configurable_child_instances( + module_id, ModuleManager::e_config_child_type::PHYSICAL)[ikey]) { + return false; + } + } + return true; +} + +/******************************************************************** + * Update the configurable children list based on fabric key definitions + *******************************************************************/ +static bool update_submodule_memory_modules_from_fabric_key( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const ModuleManager::e_config_child_type& config_child_type, + const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id) { + /* Reset the configurable children */ + module_manager.clear_configurable_children(module_id); + + for (FabricSubKeyId key_id : fabric_key.sub_keys(key_module_id)) { + std::pair inst_info(ModuleId::INVALID(), 0); + /* Try to match the alias */ + if (!fabric_key.sub_key_alias(key_id).empty()) { + if (!fabric_key.sub_key_name(key_id).empty()) { + inst_info.first = + module_manager.find_module(fabric_key.sub_key_name(key_id)); + inst_info.second = module_manager.instance_id( + module_id, inst_info.first, fabric_key.sub_key_alias(key_id)); + } else { + inst_info = find_module_manager_instance_module_info( + module_manager, module_id, fabric_key.sub_key_alias(key_id)); + } + } else { + inst_info.first = + module_manager.find_module(fabric_key.sub_key_name(key_id)); + inst_info.second = fabric_key.sub_key_value(key_id); + } + if (false == module_manager.valid_module_id(inst_info.first)) { + if (!fabric_key.sub_key_alias(key_id).empty()) { + VTR_LOG_ERROR("Invalid key alias '%s'!\n", + fabric_key.sub_key_alias(key_id).c_str()); + } else { + VTR_LOG_ERROR("Invalid key name '%s'!\n", + fabric_key.sub_key_name(key_id).c_str()); + } + return CMD_EXEC_FATAL_ERROR; + } + + if (false == module_manager.valid_module_instance_id( + module_id, inst_info.first, inst_info.second)) { + if (!fabric_key.sub_key_alias(key_id).empty()) { + VTR_LOG_ERROR("Invalid key alias '%s'!\n", + fabric_key.sub_key_alias(key_id).c_str()); + } else { + VTR_LOG_ERROR("Invalid key value '%ld'!\n", inst_info.second); + } + return CMD_EXEC_FATAL_ERROR; + } + + /* If the the child has not configuration bits, error out */ + if (0 == find_module_num_config_bits( + module_manager, inst_info.first, circuit_lib, + config_protocol.memory_model(), config_protocol.type())) { + if (!fabric_key.sub_key_alias(key_id).empty()) { + VTR_LOG_ERROR( + "Invalid key alias '%s' which has zero configuration bits!\n", + fabric_key.sub_key_alias(key_id).c_str()); + } else { + VTR_LOG_ERROR( + "Invalid key name '%s' which has zero configuration bits!\n", + fabric_key.sub_key_name(key_id).c_str()); + } + return CMD_EXEC_FATAL_ERROR; + } + + /* Now we can add the child to configurable children of the top module */ + module_manager.add_configurable_child(module_id, inst_info.first, + inst_info.second, config_child_type, + vtr::Point()); + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Remove the nets around the configuration chain (ccff_head and ccff_tails) + *******************************************************************/ +static int remove_submodule_nets_cmos_memory_chain_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { + for (size_t mem_index = 0; + mem_index < + module_manager.configurable_children(parent_module, config_child_type) + .size(); + ++mem_index) { + ModuleId net_src_module_id; + size_t net_src_instance_id; + ModulePortId net_src_port_id; + + if (0 == mem_index) { + /* Find the port name of configuration chain head */ + std::string src_port_name = + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_INPUT); + net_src_module_id = parent_module; + net_src_instance_id = 0; + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); + } else { + /* Find the port name of previous memory module */ + std::string src_port_name = generate_configuration_chain_tail_name(); + net_src_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index - 1]; + net_src_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index - 1]; + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); + } + + /* Get the pin id for source port */ + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { + /* Find the net from which the source node is driving */ + ModuleNetId net = module_manager.module_instance_port_net( + parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, + net_src_port.pins()[pin_id]); + /* Remove the net including sources and sinks */ + module_manager.clear_module_net_sinks(parent_module, net); + } + } + + /* For the last memory module: + * net source is the configuration chain tail of the previous memory module + * net sink is the configuration chain tail of the primitive module + */ + /* Find the port name of previous memory module */ + std::string src_port_name = generate_configuration_chain_tail_name(); + ModuleId net_src_module_id = + module_manager.configurable_children(parent_module, config_child_type) + .back(); + size_t net_src_instance_id = + module_manager + .configurable_child_instances(parent_module, config_child_type) + .back(); + ModulePortId net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); + + /* Get the pin id for source port */ + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { + /* Find the net from which the source node is driving */ + ModuleNetId net = module_manager.module_instance_port_net( + parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, + net_src_port.pins()[pin_id]); + /* Remove the net including sources and sinks */ + module_manager.clear_module_net_sinks(parent_module, net); + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Remove the nets around the configurable children for a given module which + *should be in CMOS type + *******************************************************************/ +static int remove_submodule_nets_cmos_memory_config_bus( + ModuleManager& module_manager, const ModuleId& module_id, + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { + switch (sram_orgz_type) { + case CONFIG_MEM_SCAN_CHAIN: { + return remove_submodule_nets_cmos_memory_chain_config_bus( + module_manager, module_id, sram_orgz_type, config_child_type); + break; + } + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + /* TODO: + add_module_nets_cmos_memory_bank_bl_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_memory_bank_wl_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + add_module_nets_cmos_memory_bank_wl_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); + */ + break; + case CONFIG_MEM_MEMORY_BANK: + /* TODO: + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + */ + break; + case CONFIG_MEM_FRAME_BASED: + /* TODO: + add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, + parent_module); + */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + return CMD_EXEC_FATAL_ERROR; + } + return CMD_EXEC_FATAL_ERROR; +} + +/******************************************************************** + * Remove the nets around the configurable children for a given module + *******************************************************************/ +static int remove_submodule_configurable_children_nets( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const ModuleManager::e_config_child_type& config_child_type) { + switch (circuit_lib.design_tech_type(config_protocol.memory_model())) { + case CIRCUIT_MODEL_DESIGN_CMOS: + return remove_submodule_nets_cmos_memory_config_bus( + module_manager, module_id, config_protocol.type(), config_child_type); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of memory design technology!\n"); + return CMD_EXEC_FATAL_ERROR; + } + return CMD_EXEC_FATAL_ERROR; +} + +/******************************************************************** + * Rebuild the nets(only sinks) around the configuration chain (ccff_head and + *ccff_tails) + *******************************************************************/ +static int rebuild_submodule_nets_cmos_memory_chain_config_bus( + ModuleManager& module_manager, const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { + for (size_t mem_index = 0; + mem_index < + module_manager.configurable_children(parent_module, config_child_type) + .size(); + ++mem_index) { + ModuleId net_src_module_id; + size_t net_src_instance_id; + ModulePortId net_src_port_id; + + ModuleId net_sink_module_id; + size_t net_sink_instance_id; + ModulePortId net_sink_port_id; + + if (0 == mem_index) { + /* Find the port name of configuration chain head */ + std::string src_port_name = + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_INPUT); + net_src_module_id = parent_module; + net_src_instance_id = 0; + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); + + /* Find the port name of next memory module */ + std::string sink_port_name = generate_configuration_chain_head_name(); + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); + } else { + /* Find the port name of previous memory module */ + std::string src_port_name = generate_configuration_chain_tail_name(); + net_src_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index - 1]; + net_src_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index - 1]; + net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); + + /* Find the port name of next memory module */ + std::string sink_port_name = generate_configuration_chain_head_name(); + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; + net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); + } + + /* Get the pin id for source port */ + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); + /* Get the pin id for sink port */ + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); + /* Port sizes of source and sink should match */ + VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { + /* Create a net and add source and sink to it */ + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[pin_id]); + /* Add net sink */ + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); + } + } + + /* For the last memory module: + * net source is the configuration chain tail of the previous memory module + * net sink is the configuration chain tail of the primitive module + */ + /* Find the port name of previous memory module */ + std::string src_port_name = generate_configuration_chain_tail_name(); + ModuleId net_src_module_id = + module_manager.configurable_children(parent_module, config_child_type) + .back(); + size_t net_src_instance_id = + module_manager + .configurable_child_instances(parent_module, config_child_type) + .back(); + ModulePortId net_src_port_id = + module_manager.find_module_port(net_src_module_id, src_port_name); + + /* Find the port name of next memory module */ + std::string sink_port_name = + generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_OUTPUT); + ModuleId net_sink_module_id = parent_module; + size_t net_sink_instance_id = 0; + ModulePortId net_sink_port_id = + module_manager.find_module_port(net_sink_module_id, sink_port_name); + + /* Get the pin id for source port */ + BasicPort net_src_port = + module_manager.module_port(net_src_module_id, net_src_port_id); + /* Get the pin id for sink port */ + BasicPort net_sink_port = + module_manager.module_port(net_sink_module_id, net_sink_port_id); + /* Port sizes of source and sink should match */ + VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { + /* Create a net and add source and sink to it */ + ModuleNetId net = create_module_source_pin_net( + module_manager, parent_module, net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[pin_id]); + /* Add net sink */ + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, + net_sink_instance_id, net_sink_port_id, + net_sink_port.pins()[pin_id]); + } + return CMD_EXEC_SUCCESS; +} + +/******************************************************************** + * Rebuild the nets around the configurable children for a given module which + *should be in CMOS type + *******************************************************************/ +static int rebuild_submodule_nets_cmos_memory_config_bus( + ModuleManager& module_manager, const ModuleId& module_id, + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { + switch (sram_orgz_type) { + case CONFIG_MEM_SCAN_CHAIN: { + return rebuild_submodule_nets_cmos_memory_chain_config_bus( + module_manager, module_id, sram_orgz_type, config_child_type); + break; + } + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + /* TODO: + add_module_nets_cmos_memory_bank_bl_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_memory_bank_wl_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + add_module_nets_cmos_memory_bank_wl_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); + */ + break; + case CONFIG_MEM_MEMORY_BANK: + /* TODO: + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + */ + break; + case CONFIG_MEM_FRAME_BASED: + /* TODO: + add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, + parent_module); + */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + return CMD_EXEC_FATAL_ERROR; + } + return CMD_EXEC_FATAL_ERROR; +} + +/******************************************************************** + * Rebuild the nets(only sinks) around the configurable children for a given + *module + *******************************************************************/ +static int rebuild_submodule_configurable_children_nets( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const ModuleManager::e_config_child_type& config_child_type) { + switch (circuit_lib.design_tech_type(config_protocol.memory_model())) { + case CIRCUIT_MODEL_DESIGN_CMOS: + return rebuild_submodule_nets_cmos_memory_config_bus( + module_manager, module_id, config_protocol.type(), config_child_type); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of memory design technology!\n"); + return CMD_EXEC_FATAL_ERROR; + } + return CMD_EXEC_FATAL_ERROR; +} + +/******************************************************************** + * Load and update the configurable children of a given module (not a top-level + *module) Compare the configurable children list with fabric sub-keys. + * - If match, nothing should be done + * - If not match, + * - remove the nets related to configurable children + * - rebuild the configurable children list + * - add the nets related to configurable children + *******************************************************************/ +static int load_and_update_submodule_memory_modules_from_fabric_key( + ModuleManager& module_manager, const ModuleId& module_id, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const FabricKey& fabric_key, const FabricKeyModuleId& key_module_id, + const bool& group_config_block) { + int status = CMD_EXEC_SUCCESS; + /* Compare the configurable children list */ + if (submodule_memory_modules_match_fabric_key(module_manager, module_id, + fabric_key, key_module_id)) { + return CMD_EXEC_SUCCESS; + } + /* Do not match, now remove all the nets for the configurable children */ + status = remove_submodule_configurable_children_nets( + module_manager, module_id, circuit_lib, config_protocol, + ModuleManager::e_config_child_type::PHYSICAL); + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } + /* Overwrite the configurable children list */ + status = update_submodule_memory_modules_from_fabric_key( + module_manager, module_id, circuit_lib, config_protocol, + group_config_block ? ModuleManager::e_config_child_type::PHYSICAL + : ModuleManager::e_config_child_type::UNIFIED, + fabric_key, key_module_id); + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } + /* TODO: Create the nets for the new list of configurable children */ + status = rebuild_submodule_configurable_children_nets( + module_manager, module_id, circuit_lib, config_protocol, + ModuleManager::e_config_child_type::PHYSICAL); + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } + return status; +} + +/******************************************************************** + * Load and update the configurable children of a given list of modules (not a + *top-level module) + *******************************************************************/ +int load_submodules_memory_modules_from_fabric_key( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol, const FabricKey& fabric_key, + const bool& group_config_block) { + int status = CMD_EXEC_SUCCESS; + for (FabricKeyModuleId key_module_id : fabric_key.modules()) { + std::string module_name = fabric_key.module_name(key_module_id); + /* Ensure this is not a top module! */ + if (module_name == std::string(FPGA_TOP_MODULE_NAME)) { + VTR_LOG_ERROR( + "Expect a non-top-level name for the sub-module '%s' in fabric key!\n", + module_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + ModuleId module_id = module_manager.find_module(module_name); + if (module_id) { + /* This is a valid module, try to load and update */ + status = load_and_update_submodule_memory_modules_from_fabric_key( + module_manager, module_id, circuit_lib, config_protocol, fabric_key, + key_module_id, group_config_block); + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } + } else { + /* Not a valid module, report error */ + VTR_LOG_ERROR( + "The sub-module '%s' in fabric key is not a valid module in FPGA " + "fabric!\n", + module_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + } + return status; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/utils/module_manager_memory_utils.h b/openfpga/src/utils/module_manager_memory_utils.h new file mode 100644 index 000000000..5f7a75b8e --- /dev/null +++ b/openfpga/src/utils/module_manager_memory_utils.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * This files includes declarations for most utilized functions + * for data structures for module management. + ******************************************************************************/ +#ifndef MODULE_MANAGER_MEMORY_UTILS_H +#define MODULE_MANAGER_MEMORY_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include + +/* Headers from readarch library */ +#include "physical_types.h" + +/* Headers from openfpgautil library */ +#include "openfpga_port.h" + +/* Headers from readarchopenfpga library */ +#include "circuit_library.h" +#include "circuit_types.h" +#include "config_protocol.h" +#include "decoder_library.h" +#include "fabric_key.h" +#include "module_manager.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +int load_submodules_memory_modules_from_fabric_key( + ModuleManager& module_manager, const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol, const FabricKey& fabric_key, + const bool& group_config_block); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 90dbc2b41..70a62d148 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -8,6 +8,7 @@ #include /* Headers from vtrutil library */ +#include "command_exit_codes.h" #include "vtr_assert.h" #include "vtr_log.h" @@ -85,11 +86,14 @@ void reserve_module_manager_module_nets(ModuleManager& module_manager, *children as well ******************************************************************************/ size_t count_module_manager_module_configurable_children( - const ModuleManager& module_manager, const ModuleId& module) { + const ModuleManager& module_manager, const ModuleId& module, + const ModuleManager::e_config_child_type& config_child_type) { size_t num_config_children = 0; - for (const ModuleId& child : module_manager.configurable_children(module)) { - if (0 != module_manager.configurable_children(child).size()) { + for (const ModuleId& child : + module_manager.configurable_children(module, config_child_type)) { + if (0 != + module_manager.configurable_children(child, config_child_type).size()) { num_config_children++; } } @@ -341,6 +345,7 @@ void add_sram_ports_to_module_manager( /* Add ports to the module manager */ switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: case CONFIG_MEM_STANDALONE: case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { @@ -1016,7 +1021,8 @@ void add_module_nets_between_logic_and_memory_sram_bus( void add_module_nets_cmos_flatten_memory_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type) { + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type) { /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; @@ -1038,7 +1044,8 @@ void add_module_nets_cmos_flatten_memory_config_bus( module_manager.module_port(net_src_module_id, net_src_port_id); for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < module_manager.num_configurable_children(parent_module, + config_child_type); ++mem_index) { ModuleId net_sink_module_id; size_t net_sink_instance_id; @@ -1047,10 +1054,10 @@ void add_module_nets_cmos_flatten_memory_config_bus( /* Find the port name of next memory module */ std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); @@ -1104,7 +1111,8 @@ void add_module_nets_cmos_flatten_memory_config_bus( void add_module_nets_cmos_memory_bank_bl_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type) { + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type) { /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; @@ -1121,15 +1129,17 @@ void add_module_nets_cmos_memory_bank_bl_config_bus( module_manager.module_port(net_src_module_id, net_src_port_id); for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager.configurable_children(parent_module, config_child_type) + .size(); ++mem_index) { /* Find the port name of next memory module */ std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - ModuleId net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - size_t net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + ModuleId net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + size_t net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); @@ -1187,7 +1197,8 @@ void add_module_nets_cmos_memory_bank_bl_config_bus( void add_module_nets_cmos_memory_bank_wl_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type) { + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type) { /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; @@ -1216,15 +1227,17 @@ void add_module_nets_cmos_memory_bank_wl_config_bus( module_manager.module_port(net_src_module_id, net_bl_port_id); for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < + module_manager.configurable_children(parent_module, config_child_type) + .size(); ++mem_index) { /* Find the port name of next memory module */ std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - ModuleId net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - size_t net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + ModuleId net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + size_t net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); @@ -1271,9 +1284,11 @@ void add_module_nets_cmos_memory_bank_wl_config_bus( *********************************************************************/ void add_module_nets_cmos_memory_chain_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type) { + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { for (size_t mem_index = 0; - mem_index < module_manager.configurable_children(parent_module).size(); + mem_index < module_manager.num_configurable_children(parent_module, + config_child_type); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -1294,28 +1309,28 @@ void add_module_nets_cmos_memory_chain_config_bus( /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } else { /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); - net_src_module_id = - module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index - 1]; net_src_instance_id = module_manager.configurable_child_instances( - parent_module)[mem_index - 1]; + parent_module, config_child_type)[mem_index - 1]; net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Find the port name of next memory module */ std::string sink_port_name = generate_configuration_chain_head_name(); - net_sink_module_id = - module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = - module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_module_id = module_manager.configurable_children( + parent_module, config_child_type)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); } @@ -1349,9 +1364,12 @@ void add_module_nets_cmos_memory_chain_config_bus( /* Find the port name of previous memory module */ std::string src_port_name = generate_configuration_chain_tail_name(); ModuleId net_src_module_id = - module_manager.configurable_children(parent_module).back(); + module_manager.configurable_children(parent_module, config_child_type) + .back(); size_t net_src_instance_id = - module_manager.configurable_child_instances(parent_module).back(); + module_manager + .configurable_child_instances(parent_module, config_child_type) + .back(); ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); @@ -1405,9 +1423,10 @@ void add_module_nets_cmos_memory_chain_config_bus( * *********************************************************************/ static void add_module_nets_cmos_memory_frame_short_config_bus( - ModuleManager& module_manager, const ModuleId& parent_module) { + ModuleManager& module_manager, const ModuleId& parent_module, + const ModuleManager::e_config_child_type& config_child_type) { std::vector configurable_children = - module_manager.configurable_children(parent_module); + module_manager.configurable_children(parent_module, config_child_type); VTR_ASSERT(1 == configurable_children.size()); ModuleId child_module = configurable_children[0]; @@ -1489,9 +1508,10 @@ static void add_module_nets_cmos_memory_frame_short_config_bus( *********************************************************************/ static void add_module_nets_cmos_memory_frame_decoder_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module) { + const ModuleId& parent_module, + const ModuleManager::e_config_child_type& config_child_type) { std::vector configurable_children = - module_manager.configurable_children(parent_module); + module_manager.configurable_children(parent_module, config_child_type); /* Find the decoder specification */ size_t addr_size = @@ -1569,8 +1589,8 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId child_addr_port = module_manager.find_module_port( child_module, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort child_addr_port_info = @@ -1601,8 +1621,8 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId child_din_port = module_manager.find_module_port( child_module, std::string(DECODER_DATA_IN_PORT_NAME)); add_module_bus_nets(module_manager, parent_module, parent_module, 0, @@ -1622,8 +1642,8 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( for (size_t mem_index = 0; mem_index < configurable_children.size(); ++mem_index) { ModuleId child_module = configurable_children[mem_index]; - size_t child_instance = - module_manager.configurable_child_instances(parent_module)[mem_index]; + size_t child_instance = module_manager.configurable_child_instances( + parent_module, config_child_type)[mem_index]; ModulePortId child_en_port = module_manager.find_module_port( child_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort child_en_port_info = @@ -1647,7 +1667,9 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( } /* Add the decoder as the last configurable children */ - module_manager.add_configurable_child(parent_module, decoder_module, 0); + module_manager.add_configurable_child( + parent_module, decoder_module, 0, + ModuleManager::e_config_child_type::UNIFIED); } /********************************************************************* @@ -1661,18 +1683,22 @@ static void add_module_nets_cmos_memory_frame_decoder_config_bus( **********************************************************************/ void add_module_nets_cmos_memory_frame_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module) { - if (0 == module_manager.configurable_children(parent_module).size()) { + const ModuleId& parent_module, + const ModuleManager::e_config_child_type& config_child_type) { + if (0 == module_manager.num_configurable_children(parent_module, + config_child_type)) { return; } - if (1 == module_manager.configurable_children(parent_module).size()) { - add_module_nets_cmos_memory_frame_short_config_bus(module_manager, - parent_module); + if (1 == module_manager.num_configurable_children(parent_module, + config_child_type)) { + add_module_nets_cmos_memory_frame_short_config_bus( + module_manager, parent_module, config_child_type); } else { - VTR_ASSERT(1 < module_manager.configurable_children(parent_module).size()); + VTR_ASSERT(1 < module_manager.num_configurable_children(parent_module, + config_child_type)); add_module_nets_cmos_memory_frame_decoder_config_bus( - module_manager, decoder_lib, parent_module); + module_manager, decoder_lib, parent_module, config_child_type); } } @@ -1722,26 +1748,38 @@ void add_module_nets_cmos_memory_frame_config_bus( **********************************************************************/ static void add_module_nets_cmos_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type) { + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { switch (sram_orgz_type) { case CONFIG_MEM_SCAN_CHAIN: { add_module_nets_cmos_memory_chain_config_bus( - module_manager, parent_module, sram_orgz_type); + module_manager, parent_module, sram_orgz_type, config_child_type); break; } + case CONFIG_MEM_FEEDTHROUGH: + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL, + config_child_type); + add_module_nets_cmos_flatten_memory_config_bus( + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BLB, + config_child_type); + break; case CONFIG_MEM_STANDALONE: case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL, + config_child_type); add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL, + config_child_type); add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR, + config_child_type); break; case CONFIG_MEM_FRAME_BASED: - add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, - parent_module); + add_module_nets_cmos_memory_frame_config_bus( + module_manager, decoder_lib, parent_module, config_child_type); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -1787,31 +1825,37 @@ static void add_module_nets_cmos_memory_config_bus( **********************************************************************/ static void add_pb_module_nets_cmos_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type) { + const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { switch (sram_orgz_type) { case CONFIG_MEM_SCAN_CHAIN: { add_module_nets_cmos_memory_chain_config_bus( - module_manager, parent_module, sram_orgz_type); + module_manager, parent_module, sram_orgz_type, config_child_type); break; } case CONFIG_MEM_STANDALONE: case CONFIG_MEM_QL_MEMORY_BANK: add_module_nets_cmos_memory_bank_bl_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL, + config_child_type); add_module_nets_cmos_memory_bank_wl_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL, + config_child_type); add_module_nets_cmos_memory_bank_wl_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WLR, + config_child_type); break; case CONFIG_MEM_MEMORY_BANK: add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL, + config_child_type); add_module_nets_cmos_flatten_memory_config_bus( - module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL, + config_child_type); break; case CONFIG_MEM_FRAME_BASED: - add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, - parent_module); + add_module_nets_cmos_memory_frame_config_bus( + module_manager, decoder_lib, parent_module, config_child_type); break; default: VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -1877,11 +1921,13 @@ static void add_pb_module_nets_cmos_memory_config_bus( void add_module_nets_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech) { + const e_circuit_model_design_tech& mem_tech, + const ModuleManager::e_config_child_type& config_child_type) { switch (mem_tech) { case CIRCUIT_MODEL_DESIGN_CMOS: add_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, - parent_module, sram_orgz_type); + parent_module, sram_orgz_type, + config_child_type); break; case CIRCUIT_MODEL_DESIGN_RRAM: /* TODO: */ @@ -1908,11 +1954,13 @@ void add_module_nets_memory_config_bus( void add_pb_module_nets_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech) { + const e_circuit_model_design_tech& mem_tech, + const ModuleManager::e_config_child_type& config_child_type) { switch (mem_tech) { case CIRCUIT_MODEL_DESIGN_CMOS: add_pb_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, - parent_module, sram_orgz_type); + parent_module, sram_orgz_type, + config_child_type); break; case CIRCUIT_MODEL_DESIGN_RRAM: /* TODO: */ @@ -2363,10 +2411,12 @@ size_t find_module_num_shared_config_bits_from_child_modules( size_t find_module_num_config_bits_from_child_modules( ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type) { + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type) { size_t num_config_bits = 0; switch (sram_orgz_type) { + case CONFIG_MEM_FEEDTHROUGH: case CONFIG_MEM_STANDALONE: case CONFIG_MEM_SCAN_CHAIN: case CONFIG_MEM_QL_MEMORY_BANK: @@ -2376,7 +2426,7 @@ size_t find_module_num_config_bits_from_child_modules( * per configurable children */ for (const ModuleId& child : - module_manager.configurable_children(module_id)) { + module_manager.configurable_children(module_id, config_child_type)) { num_config_bits += find_module_num_config_bits( module_manager, child, circuit_lib, sram_model, sram_orgz_type); } @@ -2389,7 +2439,7 @@ size_t find_module_num_config_bits_from_child_modules( * - and the number of configurable children */ for (const ModuleId& child : - module_manager.configurable_children(module_id)) { + module_manager.configurable_children(module_id, config_child_type)) { size_t temp_num_config_bits = find_module_num_config_bits( module_manager, child, circuit_lib, sram_model, sram_orgz_type); num_config_bits = @@ -2399,9 +2449,11 @@ size_t find_module_num_config_bits_from_child_modules( /* If there are more than 2 configurable children, we need a decoder * Otherwise, we can just short wire the address port to the children */ - if (1 < module_manager.configurable_children(module_id).size()) { + if (1 < module_manager.num_configurable_children(module_id, + config_child_type)) { num_config_bits += find_mux_local_decoder_addr_size( - module_manager.configurable_children(module_id).size()); + module_manager.num_configurable_children(module_id, + config_child_type)); } break; diff --git a/openfpga/src/utils/module_manager_utils.h b/openfpga/src/utils/module_manager_utils.h index bd4e43130..f55f73402 100644 --- a/openfpga/src/utils/module_manager_utils.h +++ b/openfpga/src/utils/module_manager_utils.h @@ -20,7 +20,9 @@ /* Headers from readarchopenfpga library */ #include "circuit_library.h" #include "circuit_types.h" +#include "config_protocol.h" #include "decoder_library.h" +#include "fabric_key.h" #include "module_manager.h" #include "vpr_device_annotation.h" @@ -40,7 +42,8 @@ void reserve_module_manager_module_nets(ModuleManager& module_manager, const ModuleId& module); size_t count_module_manager_module_configurable_children( - const ModuleManager& module_manager, const ModuleId& module); + const ModuleManager& module_manager, const ModuleId& module, + const ModuleManager::e_config_child_type& config_child_type); std::pair find_module_manager_instance_module_info( const ModuleManager& module_manager, const ModuleId& parent, @@ -108,35 +111,42 @@ void add_module_nets_between_logic_and_memory_sram_bus( void add_module_nets_cmos_flatten_memory_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type); + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_cmos_memory_bank_bl_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type); + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_cmos_memory_bank_wl_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& config_port_type); + const e_circuit_model_port_type& config_port_type, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_cmos_memory_chain_config_bus( ModuleManager& module_manager, const ModuleId& parent_module, - const e_config_protocol_type& sram_orgz_type); + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_cmos_memory_frame_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, - const ModuleId& parent_module); + const ModuleId& parent_module, + const ModuleManager::e_config_child_type& config_child_type); void add_module_nets_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech); + const e_circuit_model_design_tech& mem_tech, + const ModuleManager::e_config_child_type& config_child_type); void add_pb_module_nets_memory_config_bus( ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_design_tech& mem_tech); + const e_circuit_model_design_tech& mem_tech, + const ModuleManager::e_config_child_type& config_child_type); size_t find_module_num_shared_config_bits(const ModuleManager& module_manager, const ModuleId& module_id); @@ -168,7 +178,8 @@ size_t find_module_num_shared_config_bits_from_child_modules( size_t find_module_num_config_bits_from_child_modules( ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type); + const e_config_protocol_type& sram_orgz_type, + const ModuleManager::e_config_child_type& config_child_type); ModuleNetId create_module_source_pin_net(ModuleManager& module_manager, const ModuleId& cur_module_id, diff --git a/openfpga/src/utils/openfpga_device_grid_utils.cpp b/openfpga/src/utils/openfpga_device_grid_utils.cpp index 5a234b60d..01437f48f 100644 --- a/openfpga/src/utils/openfpga_device_grid_utils.cpp +++ b/openfpga/src/utils/openfpga_device_grid_utils.cpp @@ -61,4 +61,63 @@ generate_perimeter_grid_coordinates(const DeviceGrid& grids) { return io_coordinates; } +/******************************************************************** + * Create a list of the coordinates for the tiles on the device perimeter + * It follows a clockwise sequence when including the coordinates. + * Note that different from the function for grids, this function include corner + *tiles! Detailed sequence is as follows: + * - Top-left + * - TOP side, from left most to the right + * - Top-right + * - Right side, from top to the bottom + * - Bottom-right + * - Bottom side, from right to the left + * - Bottom-left + * - Left side, from bottom to top + * + * Note: + * - This function offers a standard sequence to walk through the + * grids on the perimeter of an FPGA device + * When sequence matters, this function should be used to ensure + * consistency between functions. + *******************************************************************/ +std::map>> +generate_perimeter_tile_coordinates(const DeviceGrid& grids) { + /* Search the border side */ + /* Create the coordinate range for each side of FPGA fabric */ + std::vector fpga_sides{TOP, RIGHT, BOTTOM, LEFT}; + std::map>> io_coordinates; + + /* Top-left */ + io_coordinates[TOP].push_back(vtr::Point(0, grids.height() - 1)); + /* TOP side*/ + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + io_coordinates[TOP].push_back(vtr::Point(ix, grids.height() - 1)); + } + + /* Top-Right */ + io_coordinates[RIGHT].push_back( + vtr::Point(grids.width() - 1, grids.height() - 1)); + /* RIGHT side */ + for (size_t iy = grids.height() - 2; iy > 0; --iy) { + io_coordinates[RIGHT].push_back(vtr::Point(grids.width() - 1, iy)); + } + + /* Bottom-right */ + io_coordinates[BOTTOM].push_back(vtr::Point(grids.width() - 1, 0)); + /* BOTTOM side*/ + for (size_t ix = grids.width() - 2; ix > 0; --ix) { + io_coordinates[BOTTOM].push_back(vtr::Point(ix, 0)); + } + + /* Bottom-left */ + io_coordinates[BOTTOM].push_back(vtr::Point(0, 0)); + /* LEFT side */ + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + io_coordinates[LEFT].push_back(vtr::Point(0, iy)); + } + + return io_coordinates; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/utils/openfpga_device_grid_utils.h b/openfpga/src/utils/openfpga_device_grid_utils.h index 4b49be150..6489e3be4 100644 --- a/openfpga/src/utils/openfpga_device_grid_utils.h +++ b/openfpga/src/utils/openfpga_device_grid_utils.h @@ -24,6 +24,9 @@ constexpr std::array FPGA_SIDES_CLOCKWISE{TOP, RIGHT, BOTTOM, LEFT}; std::map>> generate_perimeter_grid_coordinates(const DeviceGrid& grids); +std::map>> +generate_perimeter_tile_coordinates(const DeviceGrid& grids); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.cpp b/openfpga/src/utils/openfpga_physical_tile_utils.cpp index c4272ab09..1f539ffcf 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.cpp +++ b/openfpga/src/utils/openfpga_physical_tile_utils.cpp @@ -89,7 +89,8 @@ std::set find_physical_io_tile_located_sides( for (size_t ix = 1; ix < grids.width() - 1; ++ix) { for (size_t iy = 1; iy < grids.height() - 1; ++iy) { /* If located in center, we add a NUM_SIDES and finish */ - if (physical_tile == grids[ix][iy].type) { + if (physical_tile == + grids.get_physical_type(t_physical_tile_loc(ix, iy, 0))) { io_sides.insert(NUM_SIDES); center_io = true; break; @@ -108,7 +109,8 @@ std::set find_physical_io_tile_located_sides( for (const e_side& fpga_side : FPGA_SIDES_CLOCKWISE) { for (const vtr::Point& io_coordinate : io_coordinates[fpga_side]) { /* If located in center, we add a NUM_SIDES and finish */ - if (physical_tile == grids[io_coordinate.x()][io_coordinate.y()].type) { + if (physical_tile == grids.get_physical_type(t_physical_tile_loc( + io_coordinate.x(), io_coordinate.y(), 0))) { io_sides.insert(fpga_side); break; } diff --git a/openfpga/src/vpr_wrapper/vpr_main.cpp b/openfpga/src/vpr_wrapper/vpr_main.cpp index e9b5d563a..940fc0644 100644 --- a/openfpga/src/vpr_wrapper/vpr_main.cpp +++ b/openfpga/src/vpr_wrapper/vpr_main.cpp @@ -118,20 +118,15 @@ static int vpr_standalone(int argc, char** argv) { /* Read options, architecture, and circuit netlist */ vpr_init(argc, const_cast(argv), &Options, &vpr_setup, &Arch); - const Netlist<>& net_list = - vpr_setup.RouterOpts.flat_routing - ? (const Netlist<>&)g_vpr_ctx.atom().nlist - : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; - if (Options.show_version) { - vpr_free_all(net_list, Arch, vpr_setup); + vpr_free_all(Arch, vpr_setup); return SUCCESS_EXIT_CODE; } bool flow_succeeded = vpr_flow(vpr_setup, Arch); if (!flow_succeeded) { VTR_LOG("VPR failed to implement circuit\n"); - vpr_free_all(net_list, Arch, vpr_setup); + vpr_free_all(Arch, vpr_setup); return UNIMPLEMENTABLE_EXIT_CODE; } @@ -139,43 +134,30 @@ static int vpr_standalone(int argc, char** argv) { print_timing_stats("Flow", timing_ctx.stats); /* free data structures */ - vpr_free_all(net_list, Arch, vpr_setup); + vpr_free_all(Arch, vpr_setup); VTR_LOG("VPR succeeded\n"); } catch (const tatum::Error& tatum_error) { VTR_LOG_ERROR("%s\n", format_tatum_error(tatum_error).c_str()); - const Netlist<>& net_list = - vpr_setup.RouterOpts.flat_routing - ? (const Netlist<>&)g_vpr_ctx.atom().nlist - : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; - vpr_free_all(net_list, Arch, vpr_setup); + vpr_free_all(Arch, vpr_setup); return ERROR_EXIT_CODE; } catch (const VprError& vpr_error) { vpr_print_error(vpr_error); - const Netlist<>& net_list = - vpr_setup.RouterOpts.flat_routing - ? (const Netlist<>&)g_vpr_ctx.atom().nlist - : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; - if (vpr_error.type() == VPR_ERROR_INTERRUPTED) { - vpr_free_all(net_list, Arch, vpr_setup); + vpr_free_all(Arch, vpr_setup); return INTERRUPTED_EXIT_CODE; } else { - vpr_free_all(net_list, Arch, vpr_setup); + vpr_free_all(Arch, vpr_setup); return ERROR_EXIT_CODE; } } catch (const vtr::VtrError& vtr_error) { VTR_LOG_ERROR("%s:%d %s\n", vtr_error.filename_c_str(), vtr_error.line(), vtr_error.what()); - const Netlist<>& net_list = - vpr_setup.RouterOpts.flat_routing - ? (const Netlist<>&)g_vpr_ctx.atom().nlist - : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist; - vpr_free_all(net_list, Arch, vpr_setup); + vpr_free_all(Arch, vpr_setup); return ERROR_EXIT_CODE; } diff --git a/openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml index 0cb89d6fe..e012b32d3 100644 --- a/openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml @@ -1,25 +1,27 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml index 94b3b6090..ccb7417c7 100644 --- a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml @@ -1,39 +1,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml index 9bf434709..bcbb1e9ee 100644 --- a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml @@ -1,51 +1,53 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_sample_key.xml index 33e632b84..91293ca3d 100644 --- a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_sample_key.xml @@ -1,23 +1,25 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml index 1de56c747..ea9f98aae 100644 --- a/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml @@ -1,37 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml index 2ce5bfa52..d5d6e9f9f 100644 --- a/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_sample_key.xml @@ -1,37 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_sample_subkey.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_sample_subkey.xml new file mode 100644 index 000000000..ea1c6e27a --- /dev/null +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_sample_subkey.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/misc/ys_tmpl_yosys_vpr_adder_flow.ys b/openfpga_flow/misc/ys_tmpl_yosys_vpr_adder_flow.ys new file mode 100644 index 000000000..3d3acb5a5 --- /dev/null +++ b/openfpga_flow/misc/ys_tmpl_yosys_vpr_adder_flow.ys @@ -0,0 +1,48 @@ +# Yosys synthesis script for ${TOP_MODULE} +# Read verilog files +read_verilog ${READ_VERILOG_OPTIONS} ${VERILOG_FILES} + +# Technology mapping +hierarchy -top ${TOP_MODULE} +proc +techmap -D NO_LUT -map +/adff2dff.v + +# Synthesis +flatten +opt_expr +opt_clean +check +opt -nodffe -nosdff +fsm +opt -nodffe -nosdff +wreduce +peepopt +opt_clean + +# Map Adders +techmap -map +/techmap.v -map ${YOSYS_ADDER_MAP_VERILOG} +opt -fast -nodffe -nosdff +opt_expr +opt_merge +opt_clean +opt -nodffe -nosdff + +# +memory -nomap +opt_clean +opt -fast -full -nodffe -nosdff +memory_map +opt -full -nodffe -nosdff +techmap +opt -fast -nodffe -nosdff +clean + +# LUT mapping +abc -lut ${LUT_SIZE} + +# Check +#synth -run check + +# Clean and output blif +opt_clean -purge +write_blif ${OUTPUT_BLIF} diff --git a/openfpga_flow/openfpga_arch/README.md b/openfpga_flow/openfpga_arch/README.md index cdd8db5f3..b23e837ec 100644 --- a/openfpga_flow/openfpga_arch/README.md +++ b/openfpga_flow/openfpga_arch/README.md @@ -27,6 +27,7 @@ Note that an OpenFPGA architecture can be applied to multiple VPR architecture f - local\_encoder: If local encoders are used in routing multiplexer design - spyio/spypad: If spy I/Os are used - registerable\_io: If I/Os are registerable (can be either combinational or sequential) +- IoSubtile: If I/O block contains sub tiles (more compact with a higher density of I/Os) - stdcell: If circuit designs are built with standard cells only - tree\_mux: If routing multiplexers are built with a tree-like structure - localClkGen: The clock signal of CLB can be generated by internal programmable resources diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_registerable_io_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_registerable_io_cc_openfpga.xml index 8722f8614..56186f37f 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_registerable_io_cc_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_registerable_io_cc_openfpga.xml @@ -158,6 +158,13 @@ + + + + + + + @@ -175,6 +182,7 @@ + @@ -186,6 +194,12 @@ + + + + + + diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_IoSubtile_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_IoSubtile_cc_openfpga.xml new file mode 100644 index 000000000..6b17a175d --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_IoSubtile_cc_openfpga.xml @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/openfpga_arch/k4_frac_N4_adder_chain_mem1K_L124X_L12Y_40nm_frame_openfpga.xml b/openfpga_flow/openfpga_arch/k4_frac_N4_adder_chain_mem1K_L124X_L12Y_40nm_frame_openfpga.xml new file mode 100644 index 000000000..f489b97f5 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_frac_N4_adder_chain_mem1K_L124X_L12Y_40nm_frame_openfpga.xml @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/openfpga_shell_scripts/fpga_core_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/fpga_core_example_script.openfpga new file mode 100644 index 000000000..9385b6b28 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/fpga_core_example_script.openfpga @@ -0,0 +1,75 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose +# Add a fpga core between fpga top and the underlying modules +add_fpga_core_to_fabric ${OPENFPGA_WRAPPER_IO_NAMING_RULES} --instance_name fpga_core_inst --verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench ${OPENFPGA_TESTBENCH_DUT_MODULE} --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit +write_preconfigured_fabric_wrapper ${OPENFPGA_TESTBENCH_DUT_MODULE} --embed_bitstream iverilog --file ./SRC --explicit_port_mapping +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_shell_scripts/generate_bitstream_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_bitstream_example_script.openfpga index f96daafb9..f96bc27eb 100644 --- a/openfpga_flow/openfpga_shell_scripts/generate_bitstream_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/generate_bitstream_example_script.openfpga @@ -24,6 +24,8 @@ lut_truth_table_fixup # Note that this is turned on when bitstream generation # is the ONLY purpose of the flow!!! build_fabric --compress_routing --frame_view #--verbose +# Add a fpga core between fpga top and the underlying modules +add_fpga_core_to_fabric --instance_name fpga_core_inst --frame_view --verbose # Repack the netlist to physical pbs # This must be done before bitstream generator and testbench generation diff --git a/openfpga_flow/openfpga_shell_scripts/generate_bitstream_fpga_core_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/generate_bitstream_fpga_core_example_script.openfpga new file mode 100644 index 000000000..f96daafb9 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/generate_bitstream_fpga_core_example_script.openfpga @@ -0,0 +1,48 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route --absorb_buffer_luts off + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enabled frame view creation to save runtime and memory +# Note that this is turned on when bitstream generation +# is the ONLY purpose of the flow!!! +build_fabric --compress_routing --frame_view #--verbose + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.txt --format plain_text +write_fabric_bitstream --file fabric_bitstream.xml --format xml + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga new file mode 100644 index 000000000..74ec7b206 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga @@ -0,0 +1,74 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --device ${OPENFPGA_VPR_DEVICE} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH} --clock_modeling ideal + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --group_config_block ${OPENFPGA_GROUP_TILE_CONFIG_OPTION} #--verbose +# Add a fpga core between fpga top and the underlying modules +${OPENFPGA_ADD_FPGA_CORE_MODULE} + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit + +# Write the SDC files for PnR backend +# - Turn on every options here +# FIXME: Not supported yet. +#write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga new file mode 100644 index 000000000..978feaa56 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga @@ -0,0 +1,78 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --device ${OPENFPGA_VPR_DEVICE} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH} --clock_modeling ideal ${OPENFPGA_VPR_EXTRA_OPTIONS} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Optionally pb pin fixup +${OPENFPGA_PB_PIN_FIXUP_COMMAND} + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --group_config_block ${OPENFPGA_GROUP_TILE_CONFIG_OPTION} #--verbose +# Add a fpga core between fpga top and the underlying modules +${OPENFPGA_ADD_FPGA_CORE_MODULE} + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC ${OPENFPGA_VERILOG_TESTBENCH_OPTIONS} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} ${OPENFPGA_VERILOG_TESTBENCH_OPTIONS} + +# Write the SDC files for PnR backend +# - Turn on every options here +# FIXME: Not supported yet. +#write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_shell_scripts/group_tile_clkntwk_preconfig_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/group_tile_clkntwk_preconfig_testbench_example_script.openfpga new file mode 100644 index 000000000..e7a07d61d --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/group_tile_clkntwk_preconfig_testbench_example_script.openfpga @@ -0,0 +1,82 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --device ${OPENFPGA_VPR_DEVICE} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH} --clock_modeling ideal + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Read OpenFPGA clock architecture +read_openfpga_clock_arch -f ${OPENFPGA_CLOCK_ARCH_FILE} + +# Append clock network to vpr's routing resource graph +append_clock_rr_graph + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --sort_gsb_chan_node_in_edges + +# Route clock based on clock network definition +route_clock_rr_graph + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --group_tile ${OPENFPGA_GROUP_TILE_CONFIG_FILE} #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC ${OPENFPGA_VERILOG_TESTBENCH_OPTIONS} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} ${OPENFPGA_VERILOG_TESTBENCH_OPTIONS} + +# Write the SDC files for PnR backend +# - Turn on every options here +# FIXME: Not supported yet. +#write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_shell_scripts/group_tile_full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/group_tile_full_testbench_example_script.openfpga new file mode 100644 index 000000000..33ab79d65 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/group_tile_full_testbench_example_script.openfpga @@ -0,0 +1,72 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --group_tile ${OPENFPGA_GROUP_TILE_CONFIG_FILE} #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit + +# Write the SDC files for PnR backend +# - Turn on every options here +# FIXME: Not supported yet. +#write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga new file mode 100644 index 000000000..0e80a226a --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga @@ -0,0 +1,76 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --device ${OPENFPGA_VPR_DEVICE} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH} --clock_modeling ideal ${OPENFPGA_VPR_EXTRA_OPTIONS} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Optionally pb pin fixup +${OPENFPGA_PB_PIN_FIXUP_COMMAND} + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --group_tile ${OPENFPGA_GROUP_TILE_CONFIG_FILE} #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC ${OPENFPGA_VERILOG_TESTBENCH_OPTIONS} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} ${OPENFPGA_VERILOG_TESTBENCH_OPTIONS} + +# Write the SDC files for PnR backend +# - Turn on every options here +# FIXME: Not supported yet. +#write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga new file mode 100644 index 000000000..b1095060b --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga @@ -0,0 +1,73 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling ideal + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose +${OPENFPGA_MOCK_WRAPPER_ADD_FPGA_CORE} + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack ${OPENFPGA_REPACK_DESIGN_CONSTRAINTS} #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_mock_fpga_wrapper --file ./SRC ${OPENFPGA_MOCK_WRAPPER_OPTIONS} ${OPENFPGA_MOCK_WRAPPER_BGF} ${OPENFPGA_MOCK_WRAPPER_PCF} + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_preconfigured_fabric_wrapper --embed_bitstream none --file ./SRC --explicit_port_mapping ${OPENFPGA_MOCK_WRAPPER_BGF} ${OPENFPGA_MOCK_WRAPPER_PCF} +write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping ${OPENFPGA_MOCK_WRAPPER_BGF} ${OPENFPGA_MOCK_WRAPPER_PCF} + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga index 9eec95b23..20ff5dfe9 100644 --- a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga +++ b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga @@ -1,6 +1,6 @@ # Run VPR for the 'and' design #--write_rr_graph example_rr_graph.xml -vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route ${OPENFPGA_VPR_DEVICE_LAYOUT} +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling ideal ${OPENFPGA_VPR_DEVICE_LAYOUT} # Read OpenFPGA architecture definition read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} diff --git a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_fpga_core_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_fpga_core_example_script.openfpga new file mode 100644 index 000000000..0608ad9a7 --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_fpga_core_example_script.openfpga @@ -0,0 +1,73 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling ideal ${OPENFPGA_VPR_DEVICE_LAYOUT} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose +# Add a fpga core between fpga top and the underlying modules +add_fpga_core_to_fabric ${OPENFPGA_WRAPPER_IO_NAMING_RULES} --instance_name fpga_core_inst --verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text ${OPENFPGA_FAST_CONFIGURATION} + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench ${OPENFPGA_TESTBENCH_DUT_MODULE} --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --explicit_port_mapping --bitstream fabric_bitstream.bit ${OPENFPGA_FAST_CONFIGURATION} + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory diff --git a/openfpga_flow/openfpga_yosys_techlib/openfpga_adders_sim.v b/openfpga_flow/openfpga_yosys_techlib/openfpga_adders_sim.v index 9d82dc715..953ddf685 100644 --- a/openfpga_flow/openfpga_yosys_techlib/openfpga_adders_sim.v +++ b/openfpga_flow/openfpga_yosys_techlib/openfpga_adders_sim.v @@ -1,15 +1,15 @@ //--------------------------------------- // 1-bit adder //--------------------------------------- +(* abc9_box, lib_whitebox *) module adder( - input cin, - input a, - input b, - output cout, - output sumout ); - - - assign sumout = a ^ b ^ cin; - assign cout = (a & b) | ((a | b) & cin); + output sumout, + output cout, + input a, + input b, + input cin +); + assign sumout = a ^ b ^ cin; + assign cout = (a & b) | ((a | b) & cin); endmodule diff --git a/openfpga_flow/openfpga_yosys_techlib/openfpga_arith_map.v b/openfpga_flow/openfpga_yosys_techlib/openfpga_arith_map.v index d5227c16a..d363226fa 100644 --- a/openfpga_flow/openfpga_yosys_techlib/openfpga_arith_map.v +++ b/openfpga_flow/openfpga_yosys_techlib/openfpga_arith_map.v @@ -1,164 +1,67 @@ -////////////////////////// -// arithmetic // -////////////////////////// +// Arithmetic units: adder +// Adapt from: https://github.com/chipsalliance/yosys-f4pga-plugins/blob/0ad1af26a29243a9e76379943d735e119dcd0cc6/ql-qlf-plugin/qlf_k6n10/cells_sim.v +// Many thanks to F4PGA for their contribution -module \$alu (A, B, CI, BI, X, Y, CO); +(* techmap_celltype = "$alu" *) +module _80_quicklogic_alu (A, B, CI, BI, X, Y, CO); -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH:0] X, Y; + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] X, Y; -input CI, BI; -output [Y_WIDTH:0] CO; + input CI, BI; + output [Y_WIDTH-1:0] CO; -wire [Y_WIDTH-1:0] AA, BB; -wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean"; + wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean"; -generate - if (A_SIGNED && B_SIGNED) begin:BLOCK1 - assign AA = $signed(A), BB = BI ? ~$signed(B) : $signed(B); - end else begin:BLOCK2 - assign AA = $unsigned(A), BB = BI ? ~$unsigned(B) : $unsigned(B); - end -endgenerate + (* force_downto *) + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - wire [Y_WIDTH: 0 ] CARRY; - assign CARRY[0] = CI; + (* force_downto *) + wire [Y_WIDTH-1:0] AA = A_buf; + (* force_downto *) + wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; + wire [Y_WIDTH: 0 ] CARRY; - genvar i; - generate for (i = 0; i < Y_WIDTH - 1; i = i+1) begin:gen3 - adder my_adder ( - .cin (CARRY[i]), - .cout (CARRY[i+1]), - .a (AA[i]), - .b (BB[i]), - .sumout (Y[i]) - ); - end endgenerate + assign CO[Y_WIDTH-1:0] = CARRY[Y_WIDTH:1]; + // Due to VPR limitations regarding IO connexion to carry chain, + // we generate the carry chain input signal using an intermediate adder + // since we can connect a & b from io pads, but not cin & cout + generate + adder intermediate_adder ( + .cin ( ), + .cout (CARRY[0]), + .a (CI ), + .b (CI ), + .sumout ( ) + ); - generate if ((Y_WIDTH -1) % 20 == 0) begin:gen4 - assign Y[Y_WIDTH-1] = CARRY[Y_WIDTH-1]; - end else begin:gen5 - adder my_adder ( - .cin (CARRY[Y_WIDTH - 1]), - .cout (CARRY[Y_WIDTH]), - .a (1'b0), - .b (1'b0), - .sumout (Y[Y_WIDTH -1]) - ); - end - endgenerate - endmodule + adder first_adder ( + .cin (CARRY[0]), + .cout (CARRY[1]), + .a (AA[0] ), + .b (BB[0] ), + .sumout (Y[0] ) + ); + endgenerate -//--------------------------------------------------------- - -module \$fa (A, B, C, X, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -input C; -output [Y_WIDTH:0] X, Y; - -wire [Y_WIDTH-1:0] AA, BB; -wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean"; - -generate - if (A_SIGNED && B_SIGNED) begin:BLOCK1 - assign AA = $signed(A), BB = $signed(B); - end else begin:BLOCK2 - assign AA = $unsigned(A), BB = $unsigned(B); - end -endgenerate - - wire [Y_WIDTH: 0 ] CARRY; - assign CARRY[0] = C; - - genvar i; - generate for (i = 0; i < Y_WIDTH - 1; i = i+1) begin:gen3 - adder my_adder ( - .cin (CARRY[i]), - .cout (CARRY[i+1]), - .a (AA[i]), - .b (BB[i]), - .sumout (Y[i]) - ); - end endgenerate - - generate if ((Y_WIDTH -1) % 20 == 0) begin:gen4 - assign Y[Y_WIDTH-1] = CARRY[Y_WIDTH-1]; - end else begin:gen5 - adder my_adder ( - .cin (CARRY[Y_WIDTH - 1]), - .cout (CARRY[Y_WIDTH]), - .a (1'b0), - .b (1'b0), - .sumout (Y[Y_WIDTH -1]) - ); - end - endgenerate - endmodule - -//--------------------------------------------------------- - -module \$add (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH:0] Y; - -wire [Y_WIDTH-1:0] AA, BB; -wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean"; - -generate - if (A_SIGNED && B_SIGNED) begin:BLOCK1 - assign AA = $signed(A), BB = $signed(B); - end else begin:BLOCK2 - assign AA = $unsigned(A), BB = $unsigned(B); - end -endgenerate - - wire [Y_WIDTH: 0 ] CARRY; - assign CARRY[0] = 1'b0; - - genvar i; - generate for (i = 0; i < Y_WIDTH - 1; i = i+1) begin:gen3 - adder my_adder ( - .cin (CARRY[i]), - .cout (CARRY[i+1]), - .a (AA[i]), - .b (BB[i]), - .sumout (Y[i]) - ); - end endgenerate - - generate if ((Y_WIDTH -1) % 20 == 0) begin:gen4 - assign Y[Y_WIDTH-1] = CARRY[Y_WIDTH-1]; - end else begin:gen5 - adder my_adder ( - .cin (CARRY[Y_WIDTH - 1]), - .cout (CARRY[Y_WIDTH]), - .a (1'b0), - .b (1'b0), - .sumout (Y[Y_WIDTH -1]) - ); - end - endgenerate - endmodule + genvar i; + generate for (i = 1; i < Y_WIDTH ; i = i+1) begin:gen3 + adder my_adder ( + .cin (CARRY[i] ), + .cout (CARRY[i+1]), + .a (AA[i] ), + .b (BB[i] ), + .sumout (Y[i] ) + ); + end endgenerate + assign X = AA ^ BB; +endmodule diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index dd9e64a56..749765a33 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -15,6 +15,14 @@ echo -e "Test source commands in openfpga shell" run-task basic_tests/source_command/source_string $@ run-task basic_tests/source_command/source_file $@ +echo -e "Testing testbenches using fpga core wrapper" +run-task basic_tests/full_testbench/fpga_core_wrapper $@ +run-task basic_tests/full_testbench/fpga_core_wrapper_naming_rules $@ +run-task basic_tests/full_testbench/fpga_core_wrapper_naming_rules_use_core_tb $@ +run-task basic_tests/preconfig_testbench/fpga_core_wrapper $@ +run-task basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules $@ +run-task basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules_use_core_tb $@ + echo -e "Testing configuration chain of a K4N4 FPGA"; run-task basic_tests/full_testbench/configuration_chain $@ run-task basic_tests/full_testbench/configuration_chain_no_time_stamp $@ @@ -108,6 +116,7 @@ run-task basic_tests/fabric_key/generate_random_key $@ run-task basic_tests/fabric_key/generate_random_key_ql_memory_bank $@ run-task basic_tests/fabric_key/load_external_key $@ run-task basic_tests/fabric_key/load_external_key_cc_fpga $@ +run-task basic_tests/fabric_key/load_external_subkey_cc_fpga $@ run-task basic_tests/fabric_key/load_external_key_multi_region_cc_fpga $@ run-task basic_tests/fabric_key/load_external_key_qlbank_fpga $@ run-task basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga $@ @@ -115,6 +124,12 @@ run-task basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain_fpga $@ # TODO: This feature is temporarily out of test due to the emergency in delivering netlists for multi-chain shift-register memory bank #run-task basic_tests/fabric_key/load_external_key_multi_region_qlbanksr_fpga $@ +echo -e "Testing mock wrapper" +run-task basic_tests/mock_wrapper/mock_wrapper_explicit_port_mapping $@ +run-task basic_tests/mock_wrapper/mock_wrapper_implicit_port_mapping $@ +run-task basic_tests/mock_wrapper/mock_wrapper_pcf $@ +run-task basic_tests/mock_wrapper/mock_wrapper_bgf $@ + echo -e "Testing K4 series FPGA"; echo -e "Testing K4N4 with facturable LUTs"; run-task basic_tests/k4_series/k4n4_frac_lut $@ @@ -132,6 +147,10 @@ echo -e "Testing K4N4 with LUTRAM"; run-task basic_tests/k4_series/k4n4_lutram $@ echo -e "Testing K4N4 with multiple lengths of routing segments"; run-task basic_tests/k4_series/k4n4_L124 $@ +echo -e "Testing K4N4 with routing channel width distribution: x = 0.8, y = 1.0"; +run-task basic_tests/k4_series/k4n4_chandistr $@ +echo -e "Testing K4N4 with routing channel width distribution: x = 0.8, y = 1.0 and wire segment distribution: x=L124, Y=L12"; +run-task basic_tests/k4_series/k4n4_chandistr_segdist $@ echo -e "Testing K4N4 with 32-bit fracturable multiplier"; run-task basic_tests/k4_series/k4n4_frac_mult $@ echo -e "Testing K4N5 with pattern based local routing"; @@ -158,9 +177,34 @@ echo -e "Testing tiles with pins only on bottom and right sides"; run-task basic_tests/tile_organization/bottom_right_custom_pins $@ echo -e "Testing tiles with I/O in center grid"; run-task basic_tests/tile_organization/tileable_io $@ +echo -e "Testing tiles with I/O consisting of subtiles"; +run-task basic_tests/tile_organization/io_subtile $@ +run-task basic_tests/tile_organization/io_subtile_strong $@ +echo -e "Testing tile grouping on a homogeneous FPGA fabric (Full testbench)"; +run-task basic_tests/tile_organization/homo_fabric_tile $@ +echo -e "Testing tile grouping on a homogeneous FPGA fabric (Preconfigured testbench)"; +run-task basic_tests/tile_organization/fabric_tile_global_tile_clock_io_subtile $@ +run-task basic_tests/tile_organization/homo_fabric_tile_preconfig $@ +run-task basic_tests/tile_organization/homo_fabric_tile_2x2_preconfig $@ +run-task basic_tests/tile_organization/homo_fabric_tile_4x4_preconfig $@ +run-task basic_tests/tile_organization/homo_fabric_tile_global_tile_clock $@ +run-task basic_tests/tile_organization/homo_fabric_tile_adder_chain $@ +run-task basic_tests/tile_organization/homo_fabric_tile_clkntwk $@ +run-task basic_tests/tile_organization/hetero_fabric_tile $@ + +echo -e "Testing group config block"; +run-task basic_tests/group_config_block/group_config_block_homo_full_testbench $@ +run-task basic_tests/group_config_block/group_config_block_homo_Lshape_full_testbench $@ +run-task basic_tests/group_config_block/group_config_block_homo_fabric_tile $@ +run-task basic_tests/group_config_block/group_config_block_homo_fabric_tile_Lshape $@ +run-task basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper $@ +run-task basic_tests/group_config_block/group_config_block_hetero_fabric_tile $@ +run-task basic_tests/group_config_block/group_config_block_hetero_fabric_tile_Lshape $@ +run-task basic_tests/group_config_block/group_config_block_homo_fabric_tile_global_tile_clock_io_subtile $@ echo -e "Testing global port definition from tiles"; run-task basic_tests/global_tile_ports/global_tile_clock $@ +run-task basic_tests/global_tile_ports/global_tile_clock_subtile $@ run-task basic_tests/global_tile_ports/global_tile_reset $@ run-task basic_tests/global_tile_ports/global_tile_4clock $@ run-task basic_tests/global_tile_ports/global_tile_4clock_pin $@ diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index 585cd3f19..f5bb9a78f 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -20,6 +20,9 @@ echo -e "Testing bitstream generation for an 96x96 FPGA device"; run-task fpga_bitstream/generate_bitstream/configuration_chain/device_96x96 $@ run-task fpga_bitstream/generate_bitstream/ql_memory_bank_shift_register/device_72x72 $@ +echo -e "Testing bitstream generation when fpga core wrapper is added"; +run-task fpga_bitstream/generate_bitstream/fpga_core_wrapper $@ + echo -e "Testing loading architecture bitstream from an external file"; run-task fpga_bitstream/load_external_architecture_bitstream $@ diff --git a/openfpga_flow/scripts/run_fpga_task.py b/openfpga_flow/scripts/run_fpga_task.py index 313ee991a..30a0fde92 100644 --- a/openfpga_flow/scripts/run_fpga_task.py +++ b/openfpga_flow/scripts/run_fpga_task.py @@ -294,6 +294,7 @@ def generate_each_task_actions(taskname): yosys_params = [ "read_verilog_options", "yosys_args", + "yosys_adder_map_verilog", "yosys_bram_map_rules", "yosys_bram_map_verilog", "yosys_cell_sim_verilog", diff --git a/openfpga_flow/tasks/basic_tests/fabric_key/load_external_subkey_cc_fpga/config/task.conf b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_subkey_cc_fpga/config/task.conf new file mode 100644 index 000000000..c2fd428d7 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_subkey_cc_fpga/config/task.conf @@ -0,0 +1,39 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +external_fabric_key_file=${PATH:OPENFPGA_PATH}/openfpga_flow/fabric_keys/k4_N4_2x2_sample_subkey.xml +openfpga_vpr_device_layout=2x2 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper/config/task.conf new file mode 100644 index 000000000..55d56b630 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_fpga_core_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= +openfpga_wrapper_io_naming_rules= +openfpga_testbench_dut_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 + +bench1_top = or2 + +bench2_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules/config/task.conf new file mode 100644 index 000000000..87a7f4877 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_fpga_core_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= +openfpga_wrapper_io_naming_rules=--io_naming ${PATH:TASK_DIR}/config/wrapper_io_naming.xml +openfpga_testbench_dut_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 + +bench1_top = or2 + +bench2_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules/config/wrapper_io_naming.xml b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules/config/wrapper_io_naming.xml new file mode 100644 index 000000000..616ce00dd --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules/config/wrapper_io_naming.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/task.conf new file mode 100644 index 000000000..f059afe33 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_fpga_core_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= +openfpga_wrapper_io_naming_rules=--io_naming ${PATH:TASK_DIR}/config/wrapper_io_naming.xml +openfpga_testbench_dut_module=--dut_module fpga_core + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 + +bench1_top = or2 + +bench2_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/wrapper_io_naming.xml b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/wrapper_io_naming.xml new file mode 100644 index 000000000..616ce00dd --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/wrapper_io_naming.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_clock_subtile/config/task.conf b/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_clock_subtile/config/task.conf new file mode 100644 index 000000000..d75851ad9 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_clock_subtile/config/task.conf @@ -0,0 +1,35 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/global_tile_clock_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_registerable_io_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=2x2_hybrid_io + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_pipelined/and2_pipelined.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2_pipelined + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/task.conf new file mode 100644 index 000000000..c8f54dda0 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/task.conf @@ -0,0 +1,55 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_dsp8_caravel_io_skywater130nm_fdhd_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options=--constant_net_method route --skip_sync_clustering_and_routing_results on +openfpga_pb_pin_fixup_command = pb_pin_fixup --verbose +openfpga_vpr_device=3x2 +openfpga_vpr_route_chan_width=60 +openfpga_group_tile_config_option=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options= +openfpga_add_fpga_core_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_2/mac_2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_4/mac_4.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_6/mac_6.v +bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8/mac_8.v + +[SYNTHESIS_PARAM] +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm_cell_sim.v +bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm_dsp_map.v +bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=8 -D DSP_B_MAXWIDTH=8 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_8x8 +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dsp_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys + +bench0_top = mac_2 +bench1_top = mac_4 +bench2_top = mac_6 +bench3_top = mac_8 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile_Lshape/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile_Lshape/config/task.conf new file mode 100644 index 000000000..8967adc33 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile_Lshape/config/task.conf @@ -0,0 +1,49 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_dsp8_caravel_io_skywater130nm_fdhd_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options=--constant_net_method route --skip_sync_clustering_and_routing_results on +openfpga_pb_pin_fixup_command = pb_pin_fixup --verbose +openfpga_vpr_device=3x2L +openfpga_vpr_route_chan_width=60 +openfpga_group_tile_config_option=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options= +openfpga_add_fpga_core_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N8_tileableL_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_2/mac_2.v + +[SYNTHESIS_PARAM] +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm_cell_sim.v +bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm_dsp_map.v +bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=8 -D DSP_B_MAXWIDTH=8 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_8x8 +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dsp_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys + +bench0_top = mac_2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile_Lshape/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile_Lshape/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_hetero_fabric_tile_Lshape/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_Lshape_full_testbench/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_Lshape_full_testbench/config/task.conf new file mode 100644 index 000000000..3b77cc65e --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_Lshape_full_testbench/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_group_tile_config_option= +openfpga_add_fpga_core_module= +openfpga_vpr_device=4x4L +openfpga_vpr_route_chan_width=20 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileableL_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/task.conf new file mode 100644 index 000000000..0273db97c --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_group_tile_config_option=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml +openfpga_add_fpga_core_module= +openfpga_vpr_device=auto +openfpga_vpr_route_chan_width=20 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_Lshape/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_Lshape/config/task.conf new file mode 100644 index 000000000..e18407d92 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_Lshape/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_group_tile_config_option=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml +openfpga_add_fpga_core_module= +openfpga_vpr_device=4x4L_io_boundary +openfpga_vpr_route_chan_width=20 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileableL_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_Lshape/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_Lshape/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_Lshape/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/task.conf new file mode 100644 index 000000000..ec54e6ca9 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_group_tile_config_option=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml +openfpga_add_fpga_core_module=add_fpga_core_to_fabric --instance_name fpga_core_inst +openfpga_vpr_device=auto +openfpga_vpr_route_chan_width=20 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_core_wrapper/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_global_tile_clock_io_subtile/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_global_tile_clock_io_subtile/config/task.conf new file mode 100644 index 000000000..a04c046d9 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_global_tile_clock_io_subtile/config/task.conf @@ -0,0 +1,42 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_registerable_io_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options= +openfpga_pb_pin_fixup_command= +openfpga_vpr_device=2x2_hybrid_io +openfpga_vpr_route_chan_width=20 +openfpga_group_tile_config_option=--group_tile ${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options=--explicit_port_mapping +openfpga_add_fpga_core_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_pipelined/and2_pipelined.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2_pipelined + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_global_tile_clock_io_subtile/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_global_tile_clock_io_subtile/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_fabric_tile_global_tile_clock_io_subtile/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_full_testbench/config/task.conf b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_full_testbench/config/task.conf new file mode 100644 index 000000000..5e22d1e08 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/group_config_block/group_config_block_homo_full_testbench/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_config_block_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_group_tile_config_option= +openfpga_add_fpga_core_module= +openfpga_vpr_device=2x2 +openfpga_vpr_route_chan_width=20 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_chandistr/config/task.conf b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_chandistr/config/task.conf new file mode 100644 index 000000000..99478308c --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_chandistr/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_adder_chain_mem1K_L124_40nm_frame_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=4x4 +openfpga_vpr_route_chan_width=40 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N4_tileable_adder_chain_mem1K_L124_ChanWidth0p8_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_chandistr_segdist/config/task.conf b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_chandistr_segdist/config/task.conf new file mode 100644 index 000000000..e948a73b5 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_chandistr_segdist/config/task.conf @@ -0,0 +1,38 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_route_chan_width_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_adder_chain_mem1K_L124X_L12Y_40nm_frame_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=4x4 +openfpga_vpr_route_chan_width=60 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N4_tileable_adder_chain_mem1K_L124X_L12Y_ChanWidth0p8_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_bgf/config/counter8_bus_group.xml b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_bgf/config/counter8_bus_group.xml new file mode 100644 index 000000000..a0fd22f77 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_bgf/config/counter8_bus_group.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_bgf/config/pin_constraints_reset.xml b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_bgf/config/pin_constraints_reset.xml new file mode 100644 index 000000000..abcf209f6 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_bgf/config/pin_constraints_reset.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_bgf/config/task.conf b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_bgf/config/task.conf new file mode 100644 index 000000000..ed90fa347 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_bgf/config/task.conf @@ -0,0 +1,52 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_repack_design_constraints= +openfpga_mock_wrapper_options=--explicit_port_mapping +openfpga_mock_wrapper_bgf= +openfpga_mock_wrapper_pcf= +openfpga_mock_wrapper_add_fpga_core= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_reset/counter.v + +[SYNTHESIS_PARAM] +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v +bench_yosys_dff_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v +bench_yosys_bram_map_rules_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt +bench_yosys_bram_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v +bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v +bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36 +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys + +bench0_top = counter +bench0_openfpga_mock_wrapper_pcf=-pcf ${PATH:TASK_DIR}/config/pin_constraints_reset.xml +bench0_openfpga_mock_wrapper_bgf=-bgf ${PATH:TASK_DIR}/config/counter8_bus_group.xml + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_explicit_port_mapping/config/task.conf b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_explicit_port_mapping/config/task.conf new file mode 100644 index 000000000..efda62297 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_explicit_port_mapping/config/task.conf @@ -0,0 +1,46 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_repack_design_constraints= +openfpga_mock_wrapper_options=--explicit_port_mapping +openfpga_mock_wrapper_bgf= +openfpga_mock_wrapper_pcf= +openfpga_mock_wrapper_add_fpga_core= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 + +bench1_top = or2 + +bench2_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/counter8_bus_group.xml b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/counter8_bus_group.xml new file mode 100644 index 000000000..a0fd22f77 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/counter8_bus_group.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/pin_constraints_reset.xml b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/pin_constraints_reset.xml new file mode 100644 index 000000000..abcf209f6 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/pin_constraints_reset.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/task.conf b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/task.conf new file mode 100644 index 000000000..9647f9374 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/task.conf @@ -0,0 +1,52 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_repack_design_constraints= +openfpga_mock_wrapper_options=--explicit_port_mapping +openfpga_mock_wrapper_bgf= +openfpga_mock_wrapper_pcf= +openfpga_mock_wrapper_add_fpga_core=add_fpga_core_to_fabric --io_naming ${PATH:TASK_DIR}/config/wrapper_io_naming.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_reset/counter.v + +[SYNTHESIS_PARAM] +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v +bench_yosys_dff_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v +bench_yosys_bram_map_rules_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt +bench_yosys_bram_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v +bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v +bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36 +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys + +bench0_top = counter +bench0_openfpga_mock_wrapper_pcf=-pcf ${PATH:TASK_DIR}/config/pin_constraints_reset.xml +bench0_openfpga_mock_wrapper_bgf=-bgf ${PATH:TASK_DIR}/config/counter8_bus_group.xml + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/wrapper_io_naming.xml b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/wrapper_io_naming.xml new file mode 100644 index 000000000..616ce00dd --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_fpga_core/config/wrapper_io_naming.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_implicit_port_mapping/config/task.conf b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_implicit_port_mapping/config/task.conf new file mode 100644 index 000000000..e05f55e87 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_implicit_port_mapping/config/task.conf @@ -0,0 +1,46 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_repack_design_constraints= +openfpga_mock_wrapper_options= +openfpga_mock_wrapper_bgf= +openfpga_mock_wrapper_pcf= +openfpga_mock_wrapper_add_fpga_core= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 + +bench1_top = or2 + +bench2_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_pcf/config/and2_latch_pin_constraints.xml b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_pcf/config/and2_latch_pin_constraints.xml new file mode 100644 index 000000000..e6949c9d4 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_pcf/config/and2_latch_pin_constraints.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_pcf/config/repack_pin_constraints.xml b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_pcf/config/repack_pin_constraints.xml new file mode 100644 index 000000000..d695cf85e --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_pcf/config/repack_pin_constraints.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_pcf/config/task.conf b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_pcf/config/task.conf new file mode 100644 index 000000000..3e2a95a3a --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/mock_wrapper/mock_wrapper_pcf/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTile4Clk_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_4clock_sim_openfpga.xml +openfpga_repack_design_constraints=--design_constraints ${PATH:TASK_DIR}/config/repack_pin_constraints.xml +openfpga_mock_wrapper_options= +openfpga_mock_wrapper_bgf= +openfpga_mock_wrapper_pcf= +openfpga_mock_wrapper_add_fpga_core= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTile4Clk_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch_2clock/and2_latch_2clock.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches + +bench0_top = and2_latch_2clock +bench0_openfpga_pin_constraints=--design_constraints ${PATH:TASK_DIR}/config/and2_latch_pin_constraints.xml +bench0_openfpga_mock_wrapper_pcf=-pcf ${PATH:TASK_DIR}/config/and2_latch_pin_constraints.xml +bench0_openfpga_mock_wrapper_bgf= + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_formal_random_top_tb.v b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_formal_random_top_tb.v index f82c458e3..9445b3195 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_formal_random_top_tb.v +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_formal_random_top_tb.v @@ -50,7 +50,7 @@ module and2_top_formal_verification_random_tb; initial begin clk[0] <= 1'b0; while(1) begin - #0.7626540661 + #0.4628907144 clk[0] <= !clk[0]; end end @@ -109,7 +109,7 @@ initial begin $timeformat(-9, 2, "ns", 20); $display("Simulation start"); // ----- Can be changed by the user for his/her need ------- - #10.6771574 + #6.480470181 if(nb_error == 0) begin $display("Simulation Succeed"); end else begin diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_fpga_top_analysis.sdc b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_fpga_top_analysis.sdc index acf0f91b8..fa1a05891 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_fpga_top_analysis.sdc +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_fpga_top_analysis.sdc @@ -9,20 +9,19 @@ ################################################## # Create clock ################################################## -create_clock clk[0] -period 1.525308102e-09 -waveform {0 7.62654051e-10} +create_clock clk[0] -period 9.25781396e-10 -waveform {0 4.62890698e-10} ################################################## # Create input and output delays for used I/Os ################################################## -set_input_delay -clock clk[0] -max 1.525308102e-09 gfpga_pad_GPIO_PAD[27] -set_input_delay -clock clk[0] -max 1.525308102e-09 gfpga_pad_GPIO_PAD[15] -set_output_delay -clock clk[0] -max 1.525308102e-09 gfpga_pad_GPIO_PAD[12] +set_input_delay -clock clk[0] -max 9.25781396e-10 gfpga_pad_GPIO_PAD[11] +set_input_delay -clock clk[0] -max 9.25781396e-10 gfpga_pad_GPIO_PAD[14] +set_output_delay -clock clk[0] -max 9.25781396e-10 gfpga_pad_GPIO_PAD[1] ################################################## # Disable timing for unused I/Os ################################################## set_disable_timing gfpga_pad_GPIO_PAD[0] -set_disable_timing gfpga_pad_GPIO_PAD[1] set_disable_timing gfpga_pad_GPIO_PAD[2] set_disable_timing gfpga_pad_GPIO_PAD[3] set_disable_timing gfpga_pad_GPIO_PAD[4] @@ -32,9 +31,9 @@ set_disable_timing gfpga_pad_GPIO_PAD[7] set_disable_timing gfpga_pad_GPIO_PAD[8] set_disable_timing gfpga_pad_GPIO_PAD[9] set_disable_timing gfpga_pad_GPIO_PAD[10] -set_disable_timing gfpga_pad_GPIO_PAD[11] +set_disable_timing gfpga_pad_GPIO_PAD[12] set_disable_timing gfpga_pad_GPIO_PAD[13] -set_disable_timing gfpga_pad_GPIO_PAD[14] +set_disable_timing gfpga_pad_GPIO_PAD[15] set_disable_timing gfpga_pad_GPIO_PAD[16] set_disable_timing gfpga_pad_GPIO_PAD[17] set_disable_timing gfpga_pad_GPIO_PAD[18] @@ -46,6 +45,7 @@ set_disable_timing gfpga_pad_GPIO_PAD[23] set_disable_timing gfpga_pad_GPIO_PAD[24] set_disable_timing gfpga_pad_GPIO_PAD[25] set_disable_timing gfpga_pad_GPIO_PAD[26] +set_disable_timing gfpga_pad_GPIO_PAD[27] set_disable_timing gfpga_pad_GPIO_PAD[28] set_disable_timing gfpga_pad_GPIO_PAD[29] set_disable_timing gfpga_pad_GPIO_PAD[30] @@ -156,9 +156,11 @@ set_disable_timing cbx_1__0_/chanx_left_in[7] set_disable_timing cbx_1__0_/chanx_right_in[7] set_disable_timing cbx_1__0_/chanx_left_in[8] set_disable_timing cbx_1__0_/chanx_right_in[8] +set_disable_timing cbx_1__0_/chanx_left_in[9] set_disable_timing cbx_1__0_/chanx_right_in[9] set_disable_timing cbx_1__0_/chanx_left_in[10] set_disable_timing cbx_1__0_/chanx_right_in[10] +set_disable_timing cbx_1__0_/chanx_left_in[11] set_disable_timing cbx_1__0_/chanx_right_in[11] set_disable_timing cbx_1__0_/chanx_left_in[12] set_disable_timing cbx_1__0_/chanx_right_in[12] @@ -180,9 +182,11 @@ set_disable_timing cbx_1__0_/chanx_left_out[7] set_disable_timing cbx_1__0_/chanx_right_out[7] set_disable_timing cbx_1__0_/chanx_left_out[8] set_disable_timing cbx_1__0_/chanx_right_out[8] +set_disable_timing cbx_1__0_/chanx_left_out[9] set_disable_timing cbx_1__0_/chanx_right_out[9] set_disable_timing cbx_1__0_/chanx_left_out[10] set_disable_timing cbx_1__0_/chanx_right_out[10] +set_disable_timing cbx_1__0_/chanx_left_out[11] set_disable_timing cbx_1__0_/chanx_right_out[11] set_disable_timing cbx_1__0_/chanx_left_out[12] set_disable_timing cbx_1__0_/chanx_right_out[12] @@ -272,6 +276,7 @@ set_disable_timing cbx_1__1_/chanx_left_in[1] set_disable_timing cbx_1__1_/chanx_left_in[2] set_disable_timing cbx_1__1_/chanx_right_in[2] set_disable_timing cbx_1__1_/chanx_left_in[3] +set_disable_timing cbx_1__1_/chanx_right_in[3] set_disable_timing cbx_1__1_/chanx_left_in[4] set_disable_timing cbx_1__1_/chanx_right_in[4] set_disable_timing cbx_1__1_/chanx_left_in[5] @@ -280,6 +285,7 @@ set_disable_timing cbx_1__1_/chanx_left_in[6] set_disable_timing cbx_1__1_/chanx_right_in[6] set_disable_timing cbx_1__1_/chanx_left_in[7] set_disable_timing cbx_1__1_/chanx_right_in[7] +set_disable_timing cbx_1__1_/chanx_left_in[8] set_disable_timing cbx_1__1_/chanx_right_in[8] set_disable_timing cbx_1__1_/chanx_left_in[9] set_disable_timing cbx_1__1_/chanx_right_in[9] @@ -295,6 +301,7 @@ set_disable_timing cbx_1__1_/chanx_left_out[1] set_disable_timing cbx_1__1_/chanx_left_out[2] set_disable_timing cbx_1__1_/chanx_right_out[2] set_disable_timing cbx_1__1_/chanx_left_out[3] +set_disable_timing cbx_1__1_/chanx_right_out[3] set_disable_timing cbx_1__1_/chanx_left_out[4] set_disable_timing cbx_1__1_/chanx_right_out[4] set_disable_timing cbx_1__1_/chanx_left_out[5] @@ -303,6 +310,7 @@ set_disable_timing cbx_1__1_/chanx_left_out[6] set_disable_timing cbx_1__1_/chanx_right_out[6] set_disable_timing cbx_1__1_/chanx_left_out[7] set_disable_timing cbx_1__1_/chanx_right_out[7] +set_disable_timing cbx_1__1_/chanx_left_out[8] set_disable_timing cbx_1__1_/chanx_right_out[8] set_disable_timing cbx_1__1_/chanx_left_out[9] set_disable_timing cbx_1__1_/chanx_right_out[9] @@ -313,13 +321,13 @@ set_disable_timing cbx_1__1_/chanx_right_out[11] set_disable_timing cbx_1__1_/chanx_left_out[12] set_disable_timing cbx_1__1_/chanx_right_out[12] set_disable_timing cbx_1__1_/top_grid_bottom_width_0_height_0_subtile_0__pin_outpad_0_[0] -set_disable_timing cbx_1__1_/top_grid_bottom_width_0_height_0_subtile_1__pin_outpad_0_[0] set_disable_timing cbx_1__1_/top_grid_bottom_width_0_height_0_subtile_2__pin_outpad_0_[0] set_disable_timing cbx_1__1_/top_grid_bottom_width_0_height_0_subtile_3__pin_outpad_0_[0] set_disable_timing cbx_1__1_/top_grid_bottom_width_0_height_0_subtile_4__pin_outpad_0_[0] set_disable_timing cbx_1__1_/top_grid_bottom_width_0_height_0_subtile_5__pin_outpad_0_[0] set_disable_timing cbx_1__1_/top_grid_bottom_width_0_height_0_subtile_6__pin_outpad_0_[0] set_disable_timing cbx_1__1_/top_grid_bottom_width_0_height_0_subtile_7__pin_outpad_0_[0] +set_disable_timing cbx_1__1_/bottom_grid_top_width_0_height_0_subtile_0__pin_I_0_[0] set_disable_timing cbx_1__1_/bottom_grid_top_width_0_height_0_subtile_0__pin_I_4_[0] set_disable_timing cbx_1__1_/bottom_grid_top_width_0_height_0_subtile_0__pin_I_8_[0] set_disable_timing cbx_1__1_/mux_bottom_ipin_0/in[1] @@ -331,7 +339,6 @@ set_disable_timing cbx_1__1_/mux_bottom_ipin_7/in[0] set_disable_timing cbx_1__1_/mux_bottom_ipin_1/in[3] set_disable_timing cbx_1__1_/mux_bottom_ipin_2/in[1] set_disable_timing cbx_1__1_/mux_top_ipin_0/in[1] -set_disable_timing cbx_1__1_/mux_bottom_ipin_1/in[2] set_disable_timing cbx_1__1_/mux_bottom_ipin_2/in[0] set_disable_timing cbx_1__1_/mux_top_ipin_0/in[0] set_disable_timing cbx_1__1_/mux_bottom_ipin_2/in[3] @@ -367,6 +374,7 @@ set_disable_timing cbx_1__1_/mux_bottom_ipin_1/in[4] set_disable_timing cbx_1__1_/mux_bottom_ipin_7/in[4] set_disable_timing cbx_1__1_/mux_top_ipin_0/in[2] set_disable_timing cbx_1__1_/mux_bottom_ipin_2/in[5] +set_disable_timing cbx_1__1_/mux_top_ipin_0/in[5] set_disable_timing cbx_1__1_/mux_top_ipin_1/in[3] set_disable_timing cbx_1__1_/mux_bottom_ipin_2/in[4] set_disable_timing cbx_1__1_/mux_top_ipin_0/in[4] @@ -396,6 +404,7 @@ set_disable_timing cby_0__1_/chany_bottom_in[1] set_disable_timing cby_0__1_/chany_top_in[1] set_disable_timing cby_0__1_/chany_bottom_in[2] set_disable_timing cby_0__1_/chany_top_in[2] +set_disable_timing cby_0__1_/chany_bottom_in[3] set_disable_timing cby_0__1_/chany_top_in[3] set_disable_timing cby_0__1_/chany_bottom_in[4] set_disable_timing cby_0__1_/chany_top_in[4] @@ -406,9 +415,11 @@ set_disable_timing cby_0__1_/chany_top_in[6] set_disable_timing cby_0__1_/chany_bottom_in[7] set_disable_timing cby_0__1_/chany_top_in[7] set_disable_timing cby_0__1_/chany_bottom_in[8] +set_disable_timing cby_0__1_/chany_top_in[8] set_disable_timing cby_0__1_/chany_bottom_in[9] set_disable_timing cby_0__1_/chany_top_in[9] set_disable_timing cby_0__1_/chany_bottom_in[10] +set_disable_timing cby_0__1_/chany_top_in[10] set_disable_timing cby_0__1_/chany_bottom_in[11] set_disable_timing cby_0__1_/chany_top_in[11] set_disable_timing cby_0__1_/chany_bottom_in[12] @@ -419,6 +430,7 @@ set_disable_timing cby_0__1_/chany_bottom_out[1] set_disable_timing cby_0__1_/chany_top_out[1] set_disable_timing cby_0__1_/chany_bottom_out[2] set_disable_timing cby_0__1_/chany_top_out[2] +set_disable_timing cby_0__1_/chany_bottom_out[3] set_disable_timing cby_0__1_/chany_top_out[3] set_disable_timing cby_0__1_/chany_bottom_out[4] set_disable_timing cby_0__1_/chany_top_out[4] @@ -429,9 +441,11 @@ set_disable_timing cby_0__1_/chany_top_out[6] set_disable_timing cby_0__1_/chany_bottom_out[7] set_disable_timing cby_0__1_/chany_top_out[7] set_disable_timing cby_0__1_/chany_bottom_out[8] +set_disable_timing cby_0__1_/chany_top_out[8] set_disable_timing cby_0__1_/chany_bottom_out[9] set_disable_timing cby_0__1_/chany_top_out[9] set_disable_timing cby_0__1_/chany_bottom_out[10] +set_disable_timing cby_0__1_/chany_top_out[10] set_disable_timing cby_0__1_/chany_bottom_out[11] set_disable_timing cby_0__1_/chany_top_out[11] set_disable_timing cby_0__1_/chany_bottom_out[12] @@ -510,44 +524,46 @@ set_disable_timing cby_0__1_/mux_right_ipin_4/in[4] # Disable timing for Connection block cby_1__1_ ################################################## set_disable_timing cby_1__1_/chany_top_in[0] +set_disable_timing cby_1__1_/chany_bottom_in[1] set_disable_timing cby_1__1_/chany_top_in[1] +set_disable_timing cby_1__1_/chany_bottom_in[2] set_disable_timing cby_1__1_/chany_top_in[2] set_disable_timing cby_1__1_/chany_bottom_in[3] set_disable_timing cby_1__1_/chany_top_in[3] +set_disable_timing cby_1__1_/chany_bottom_in[4] set_disable_timing cby_1__1_/chany_top_in[4] set_disable_timing cby_1__1_/chany_bottom_in[5] set_disable_timing cby_1__1_/chany_top_in[5] set_disable_timing cby_1__1_/chany_bottom_in[6] set_disable_timing cby_1__1_/chany_top_in[6] -set_disable_timing cby_1__1_/chany_bottom_in[7] set_disable_timing cby_1__1_/chany_top_in[7] set_disable_timing cby_1__1_/chany_bottom_in[8] set_disable_timing cby_1__1_/chany_top_in[8] set_disable_timing cby_1__1_/chany_bottom_in[9] set_disable_timing cby_1__1_/chany_top_in[9] -set_disable_timing cby_1__1_/chany_bottom_in[10] set_disable_timing cby_1__1_/chany_top_in[10] set_disable_timing cby_1__1_/chany_bottom_in[11] set_disable_timing cby_1__1_/chany_top_in[11] set_disable_timing cby_1__1_/chany_bottom_in[12] set_disable_timing cby_1__1_/chany_top_in[12] set_disable_timing cby_1__1_/chany_top_out[0] +set_disable_timing cby_1__1_/chany_bottom_out[1] set_disable_timing cby_1__1_/chany_top_out[1] +set_disable_timing cby_1__1_/chany_bottom_out[2] set_disable_timing cby_1__1_/chany_top_out[2] set_disable_timing cby_1__1_/chany_bottom_out[3] set_disable_timing cby_1__1_/chany_top_out[3] +set_disable_timing cby_1__1_/chany_bottom_out[4] set_disable_timing cby_1__1_/chany_top_out[4] set_disable_timing cby_1__1_/chany_bottom_out[5] set_disable_timing cby_1__1_/chany_top_out[5] set_disable_timing cby_1__1_/chany_bottom_out[6] set_disable_timing cby_1__1_/chany_top_out[6] -set_disable_timing cby_1__1_/chany_bottom_out[7] set_disable_timing cby_1__1_/chany_top_out[7] set_disable_timing cby_1__1_/chany_bottom_out[8] set_disable_timing cby_1__1_/chany_top_out[8] set_disable_timing cby_1__1_/chany_bottom_out[9] set_disable_timing cby_1__1_/chany_top_out[9] -set_disable_timing cby_1__1_/chany_bottom_out[10] set_disable_timing cby_1__1_/chany_top_out[10] set_disable_timing cby_1__1_/chany_bottom_out[11] set_disable_timing cby_1__1_/chany_top_out[11] @@ -557,11 +573,11 @@ set_disable_timing cby_1__1_/right_grid_left_width_0_height_0_subtile_0__pin_out set_disable_timing cby_1__1_/right_grid_left_width_0_height_0_subtile_1__pin_outpad_0_[0] set_disable_timing cby_1__1_/right_grid_left_width_0_height_0_subtile_2__pin_outpad_0_[0] set_disable_timing cby_1__1_/right_grid_left_width_0_height_0_subtile_3__pin_outpad_0_[0] +set_disable_timing cby_1__1_/right_grid_left_width_0_height_0_subtile_4__pin_outpad_0_[0] set_disable_timing cby_1__1_/right_grid_left_width_0_height_0_subtile_5__pin_outpad_0_[0] set_disable_timing cby_1__1_/right_grid_left_width_0_height_0_subtile_6__pin_outpad_0_[0] set_disable_timing cby_1__1_/right_grid_left_width_0_height_0_subtile_7__pin_outpad_0_[0] set_disable_timing cby_1__1_/left_grid_right_width_0_height_0_subtile_0__pin_I_5_[0] -set_disable_timing cby_1__1_/left_grid_right_width_0_height_0_subtile_0__pin_I_9_[0] set_disable_timing cby_1__1_/mux_left_ipin_0/in[1] set_disable_timing cby_1__1_/mux_left_ipin_1/in[1] set_disable_timing cby_1__1_/mux_left_ipin_7/in[1] @@ -570,6 +586,7 @@ set_disable_timing cby_1__1_/mux_left_ipin_1/in[0] set_disable_timing cby_1__1_/mux_left_ipin_7/in[0] set_disable_timing cby_1__1_/mux_left_ipin_1/in[3] set_disable_timing cby_1__1_/mux_left_ipin_2/in[1] +set_disable_timing cby_1__1_/mux_right_ipin_0/in[1] set_disable_timing cby_1__1_/mux_left_ipin_1/in[2] set_disable_timing cby_1__1_/mux_left_ipin_2/in[0] set_disable_timing cby_1__1_/mux_right_ipin_0/in[0] @@ -585,6 +602,7 @@ set_disable_timing cby_1__1_/mux_right_ipin_2/in[1] set_disable_timing cby_1__1_/mux_left_ipin_3/in[2] set_disable_timing cby_1__1_/mux_left_ipin_4/in[0] set_disable_timing cby_1__1_/mux_right_ipin_2/in[0] +set_disable_timing cby_1__1_/mux_left_ipin_4/in[3] set_disable_timing cby_1__1_/mux_left_ipin_5/in[1] set_disable_timing cby_1__1_/mux_left_ipin_4/in[2] set_disable_timing cby_1__1_/mux_left_ipin_5/in[0] @@ -600,7 +618,6 @@ set_disable_timing cby_1__1_/mux_left_ipin_6/in[2] set_disable_timing cby_1__1_/mux_left_ipin_7/in[2] set_disable_timing cby_1__1_/mux_left_ipin_1/in[5] set_disable_timing cby_1__1_/mux_left_ipin_7/in[5] -set_disable_timing cby_1__1_/mux_right_ipin_0/in[3] set_disable_timing cby_1__1_/mux_left_ipin_1/in[4] set_disable_timing cby_1__1_/mux_left_ipin_7/in[4] set_disable_timing cby_1__1_/mux_right_ipin_0/in[2] @@ -617,7 +634,6 @@ set_disable_timing cby_1__1_/mux_left_ipin_3/in[4] set_disable_timing cby_1__1_/mux_right_ipin_1/in[4] set_disable_timing cby_1__1_/mux_right_ipin_2/in[2] set_disable_timing cby_1__1_/mux_left_ipin_4/in[5] -set_disable_timing cby_1__1_/mux_right_ipin_2/in[5] set_disable_timing cby_1__1_/mux_left_ipin_4/in[4] set_disable_timing cby_1__1_/mux_right_ipin_2/in[4] set_disable_timing cby_1__1_/mux_left_ipin_5/in[5] @@ -635,6 +651,7 @@ set_disable_timing sb_0__0_/chany_top_out[1] set_disable_timing sb_0__0_/chany_top_in[1] set_disable_timing sb_0__0_/chany_top_out[2] set_disable_timing sb_0__0_/chany_top_in[2] +set_disable_timing sb_0__0_/chany_top_out[3] set_disable_timing sb_0__0_/chany_top_in[3] set_disable_timing sb_0__0_/chany_top_out[4] set_disable_timing sb_0__0_/chany_top_in[4] @@ -645,9 +662,11 @@ set_disable_timing sb_0__0_/chany_top_in[6] set_disable_timing sb_0__0_/chany_top_out[7] set_disable_timing sb_0__0_/chany_top_in[7] set_disable_timing sb_0__0_/chany_top_out[8] +set_disable_timing sb_0__0_/chany_top_in[8] set_disable_timing sb_0__0_/chany_top_out[9] set_disable_timing sb_0__0_/chany_top_in[9] set_disable_timing sb_0__0_/chany_top_out[10] +set_disable_timing sb_0__0_/chany_top_in[10] set_disable_timing sb_0__0_/chany_top_out[11] set_disable_timing sb_0__0_/chany_top_in[11] set_disable_timing sb_0__0_/chany_top_out[12] @@ -670,15 +689,18 @@ set_disable_timing sb_0__0_/chanx_right_out[7] set_disable_timing sb_0__0_/chanx_right_in[7] set_disable_timing sb_0__0_/chanx_right_out[8] set_disable_timing sb_0__0_/chanx_right_in[8] +set_disable_timing sb_0__0_/chanx_right_out[9] set_disable_timing sb_0__0_/chanx_right_in[9] set_disable_timing sb_0__0_/chanx_right_out[10] set_disable_timing sb_0__0_/chanx_right_in[10] +set_disable_timing sb_0__0_/chanx_right_out[11] set_disable_timing sb_0__0_/chanx_right_in[11] set_disable_timing sb_0__0_/chanx_right_out[12] set_disable_timing sb_0__0_/chanx_right_in[12] set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_1__pin_inpad_0_[0] set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_2__pin_inpad_0_[0] +set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_3__pin_inpad_0_[0] set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_5__pin_inpad_0_[0] set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_6__pin_inpad_0_[0] @@ -703,6 +725,7 @@ set_disable_timing sb_0__0_/mux_top_track_2/in[1] set_disable_timing sb_0__0_/mux_top_track_4/in[0] set_disable_timing sb_0__0_/mux_top_track_16/in[0] set_disable_timing sb_0__0_/mux_top_track_4/in[1] +set_disable_timing sb_0__0_/mux_top_track_6/in[0] set_disable_timing sb_0__0_/mux_top_track_18/in[0] set_disable_timing sb_0__0_/mux_top_track_6/in[1] set_disable_timing sb_0__0_/mux_top_track_8/in[0] @@ -752,7 +775,9 @@ set_disable_timing sb_0__0_/mux_right_track_10/in[0] set_disable_timing sb_0__0_/mux_right_track_12/in[0] set_disable_timing sb_0__0_/mux_right_track_14/in[0] set_disable_timing sb_0__0_/mux_right_track_16/in[0] +set_disable_timing sb_0__0_/mux_right_track_18/in[0] set_disable_timing sb_0__0_/mux_right_track_20/in[0] +set_disable_timing sb_0__0_/mux_right_track_22/in[0] set_disable_timing sb_0__0_/mux_right_track_24/in[0] set_disable_timing sb_0__0_/mux_right_track_0/in[0] set_disable_timing sb_0__0_/mux_top_track_24/in[2] @@ -777,6 +802,7 @@ set_disable_timing sb_0__1_/chanx_right_out[1] set_disable_timing sb_0__1_/chanx_right_out[2] set_disable_timing sb_0__1_/chanx_right_in[2] set_disable_timing sb_0__1_/chanx_right_out[3] +set_disable_timing sb_0__1_/chanx_right_in[3] set_disable_timing sb_0__1_/chanx_right_out[4] set_disable_timing sb_0__1_/chanx_right_in[4] set_disable_timing sb_0__1_/chanx_right_out[5] @@ -785,6 +811,7 @@ set_disable_timing sb_0__1_/chanx_right_out[6] set_disable_timing sb_0__1_/chanx_right_in[6] set_disable_timing sb_0__1_/chanx_right_out[7] set_disable_timing sb_0__1_/chanx_right_in[7] +set_disable_timing sb_0__1_/chanx_right_out[8] set_disable_timing sb_0__1_/chanx_right_in[8] set_disable_timing sb_0__1_/chanx_right_out[9] set_disable_timing sb_0__1_/chanx_right_in[9] @@ -800,6 +827,7 @@ set_disable_timing sb_0__1_/chany_bottom_in[1] set_disable_timing sb_0__1_/chany_bottom_out[1] set_disable_timing sb_0__1_/chany_bottom_in[2] set_disable_timing sb_0__1_/chany_bottom_out[2] +set_disable_timing sb_0__1_/chany_bottom_in[3] set_disable_timing sb_0__1_/chany_bottom_out[3] set_disable_timing sb_0__1_/chany_bottom_in[4] set_disable_timing sb_0__1_/chany_bottom_out[4] @@ -810,9 +838,11 @@ set_disable_timing sb_0__1_/chany_bottom_out[6] set_disable_timing sb_0__1_/chany_bottom_in[7] set_disable_timing sb_0__1_/chany_bottom_out[7] set_disable_timing sb_0__1_/chany_bottom_in[8] +set_disable_timing sb_0__1_/chany_bottom_out[8] set_disable_timing sb_0__1_/chany_bottom_in[9] set_disable_timing sb_0__1_/chany_bottom_out[9] set_disable_timing sb_0__1_/chany_bottom_in[10] +set_disable_timing sb_0__1_/chany_bottom_out[10] set_disable_timing sb_0__1_/chany_bottom_in[11] set_disable_timing sb_0__1_/chany_bottom_out[11] set_disable_timing sb_0__1_/chany_bottom_in[12] @@ -830,6 +860,7 @@ set_disable_timing sb_0__1_/bottom_right_grid_left_width_0_height_0_subtile_0__p set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_1__pin_inpad_0_[0] set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_2__pin_inpad_0_[0] +set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_3__pin_inpad_0_[0] set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_5__pin_inpad_0_[0] set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_6__pin_inpad_0_[0] @@ -885,7 +916,9 @@ set_disable_timing sb_0__1_/mux_bottom_track_3/in[3] set_disable_timing sb_0__1_/mux_bottom_track_15/in[3] set_disable_timing sb_0__1_/mux_bottom_track_17/in[2] set_disable_timing sb_0__1_/mux_bottom_track_23/in[0] +set_disable_timing sb_0__1_/mux_bottom_track_21/in[0] set_disable_timing sb_0__1_/mux_bottom_track_19/in[0] +set_disable_timing sb_0__1_/mux_bottom_track_17/in[0] set_disable_timing sb_0__1_/mux_bottom_track_15/in[0] set_disable_timing sb_0__1_/mux_bottom_track_13/in[0] set_disable_timing sb_0__1_/mux_bottom_track_11/in[0] @@ -898,6 +931,7 @@ set_disable_timing sb_0__1_/mux_bottom_track_25/in[0] set_disable_timing sb_0__1_/mux_right_track_22/in[1] set_disable_timing sb_0__1_/mux_right_track_20/in[1] set_disable_timing sb_0__1_/mux_right_track_18/in[1] +set_disable_timing sb_0__1_/mux_right_track_16/in[2] set_disable_timing sb_0__1_/mux_right_track_14/in[2] set_disable_timing sb_0__1_/mux_right_track_12/in[3] set_disable_timing sb_0__1_/mux_right_track_10/in[2] @@ -911,22 +945,23 @@ set_disable_timing sb_0__1_/mux_right_track_24/in[2] # Disable timing for Switch block sb_1__0_ ################################################## set_disable_timing sb_1__0_/chany_top_in[0] +set_disable_timing sb_1__0_/chany_top_out[1] set_disable_timing sb_1__0_/chany_top_in[1] +set_disable_timing sb_1__0_/chany_top_out[2] set_disable_timing sb_1__0_/chany_top_in[2] set_disable_timing sb_1__0_/chany_top_out[3] set_disable_timing sb_1__0_/chany_top_in[3] +set_disable_timing sb_1__0_/chany_top_out[4] set_disable_timing sb_1__0_/chany_top_in[4] set_disable_timing sb_1__0_/chany_top_out[5] set_disable_timing sb_1__0_/chany_top_in[5] set_disable_timing sb_1__0_/chany_top_out[6] set_disable_timing sb_1__0_/chany_top_in[6] -set_disable_timing sb_1__0_/chany_top_out[7] set_disable_timing sb_1__0_/chany_top_in[7] set_disable_timing sb_1__0_/chany_top_out[8] set_disable_timing sb_1__0_/chany_top_in[8] set_disable_timing sb_1__0_/chany_top_out[9] set_disable_timing sb_1__0_/chany_top_in[9] -set_disable_timing sb_1__0_/chany_top_out[10] set_disable_timing sb_1__0_/chany_top_in[10] set_disable_timing sb_1__0_/chany_top_out[11] set_disable_timing sb_1__0_/chany_top_in[11] @@ -950,19 +985,20 @@ set_disable_timing sb_1__0_/chanx_left_in[7] set_disable_timing sb_1__0_/chanx_left_out[7] set_disable_timing sb_1__0_/chanx_left_in[8] set_disable_timing sb_1__0_/chanx_left_out[8] +set_disable_timing sb_1__0_/chanx_left_in[9] set_disable_timing sb_1__0_/chanx_left_out[9] set_disable_timing sb_1__0_/chanx_left_in[10] set_disable_timing sb_1__0_/chanx_left_out[10] +set_disable_timing sb_1__0_/chanx_left_in[11] set_disable_timing sb_1__0_/chanx_left_out[11] set_disable_timing sb_1__0_/chanx_left_in[12] set_disable_timing sb_1__0_/chanx_left_out[12] set_disable_timing sb_1__0_/top_right_grid_left_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_1__0_/top_right_grid_left_width_0_height_0_subtile_1__pin_inpad_0_[0] set_disable_timing sb_1__0_/top_right_grid_left_width_0_height_0_subtile_2__pin_inpad_0_[0] -set_disable_timing sb_1__0_/top_right_grid_left_width_0_height_0_subtile_3__pin_inpad_0_[0] set_disable_timing sb_1__0_/top_right_grid_left_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_1__0_/top_right_grid_left_width_0_height_0_subtile_5__pin_inpad_0_[0] -set_disable_timing sb_1__0_/top_right_grid_left_width_0_height_0_subtile_6__pin_inpad_0_[0] +set_disable_timing sb_1__0_/top_right_grid_left_width_0_height_0_subtile_7__pin_inpad_0_[0] set_disable_timing sb_1__0_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_0_[0] set_disable_timing sb_1__0_/left_bottom_grid_top_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_1__0_/left_bottom_grid_top_width_0_height_0_subtile_1__pin_inpad_0_[0] @@ -983,7 +1019,6 @@ set_disable_timing sb_1__0_/mux_top_track_6/in[0] set_disable_timing sb_1__0_/mux_top_track_18/in[0] set_disable_timing sb_1__0_/mux_top_track_6/in[1] set_disable_timing sb_1__0_/mux_top_track_8/in[0] -set_disable_timing sb_1__0_/mux_top_track_20/in[0] set_disable_timing sb_1__0_/mux_top_track_8/in[1] set_disable_timing sb_1__0_/mux_top_track_10/in[0] set_disable_timing sb_1__0_/mux_top_track_22/in[0] @@ -992,7 +1027,7 @@ set_disable_timing sb_1__0_/mux_top_track_12/in[0] set_disable_timing sb_1__0_/mux_top_track_24/in[0] set_disable_timing sb_1__0_/mux_top_track_0/in[2] set_disable_timing sb_1__0_/mux_top_track_12/in[1] -set_disable_timing sb_1__0_/mux_top_track_14/in[1] +set_disable_timing sb_1__0_/mux_top_track_2/in[2] set_disable_timing sb_1__0_/mux_top_track_14/in[2] set_disable_timing sb_1__0_/mux_top_track_16/in[1] set_disable_timing sb_1__0_/mux_left_track_1/in[1] @@ -1044,28 +1079,31 @@ set_disable_timing sb_1__0_/mux_top_track_16/in[2] set_disable_timing sb_1__0_/mux_top_track_14/in[3] set_disable_timing sb_1__0_/mux_top_track_12/in[2] set_disable_timing sb_1__0_/mux_top_track_10/in[2] +set_disable_timing sb_1__0_/mux_top_track_8/in[2] set_disable_timing sb_1__0_/mux_top_track_6/in[2] +set_disable_timing sb_1__0_/mux_top_track_4/in[2] set_disable_timing sb_1__0_/mux_top_track_2/in[3] ################################################## # Disable timing for Switch block sb_1__1_ ################################################## set_disable_timing sb_1__1_/chany_bottom_out[0] +set_disable_timing sb_1__1_/chany_bottom_in[1] set_disable_timing sb_1__1_/chany_bottom_out[1] +set_disable_timing sb_1__1_/chany_bottom_in[2] set_disable_timing sb_1__1_/chany_bottom_out[2] set_disable_timing sb_1__1_/chany_bottom_in[3] set_disable_timing sb_1__1_/chany_bottom_out[3] +set_disable_timing sb_1__1_/chany_bottom_in[4] set_disable_timing sb_1__1_/chany_bottom_out[4] set_disable_timing sb_1__1_/chany_bottom_in[5] set_disable_timing sb_1__1_/chany_bottom_out[5] set_disable_timing sb_1__1_/chany_bottom_in[6] set_disable_timing sb_1__1_/chany_bottom_out[6] -set_disable_timing sb_1__1_/chany_bottom_in[7] set_disable_timing sb_1__1_/chany_bottom_out[7] set_disable_timing sb_1__1_/chany_bottom_in[8] set_disable_timing sb_1__1_/chany_bottom_out[8] set_disable_timing sb_1__1_/chany_bottom_in[9] set_disable_timing sb_1__1_/chany_bottom_out[9] -set_disable_timing sb_1__1_/chany_bottom_in[10] set_disable_timing sb_1__1_/chany_bottom_out[10] set_disable_timing sb_1__1_/chany_bottom_in[11] set_disable_timing sb_1__1_/chany_bottom_out[11] @@ -1077,6 +1115,7 @@ set_disable_timing sb_1__1_/chanx_left_in[1] set_disable_timing sb_1__1_/chanx_left_in[2] set_disable_timing sb_1__1_/chanx_left_out[2] set_disable_timing sb_1__1_/chanx_left_in[3] +set_disable_timing sb_1__1_/chanx_left_out[3] set_disable_timing sb_1__1_/chanx_left_in[4] set_disable_timing sb_1__1_/chanx_left_out[4] set_disable_timing sb_1__1_/chanx_left_in[5] @@ -1085,6 +1124,7 @@ set_disable_timing sb_1__1_/chanx_left_in[6] set_disable_timing sb_1__1_/chanx_left_out[6] set_disable_timing sb_1__1_/chanx_left_in[7] set_disable_timing sb_1__1_/chanx_left_out[7] +set_disable_timing sb_1__1_/chanx_left_in[8] set_disable_timing sb_1__1_/chanx_left_out[8] set_disable_timing sb_1__1_/chanx_left_in[9] set_disable_timing sb_1__1_/chanx_left_out[9] @@ -1097,10 +1137,9 @@ set_disable_timing sb_1__1_/chanx_left_out[12] set_disable_timing sb_1__1_/bottom_right_grid_left_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_1__1_/bottom_right_grid_left_width_0_height_0_subtile_1__pin_inpad_0_[0] set_disable_timing sb_1__1_/bottom_right_grid_left_width_0_height_0_subtile_2__pin_inpad_0_[0] -set_disable_timing sb_1__1_/bottom_right_grid_left_width_0_height_0_subtile_3__pin_inpad_0_[0] set_disable_timing sb_1__1_/bottom_right_grid_left_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_1__1_/bottom_right_grid_left_width_0_height_0_subtile_5__pin_inpad_0_[0] -set_disable_timing sb_1__1_/bottom_right_grid_left_width_0_height_0_subtile_6__pin_inpad_0_[0] +set_disable_timing sb_1__1_/bottom_right_grid_left_width_0_height_0_subtile_7__pin_inpad_0_[0] set_disable_timing sb_1__1_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_1__1_/left_top_grid_bottom_width_0_height_0_subtile_1__pin_inpad_0_[0] set_disable_timing sb_1__1_/left_top_grid_bottom_width_0_height_0_subtile_2__pin_inpad_0_[0] @@ -1161,6 +1200,7 @@ set_disable_timing sb_1__1_/mux_left_track_13/in[3] set_disable_timing sb_1__1_/mux_left_track_15/in[2] set_disable_timing sb_1__1_/mux_left_track_17/in[2] set_disable_timing sb_1__1_/mux_left_track_5/in[0] +set_disable_timing sb_1__1_/mux_left_track_7/in[0] set_disable_timing sb_1__1_/mux_left_track_9/in[0] set_disable_timing sb_1__1_/mux_left_track_11/in[0] set_disable_timing sb_1__1_/mux_left_track_13/in[0] @@ -1193,6 +1233,7 @@ set_disable_timing sb_1__1_/mux_bottom_track_23/in[1] ####################################### # Disable unused pins for pb_graph_node clb[0] ####################################### +set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_I[0] set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_I[2] set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_I[3] set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_I[4] @@ -1200,7 +1241,6 @@ set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_I[5] set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_I[6] set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_I[7] set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_I[8] -set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_I[9] set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_O[0] set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_O[1] set_disable_timing grid_clb_1__1_/logical_tile_clb_mode_clb__0/clb_O[2] @@ -1426,16 +1466,20 @@ set_disable_timing grid_io_top_1__2_/logical_tile_io_mode_io__0/* ####################################### set_disable_timing grid_io_top_1__2_/logical_tile_io_mode_io__0/logical_tile_io_mode_physical__iopad_0/* ####################################### -# Disable Timing for unused grid[1][2][1] +# Disable Timing for unused resources in grid[1][2][1] ####################################### ####################################### -# Disable all the ports for pb_graph_node io[0] +# Disable unused pins for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_top_1__2_/logical_tile_io_mode_io__1/* +set_disable_timing grid_io_top_1__2_/logical_tile_io_mode_io__1/io_inpad[0] ####################################### -# Disable all the ports for pb_graph_node iopad[0] +# Disable unused mux_inputs for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_top_1__2_/logical_tile_io_mode_io__1/logical_tile_io_mode_physical__iopad_0/* +set_disable_timing grid_io_top_1__2_/logical_tile_io_mode_io__1//direct_interc_0_/in[0] +####################################### +# Disable unused pins for pb_graph_node iopad[0] +####################################### +set_disable_timing grid_io_top_1__2_/logical_tile_io_mode_io__1/logical_tile_io_mode_physical__iopad_0/iopad_inpad[0] ####################################### # Disable Timing for unused grid[1][2][2] ####################################### @@ -1539,31 +1583,31 @@ set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__2/* ####################################### set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__2/logical_tile_io_mode_physical__iopad_0/* ####################################### -# Disable Timing for unused grid[2][1][3] -####################################### -####################################### -# Disable all the ports for pb_graph_node io[0] -####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__3/* -####################################### -# Disable all the ports for pb_graph_node iopad[0] -####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__3/logical_tile_io_mode_physical__iopad_0/* -####################################### -# Disable Timing for unused resources in grid[2][1][4] +# Disable Timing for unused resources in grid[2][1][3] ####################################### ####################################### # Disable unused pins for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__4/io_inpad[0] +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__3/io_outpad[0] ####################################### # Disable unused mux_inputs for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__4//direct_interc_0_/in[0] +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__3//direct_interc_1_/in[0] ####################################### # Disable unused pins for pb_graph_node iopad[0] ####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__4/logical_tile_io_mode_physical__iopad_0/iopad_inpad[0] +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__3/logical_tile_io_mode_physical__iopad_0/iopad_outpad[0] +####################################### +# Disable Timing for unused grid[2][1][4] +####################################### +####################################### +# Disable all the ports for pb_graph_node io[0] +####################################### +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__4/* +####################################### +# Disable all the ports for pb_graph_node iopad[0] +####################################### +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__4/logical_tile_io_mode_physical__iopad_0/* ####################################### # Disable Timing for unused grid[2][1][5] ####################################### @@ -1576,31 +1620,31 @@ set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__5/* ####################################### set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__5/logical_tile_io_mode_physical__iopad_0/* ####################################### -# Disable Timing for unused grid[2][1][6] -####################################### -####################################### -# Disable all the ports for pb_graph_node io[0] -####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__6/* -####################################### -# Disable all the ports for pb_graph_node iopad[0] -####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__6/logical_tile_io_mode_physical__iopad_0/* -####################################### -# Disable Timing for unused resources in grid[2][1][7] +# Disable Timing for unused resources in grid[2][1][6] ####################################### ####################################### # Disable unused pins for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__7/io_outpad[0] +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__6/io_outpad[0] ####################################### # Disable unused mux_inputs for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__7//direct_interc_1_/in[0] +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__6//direct_interc_1_/in[0] ####################################### # Disable unused pins for pb_graph_node iopad[0] ####################################### -set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__7/logical_tile_io_mode_physical__iopad_0/iopad_outpad[0] +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__6/logical_tile_io_mode_physical__iopad_0/iopad_outpad[0] +####################################### +# Disable Timing for unused grid[2][1][7] +####################################### +####################################### +# Disable all the ports for pb_graph_node io[0] +####################################### +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__7/* +####################################### +# Disable all the ports for pb_graph_node iopad[0] +####################################### +set_disable_timing grid_io_right_2__1_/logical_tile_io_mode_io__7/logical_tile_io_mode_physical__iopad_0/* ####################################### # Disable Timing for grid[1][0] ####################################### @@ -1729,20 +1773,16 @@ set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__2/* ####################################### set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__2/logical_tile_io_mode_physical__iopad_0/* ####################################### -# Disable Timing for unused resources in grid[0][1][3] +# Disable Timing for unused grid[0][1][3] ####################################### ####################################### -# Disable unused pins for pb_graph_node io[0] +# Disable all the ports for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__3/io_outpad[0] +set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__3/* ####################################### -# Disable unused mux_inputs for pb_graph_node io[0] +# Disable all the ports for pb_graph_node iopad[0] ####################################### -set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__3//direct_interc_1_/in[0] -####################################### -# Disable unused pins for pb_graph_node iopad[0] -####################################### -set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__3/logical_tile_io_mode_physical__iopad_0/iopad_outpad[0] +set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__3/logical_tile_io_mode_physical__iopad_0/* ####################################### # Disable Timing for unused grid[0][1][4] ####################################### diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_top_formal_verification.v b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_top_formal_verification.v index 237dad23a..35b9564df 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_top_formal_verification.v +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/and2_top_formal_verification.v @@ -42,18 +42,17 @@ wire [0:0] clk_fm; // ----- End Connect Global ports of FPGA top module ----- // ----- Link BLIF Benchmark I/Os to FPGA I/Os ----- -// ----- Blif Benchmark input a is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[27] ----- - assign gfpga_pad_GPIO_PAD_fm[27] = a[0]; +// ----- Blif Benchmark input a is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[11] ----- + assign gfpga_pad_GPIO_PAD_fm[11] = a[0]; -// ----- Blif Benchmark input b is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[15] ----- - assign gfpga_pad_GPIO_PAD_fm[15] = b[0]; +// ----- Blif Benchmark input b is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[14] ----- + assign gfpga_pad_GPIO_PAD_fm[14] = b[0]; -// ----- Blif Benchmark output c is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[12] ----- - assign c[0] = gfpga_pad_GPIO_PAD_fm[12]; +// ----- Blif Benchmark output c is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[1] ----- + assign c[0] = gfpga_pad_GPIO_PAD_fm[1]; // ----- Wire unused FPGA I/Os to constants ----- assign gfpga_pad_GPIO_PAD_fm[0] = 1'b0; - assign gfpga_pad_GPIO_PAD_fm[1] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[2] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[3] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[4] = 1'b0; @@ -63,9 +62,9 @@ wire [0:0] clk_fm; assign gfpga_pad_GPIO_PAD_fm[8] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[9] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[10] = 1'b0; - assign gfpga_pad_GPIO_PAD_fm[11] = 1'b0; + assign gfpga_pad_GPIO_PAD_fm[12] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[13] = 1'b0; - assign gfpga_pad_GPIO_PAD_fm[14] = 1'b0; + assign gfpga_pad_GPIO_PAD_fm[15] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[16] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[17] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[18] = 1'b0; @@ -77,6 +76,7 @@ wire [0:0] clk_fm; assign gfpga_pad_GPIO_PAD_fm[24] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[25] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[26] = 1'b0; + assign gfpga_pad_GPIO_PAD_fm[27] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[28] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[29] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[30] = 1'b0; @@ -125,8 +125,8 @@ initial begin force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_2_in_2.mem_outb[0:3] = {4{1'b1}}; force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_2_in_3.mem_out[0:3] = {4{1'b0}}; force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_2_in_3.mem_outb[0:3] = {4{1'b1}}; - force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_0.mem_out[0:3] = {4{1'b1}}; - force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_0.mem_outb[0:3] = {4{1'b0}}; + force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_0.mem_out[0:3] = 4'b0110; + force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_0.mem_outb[0:3] = 4'b1001; force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_out[0:3] = {4{1'b0}}; force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_outb[0:3] = {4{1'b1}}; force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_2.mem_out[0:3] = {4{1'b0}}; @@ -135,8 +135,8 @@ initial begin force U0_formal_verification.grid_clb_1__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_3.mem_outb[0:3] = 4'b1000; force U0_formal_verification.grid_io_top_1__2_.logical_tile_io_mode_io__0.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b1; force U0_formal_verification.grid_io_top_1__2_.logical_tile_io_mode_io__0.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_outb[0] = 1'b0; - force U0_formal_verification.grid_io_top_1__2_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b1; - force U0_formal_verification.grid_io_top_1__2_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_outb[0] = 1'b0; + force U0_formal_verification.grid_io_top_1__2_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b0; + force U0_formal_verification.grid_io_top_1__2_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_outb[0] = 1'b1; force U0_formal_verification.grid_io_top_1__2_.logical_tile_io_mode_io__2.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b1; force U0_formal_verification.grid_io_top_1__2_.logical_tile_io_mode_io__2.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_outb[0] = 1'b0; force U0_formal_verification.grid_io_top_1__2_.logical_tile_io_mode_io__3.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b1; @@ -157,8 +157,8 @@ initial begin force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__2.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_outb[0] = 1'b0; force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__3.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b1; force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__3.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_outb[0] = 1'b0; - force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__4.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b0; - force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__4.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_outb[0] = 1'b1; + force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__4.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b1; + force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__4.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_outb[0] = 1'b0; force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__5.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b1; force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__5.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_outb[0] = 1'b0; force U0_formal_verification.grid_io_right_2__1_.logical_tile_io_mode_io__6.logical_tile_io_mode_physical__iopad_0.GPIO_DFF_mem.mem_out[0] = 1'b1; @@ -203,8 +203,8 @@ initial begin force U0_formal_verification.sb_0__0_.mem_top_track_2.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__0_.mem_top_track_4.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__0_.mem_top_track_4.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__0_.mem_top_track_6.mem_out[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__0_.mem_top_track_6.mem_outb[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__0_.mem_top_track_6.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__0_.mem_top_track_6.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__0_.mem_top_track_8.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__0_.mem_top_track_8.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__0_.mem_top_track_10.mem_out[0:1] = {2{1'b0}}; @@ -241,12 +241,12 @@ initial begin force U0_formal_verification.sb_0__0_.mem_right_track_14.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.sb_0__0_.mem_right_track_16.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__0_.mem_right_track_16.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__0_.mem_right_track_18.mem_out[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__0_.mem_right_track_18.mem_outb[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__0_.mem_right_track_18.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__0_.mem_right_track_18.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__0_.mem_right_track_20.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__0_.mem_right_track_20.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__0_.mem_right_track_22.mem_out[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__0_.mem_right_track_22.mem_outb[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__0_.mem_right_track_22.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__0_.mem_right_track_22.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__0_.mem_right_track_24.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__0_.mem_right_track_24.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__1_.mem_right_track_0.mem_out[0:2] = {3{1'b0}}; @@ -265,8 +265,8 @@ initial begin force U0_formal_verification.sb_0__1_.mem_right_track_12.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.sb_0__1_.mem_right_track_14.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__1_.mem_right_track_14.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__1_.mem_right_track_16.mem_out[0:1] = 2'b10; - force U0_formal_verification.sb_0__1_.mem_right_track_16.mem_outb[0:1] = 2'b01; + force U0_formal_verification.sb_0__1_.mem_right_track_16.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__1_.mem_right_track_16.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__1_.mem_right_track_18.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__1_.mem_right_track_18.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__1_.mem_right_track_20.mem_out[0:1] = {2{1'b0}}; @@ -291,38 +291,38 @@ initial begin force U0_formal_verification.sb_0__1_.mem_bottom_track_13.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__1_.mem_bottom_track_15.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.sb_0__1_.mem_bottom_track_15.mem_outb[0:2] = {3{1'b1}}; - force U0_formal_verification.sb_0__1_.mem_bottom_track_17.mem_out[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__1_.mem_bottom_track_17.mem_outb[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__1_.mem_bottom_track_17.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__1_.mem_bottom_track_17.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__1_.mem_bottom_track_19.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__1_.mem_bottom_track_19.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__1_.mem_bottom_track_21.mem_out[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__1_.mem_bottom_track_21.mem_outb[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__1_.mem_bottom_track_21.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__1_.mem_bottom_track_21.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__1_.mem_bottom_track_23.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__1_.mem_bottom_track_23.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__1_.mem_bottom_track_25.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__1_.mem_bottom_track_25.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_1__0_.mem_top_track_0.mem_out[0:2] = {3{1'b1}}; force U0_formal_verification.sb_1__0_.mem_top_track_0.mem_outb[0:2] = {3{1'b0}}; - force U0_formal_verification.sb_1__0_.mem_top_track_2.mem_out[0:2] = 3'b001; - force U0_formal_verification.sb_1__0_.mem_top_track_2.mem_outb[0:2] = 3'b110; - force U0_formal_verification.sb_1__0_.mem_top_track_4.mem_out[0:1] = 2'b10; - force U0_formal_verification.sb_1__0_.mem_top_track_4.mem_outb[0:1] = 2'b01; + force U0_formal_verification.sb_1__0_.mem_top_track_2.mem_out[0:2] = {3{1'b0}}; + force U0_formal_verification.sb_1__0_.mem_top_track_2.mem_outb[0:2] = {3{1'b1}}; + force U0_formal_verification.sb_1__0_.mem_top_track_4.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_1__0_.mem_top_track_4.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_1__0_.mem_top_track_6.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__0_.mem_top_track_6.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_1__0_.mem_top_track_8.mem_out[0:1] = 2'b10; - force U0_formal_verification.sb_1__0_.mem_top_track_8.mem_outb[0:1] = 2'b01; + force U0_formal_verification.sb_1__0_.mem_top_track_8.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_1__0_.mem_top_track_8.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_1__0_.mem_top_track_10.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__0_.mem_top_track_10.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_1__0_.mem_top_track_12.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__0_.mem_top_track_12.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_1__0_.mem_top_track_14.mem_out[0:2] = {3{1'b0}}; - force U0_formal_verification.sb_1__0_.mem_top_track_14.mem_outb[0:2] = {3{1'b1}}; + force U0_formal_verification.sb_1__0_.mem_top_track_14.mem_out[0:2] = 3'b011; + force U0_formal_verification.sb_1__0_.mem_top_track_14.mem_outb[0:2] = 3'b100; force U0_formal_verification.sb_1__0_.mem_top_track_16.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__0_.mem_top_track_16.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_1__0_.mem_top_track_18.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__0_.mem_top_track_18.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_1__0_.mem_top_track_20.mem_out[0:1] = {2{1'b0}}; - force U0_formal_verification.sb_1__0_.mem_top_track_20.mem_outb[0:1] = {2{1'b1}}; + force U0_formal_verification.sb_1__0_.mem_top_track_20.mem_out[0:1] = {2{1'b1}}; + force U0_formal_verification.sb_1__0_.mem_top_track_20.mem_outb[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__0_.mem_top_track_22.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__0_.mem_top_track_22.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_1__0_.mem_top_track_24.mem_out[0:1] = {2{1'b0}}; @@ -385,8 +385,8 @@ initial begin force U0_formal_verification.sb_1__1_.mem_left_track_3.mem_outb[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__1_.mem_left_track_5.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__1_.mem_left_track_5.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_1__1_.mem_left_track_7.mem_out[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_1__1_.mem_left_track_7.mem_outb[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_1__1_.mem_left_track_7.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_1__1_.mem_left_track_7.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_1__1_.mem_left_track_9.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_1__1_.mem_left_track_9.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_1__1_.mem_left_track_11.mem_out[0:1] = {2{1'b0}}; @@ -429,8 +429,8 @@ initial begin force U0_formal_verification.cbx_1__0_.mem_top_ipin_7.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_0.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_0.mem_outb[0:2] = {3{1'b1}}; - force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_1.mem_out[0:2] = {3{1'b0}}; - force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_1.mem_outb[0:2] = {3{1'b1}}; + force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_1.mem_out[0:2] = 3'b001; + force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_1.mem_outb[0:2] = 3'b110; force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_2.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_2.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_3.mem_out[0:2] = {3{1'b0}}; @@ -443,8 +443,8 @@ initial begin force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_6.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_7.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.cbx_1__1_.mem_bottom_ipin_7.mem_outb[0:2] = {3{1'b1}}; - force U0_formal_verification.cbx_1__1_.mem_top_ipin_0.mem_out[0:2] = 3'b110; - force U0_formal_verification.cbx_1__1_.mem_top_ipin_0.mem_outb[0:2] = 3'b001; + force U0_formal_verification.cbx_1__1_.mem_top_ipin_0.mem_out[0:2] = {3{1'b0}}; + force U0_formal_verification.cbx_1__1_.mem_top_ipin_0.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.cbx_1__1_.mem_top_ipin_1.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.cbx_1__1_.mem_top_ipin_1.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.cbx_1__1_.mem_top_ipin_2.mem_out[0:2] = {3{1'b0}}; @@ -477,20 +477,20 @@ initial begin force U0_formal_verification.cby_1__1_.mem_left_ipin_2.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.cby_1__1_.mem_left_ipin_3.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.cby_1__1_.mem_left_ipin_3.mem_outb[0:2] = {3{1'b1}}; - force U0_formal_verification.cby_1__1_.mem_left_ipin_4.mem_out[0:2] = 3'b101; - force U0_formal_verification.cby_1__1_.mem_left_ipin_4.mem_outb[0:2] = 3'b010; + force U0_formal_verification.cby_1__1_.mem_left_ipin_4.mem_out[0:2] = {3{1'b0}}; + force U0_formal_verification.cby_1__1_.mem_left_ipin_4.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.cby_1__1_.mem_left_ipin_5.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.cby_1__1_.mem_left_ipin_5.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.cby_1__1_.mem_left_ipin_6.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.cby_1__1_.mem_left_ipin_6.mem_outb[0:2] = {3{1'b1}}; force U0_formal_verification.cby_1__1_.mem_left_ipin_7.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.cby_1__1_.mem_left_ipin_7.mem_outb[0:2] = {3{1'b1}}; - force U0_formal_verification.cby_1__1_.mem_right_ipin_0.mem_out[0:2] = {3{1'b1}}; - force U0_formal_verification.cby_1__1_.mem_right_ipin_0.mem_outb[0:2] = {3{1'b0}}; + force U0_formal_verification.cby_1__1_.mem_right_ipin_0.mem_out[0:2] = 3'b101; + force U0_formal_verification.cby_1__1_.mem_right_ipin_0.mem_outb[0:2] = 3'b010; force U0_formal_verification.cby_1__1_.mem_right_ipin_1.mem_out[0:2] = {3{1'b0}}; force U0_formal_verification.cby_1__1_.mem_right_ipin_1.mem_outb[0:2] = {3{1'b1}}; - force U0_formal_verification.cby_1__1_.mem_right_ipin_2.mem_out[0:2] = {3{1'b0}}; - force U0_formal_verification.cby_1__1_.mem_right_ipin_2.mem_outb[0:2] = {3{1'b1}}; + force U0_formal_verification.cby_1__1_.mem_right_ipin_2.mem_out[0:2] = 3'b110; + force U0_formal_verification.cby_1__1_.mem_right_ipin_2.mem_outb[0:2] = 3'b001; end // ----- End assign bitstream to configuration memories ----- // ----- End load bitstream to configuration memories ----- diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_bitstream.bit b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_bitstream.bit index 7ed88111a..3387708eb 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_bitstream.bit +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_bitstream.bit @@ -13,10 +13,10 @@ 0 0 0 +0 1 1 -1 -1 +0 0 0 0 @@ -138,13 +138,13 @@ 0 0 0 +1 +1 0 0 0 -0 -0 -1 1 +0 1 0 0 @@ -155,9 +155,7 @@ 0 0 0 -1 0 -1 0 0 0 @@ -239,10 +237,15 @@ 0 0 0 +1 +1 0 0 0 0 +1 +1 +0 0 0 0 @@ -251,12 +254,9 @@ 0 0 0 -1 0 0 0 -1 -1 0 0 1 @@ -302,12 +302,8 @@ 0 0 0 -1 -1 0 0 -1 -1 0 0 0 @@ -349,8 +345,6 @@ 0 0 0 -1 -1 0 0 0 @@ -362,12 +356,8 @@ 0 0 0 -1 -1 0 0 -1 -1 0 0 0 @@ -396,7 +386,17 @@ 0 0 0 -1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 0 0 0 @@ -421,7 +421,7 @@ 1 1 1 -1 +0 1 0 0 @@ -430,8 +430,6 @@ 0 0 0 -1 -1 0 0 0 @@ -452,6 +450,10 @@ 0 0 0 +1 +0 +0 +0 0 0 0 @@ -475,8 +477,6 @@ 0 0 0 -1 -1 0 0 1 @@ -515,7 +515,7 @@ 1 1 1 -0 +1 1 1 1 diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_bitstream.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_bitstream.xml index 419917847..4edf9cf2b 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_bitstream.xml +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_bitstream.xml @@ -30,13 +30,13 @@ - + - + @@ -280,9 +280,9 @@ - + - + @@ -292,7 +292,7 @@ - + @@ -314,11 +314,11 @@ - + - + @@ -478,9 +478,9 @@ - + - + @@ -490,9 +490,9 @@ - + - + @@ -506,7 +506,7 @@ - + @@ -514,9 +514,9 @@ - + - + @@ -608,17 +608,17 @@ - + - + - + - + @@ -702,9 +702,9 @@ - + - + @@ -728,17 +728,17 @@ - + - + - + - + @@ -796,7 +796,7 @@ - + @@ -846,7 +846,7 @@ - + @@ -864,9 +864,9 @@ - + - + @@ -904,7 +904,7 @@ - + @@ -954,9 +954,9 @@ - + - + @@ -1034,7 +1034,7 @@ - + diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_independent_bitstream.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_independent_bitstream.xml index eddb1a906..1b1ecfa0d 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_independent_bitstream.xml +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_independent_bitstream.xml @@ -431,7 +431,7 @@ - + @@ -440,7 +440,7 @@ - + @@ -449,11 +449,11 @@ - - + + - + @@ -498,7 +498,7 @@ - + @@ -507,7 +507,7 @@ - + @@ -553,7 +553,7 @@ - + @@ -731,7 +731,7 @@ - + @@ -1094,7 +1094,7 @@ - + @@ -1112,16 +1112,16 @@ - + - + - - - + + + @@ -1228,7 +1228,7 @@ - + @@ -1480,15 +1480,15 @@ - + - + - - - + + + @@ -1516,15 +1516,15 @@ - + - + - - - + + + @@ -1713,13 +1713,13 @@ - + - + - - + + @@ -1866,7 +1866,7 @@ - + @@ -1884,7 +1884,7 @@ - + @@ -1961,16 +1961,16 @@ - + - + - - - + + + @@ -1999,14 +1999,14 @@ - + - + - - - + + + @@ -2056,7 +2056,7 @@ - + @@ -2077,16 +2077,16 @@ - + - + - + - + @@ -2098,13 +2098,13 @@ - + - + - - + + @@ -2116,7 +2116,7 @@ - + @@ -2134,15 +2134,15 @@ - + - + - + - - + + @@ -2173,7 +2173,7 @@ - + @@ -2192,17 +2192,17 @@ - - + + - + - + - - + + @@ -2213,7 +2213,7 @@ - + @@ -2249,15 +2249,15 @@ - + - + - - - + + + @@ -2559,7 +2559,7 @@ - + @@ -2598,7 +2598,7 @@ - + @@ -2616,7 +2616,7 @@ - + @@ -2655,7 +2655,7 @@ - + @@ -2674,8 +2674,8 @@ - - + + @@ -2695,8 +2695,8 @@ - - + + @@ -2732,7 +2732,7 @@ - + @@ -2787,7 +2787,7 @@ - + @@ -2845,7 +2845,7 @@ - + @@ -2864,16 +2864,16 @@ - + - + - - - + + + @@ -2902,7 +2902,7 @@ - + @@ -2961,7 +2961,7 @@ - + @@ -3016,7 +3016,7 @@ - + @@ -3128,7 +3128,7 @@ - + @@ -3174,7 +3174,7 @@ - + @@ -3266,7 +3266,7 @@ - + @@ -3287,7 +3287,7 @@ - + @@ -3341,12 +3341,12 @@ - + - + - + @@ -3360,7 +3360,7 @@ - + @@ -3382,7 +3382,7 @@ - + @@ -3403,7 +3403,7 @@ - + @@ -3498,15 +3498,15 @@ - + - + - - - + + + @@ -3519,7 +3519,7 @@ - + @@ -3541,7 +3541,7 @@ - + @@ -3616,7 +3616,7 @@ - + @@ -3636,7 +3636,7 @@ - + @@ -3657,12 +3657,12 @@ - + - + @@ -3754,7 +3754,7 @@ - + @@ -3775,7 +3775,7 @@ - + @@ -3822,9 +3822,9 @@ - + - + @@ -3843,9 +3843,9 @@ - + - + @@ -3866,7 +3866,7 @@ - + @@ -3891,18 +3891,18 @@ - + - + - + - - + + - + @@ -3912,7 +3912,7 @@ - + @@ -3962,7 +3962,7 @@ - + @@ -3981,9 +3981,9 @@ - + - + @@ -3991,9 +3991,9 @@ - + - + @@ -4004,7 +4004,7 @@ - + @@ -4031,15 +4031,15 @@ - + - + - - - + + + diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_netlists.v b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_netlists.v index 662174af0..2b7055cd8 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_netlists.v +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/fabric_netlists.v @@ -48,6 +48,8 @@ `include "routing/cby_0__1_.v" `include "routing/cby_1__1_.v" +// ------ Include tile module netlists ----- + // ------ Include fabric top-level netlists ----- `include "fpga_top.v" diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/global_ports.sdc b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/global_ports.sdc index 7b26126b2..0cf7373f8 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/global_ports.sdc +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/global_ports.sdc @@ -14,7 +14,7 @@ set_units -time s ################################################## # Create clock ################################################## -create_clock -name clk[0] -period 1.525308102e-09 -waveform {0 7.62654051e-10} [get_ports {clk[0]}] +create_clock -name clk[0] -period 9.25781396e-10 -waveform {0 4.62890698e-10} [get_ports {clk[0]}] ################################################## # Create programmable clock ################################################## diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/pin_mapping.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/pin_mapping.xml index e39c498fe..89523007a 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/pin_mapping.xml +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_1x1/golden_outputs_no_time_stamp/pin_mapping.xml @@ -3,7 +3,7 @@ --> - - - + + + diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_4x4/golden_outputs_no_time_stamp/fabric_netlists.v b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_4x4/golden_outputs_no_time_stamp/fabric_netlists.v index 2eac9b4f9..130506763 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/device_4x4/golden_outputs_no_time_stamp/fabric_netlists.v +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/device_4x4/golden_outputs_no_time_stamp/fabric_netlists.v @@ -55,6 +55,8 @@ `include "routing/cby_1__1_.v" `include "routing/cby_4__1_.v" +// ------ Include tile module netlists ----- + // ------ Include fabric top-level netlists ----- `include "fpga_top.v" diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_formal_random_top_tb.v b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_formal_random_top_tb.v index c6df32c2a..59580560b 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_formal_random_top_tb.v +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_formal_random_top_tb.v @@ -50,7 +50,7 @@ module and2_top_formal_verification_random_tb; initial begin clk[0] <= 1'b0; while(1) begin - #0.4485172927 + #0.4866067469 clk[0] <= !clk[0]; end end @@ -109,7 +109,7 @@ initial begin $timeformat(-9, 2, "ns", 20); $display("Simulation start"); // ----- Can be changed by the user for his/her need ------- - #6.279242039 + #6.812494755 if(nb_error == 0) begin $display("Simulation Succeed"); end else begin diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_fpga_top_analysis.sdc b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_fpga_top_analysis.sdc index 0ab31beb3..73d00c19f 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_fpga_top_analysis.sdc +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_fpga_top_analysis.sdc @@ -9,14 +9,14 @@ ################################################## # Create clock ################################################## -create_clock clk[0] -period 8.970345577e-10 -waveform {0 4.485172789e-10} +create_clock clk[0] -period 9.732135098e-10 -waveform {0 4.866067549e-10} ################################################## # Create input and output delays for used I/Os ################################################## -set_input_delay -clock clk[0] -max 8.970345577e-10 gfpga_pad_GPIO_PAD[39] -set_input_delay -clock clk[0] -max 8.970345577e-10 gfpga_pad_GPIO_PAD[48] -set_output_delay -clock clk[0] -max 8.970345577e-10 gfpga_pad_GPIO_PAD[34] +set_input_delay -clock clk[0] -max 9.732135098e-10 gfpga_pad_GPIO_PAD[22] +set_input_delay -clock clk[0] -max 9.732135098e-10 gfpga_pad_GPIO_PAD[26] +set_output_delay -clock clk[0] -max 9.732135098e-10 gfpga_pad_GPIO_PAD[9] ################################################## # Disable timing for unused I/Os @@ -30,7 +30,6 @@ set_disable_timing gfpga_pad_GPIO_PAD[5] set_disable_timing gfpga_pad_GPIO_PAD[6] set_disable_timing gfpga_pad_GPIO_PAD[7] set_disable_timing gfpga_pad_GPIO_PAD[8] -set_disable_timing gfpga_pad_GPIO_PAD[9] set_disable_timing gfpga_pad_GPIO_PAD[10] set_disable_timing gfpga_pad_GPIO_PAD[11] set_disable_timing gfpga_pad_GPIO_PAD[12] @@ -43,11 +42,9 @@ set_disable_timing gfpga_pad_GPIO_PAD[18] set_disable_timing gfpga_pad_GPIO_PAD[19] set_disable_timing gfpga_pad_GPIO_PAD[20] set_disable_timing gfpga_pad_GPIO_PAD[21] -set_disable_timing gfpga_pad_GPIO_PAD[22] set_disable_timing gfpga_pad_GPIO_PAD[23] set_disable_timing gfpga_pad_GPIO_PAD[24] set_disable_timing gfpga_pad_GPIO_PAD[25] -set_disable_timing gfpga_pad_GPIO_PAD[26] set_disable_timing gfpga_pad_GPIO_PAD[27] set_disable_timing gfpga_pad_GPIO_PAD[28] set_disable_timing gfpga_pad_GPIO_PAD[29] @@ -55,10 +52,12 @@ set_disable_timing gfpga_pad_GPIO_PAD[30] set_disable_timing gfpga_pad_GPIO_PAD[31] set_disable_timing gfpga_pad_GPIO_PAD[32] set_disable_timing gfpga_pad_GPIO_PAD[33] +set_disable_timing gfpga_pad_GPIO_PAD[34] set_disable_timing gfpga_pad_GPIO_PAD[35] set_disable_timing gfpga_pad_GPIO_PAD[36] set_disable_timing gfpga_pad_GPIO_PAD[37] set_disable_timing gfpga_pad_GPIO_PAD[38] +set_disable_timing gfpga_pad_GPIO_PAD[39] set_disable_timing gfpga_pad_GPIO_PAD[40] set_disable_timing gfpga_pad_GPIO_PAD[41] set_disable_timing gfpga_pad_GPIO_PAD[42] @@ -67,6 +66,7 @@ set_disable_timing gfpga_pad_GPIO_PAD[44] set_disable_timing gfpga_pad_GPIO_PAD[45] set_disable_timing gfpga_pad_GPIO_PAD[46] set_disable_timing gfpga_pad_GPIO_PAD[47] +set_disable_timing gfpga_pad_GPIO_PAD[48] set_disable_timing gfpga_pad_GPIO_PAD[49] set_disable_timing gfpga_pad_GPIO_PAD[50] set_disable_timing gfpga_pad_GPIO_PAD[51] @@ -229,8 +229,10 @@ set_disable_timing fpga_top/sb_*__*_/mem_left_track_*/DFFR_*_/QN ################################################## set_disable_timing cbx_1__0_/chanx_left_in[0] set_disable_timing cbx_1__0_/chanx_right_in[0] +set_disable_timing cbx_1__0_/chanx_left_in[1] set_disable_timing cbx_1__0_/chanx_right_in[1] set_disable_timing cbx_1__0_/chanx_left_in[2] +set_disable_timing cbx_1__0_/chanx_right_in[2] set_disable_timing cbx_1__0_/chanx_left_in[3] set_disable_timing cbx_1__0_/chanx_right_in[3] set_disable_timing cbx_1__0_/chanx_left_in[4] @@ -247,8 +249,10 @@ set_disable_timing cbx_1__0_/chanx_left_in[9] set_disable_timing cbx_1__0_/chanx_right_in[9] set_disable_timing cbx_1__0_/chanx_left_out[0] set_disable_timing cbx_1__0_/chanx_right_out[0] +set_disable_timing cbx_1__0_/chanx_left_out[1] set_disable_timing cbx_1__0_/chanx_right_out[1] set_disable_timing cbx_1__0_/chanx_left_out[2] +set_disable_timing cbx_1__0_/chanx_right_out[2] set_disable_timing cbx_1__0_/chanx_left_out[3] set_disable_timing cbx_1__0_/chanx_right_out[3] set_disable_timing cbx_1__0_/chanx_left_out[4] @@ -390,7 +394,6 @@ set_disable_timing cbx_1__2_/chanx_right_in[0] set_disable_timing cbx_1__2_/chanx_left_in[1] set_disable_timing cbx_1__2_/chanx_right_in[1] set_disable_timing cbx_1__2_/chanx_left_in[2] -set_disable_timing cbx_1__2_/chanx_right_in[2] set_disable_timing cbx_1__2_/chanx_left_in[3] set_disable_timing cbx_1__2_/chanx_right_in[3] set_disable_timing cbx_1__2_/chanx_left_in[4] @@ -410,7 +413,6 @@ set_disable_timing cbx_1__2_/chanx_right_out[0] set_disable_timing cbx_1__2_/chanx_left_out[1] set_disable_timing cbx_1__2_/chanx_right_out[1] set_disable_timing cbx_1__2_/chanx_left_out[2] -set_disable_timing cbx_1__2_/chanx_right_out[2] set_disable_timing cbx_1__2_/chanx_left_out[3] set_disable_timing cbx_1__2_/chanx_right_out[3] set_disable_timing cbx_1__2_/chanx_left_out[4] @@ -471,8 +473,11 @@ set_disable_timing cbx_1__2_/mux_bottom_ipin_4/in[2] set_disable_timing cbx_2__0_/chanx_left_in[0] set_disable_timing cbx_2__0_/chanx_right_in[0] set_disable_timing cbx_2__0_/chanx_left_in[1] +set_disable_timing cbx_2__0_/chanx_right_in[1] +set_disable_timing cbx_2__0_/chanx_left_in[2] set_disable_timing cbx_2__0_/chanx_right_in[2] set_disable_timing cbx_2__0_/chanx_left_in[3] +set_disable_timing cbx_2__0_/chanx_right_in[3] set_disable_timing cbx_2__0_/chanx_left_in[4] set_disable_timing cbx_2__0_/chanx_right_in[4] set_disable_timing cbx_2__0_/chanx_left_in[5] @@ -488,8 +493,11 @@ set_disable_timing cbx_2__0_/chanx_right_in[9] set_disable_timing cbx_2__0_/chanx_left_out[0] set_disable_timing cbx_2__0_/chanx_right_out[0] set_disable_timing cbx_2__0_/chanx_left_out[1] +set_disable_timing cbx_2__0_/chanx_right_out[1] +set_disable_timing cbx_2__0_/chanx_left_out[2] set_disable_timing cbx_2__0_/chanx_right_out[2] set_disable_timing cbx_2__0_/chanx_left_out[3] +set_disable_timing cbx_2__0_/chanx_right_out[3] set_disable_timing cbx_2__0_/chanx_left_out[4] set_disable_timing cbx_2__0_/chanx_right_out[4] set_disable_timing cbx_2__0_/chanx_left_out[5] @@ -503,11 +511,14 @@ set_disable_timing cbx_2__0_/chanx_right_out[8] set_disable_timing cbx_2__0_/chanx_left_out[9] set_disable_timing cbx_2__0_/chanx_right_out[9] set_disable_timing cbx_2__0_/top_grid_bottom_width_0_height_0_subtile_0__pin_I_6_[0] +set_disable_timing cbx_2__0_/top_grid_bottom_width_0_height_0_subtile_0__pin_I_7_[0] +set_disable_timing cbx_2__0_/top_grid_bottom_width_0_height_0_subtile_0__pin_I_8_[0] set_disable_timing cbx_2__0_/top_grid_bottom_width_0_height_0_subtile_0__pin_I_9_[0] set_disable_timing cbx_2__0_/top_grid_bottom_width_0_height_0_subtile_0__pin_I_10_[0] set_disable_timing cbx_2__0_/top_grid_bottom_width_0_height_0_subtile_0__pin_I_11_[0] set_disable_timing cbx_2__0_/bottom_grid_top_width_0_height_0_subtile_0__pin_outpad_0_[0] set_disable_timing cbx_2__0_/bottom_grid_top_width_0_height_0_subtile_1__pin_outpad_0_[0] +set_disable_timing cbx_2__0_/bottom_grid_top_width_0_height_0_subtile_2__pin_outpad_0_[0] set_disable_timing cbx_2__0_/bottom_grid_top_width_0_height_0_subtile_3__pin_outpad_0_[0] set_disable_timing cbx_2__0_/bottom_grid_top_width_0_height_0_subtile_4__pin_outpad_0_[0] set_disable_timing cbx_2__0_/bottom_grid_top_width_0_height_0_subtile_5__pin_outpad_0_[0] @@ -520,8 +531,10 @@ set_disable_timing cbx_2__0_/mux_top_ipin_4/in[0] set_disable_timing cbx_2__0_/mux_bottom_ipin_1/in[1] set_disable_timing cbx_2__0_/mux_top_ipin_0/in[1] set_disable_timing cbx_2__0_/mux_top_ipin_5/in[1] +set_disable_timing cbx_2__0_/mux_bottom_ipin_1/in[0] set_disable_timing cbx_2__0_/mux_top_ipin_0/in[0] set_disable_timing cbx_2__0_/mux_top_ipin_5/in[0] +set_disable_timing cbx_2__0_/mux_bottom_ipin_2/in[1] set_disable_timing cbx_2__0_/mux_top_ipin_1/in[1] set_disable_timing cbx_2__0_/mux_top_ipin_6/in[1] set_disable_timing cbx_2__0_/mux_bottom_ipin_2/in[0] @@ -531,6 +544,7 @@ set_disable_timing cbx_2__0_/mux_bottom_ipin_3/in[1] set_disable_timing cbx_2__0_/mux_top_ipin_2/in[1] set_disable_timing cbx_2__0_/mux_top_ipin_7/in[1] set_disable_timing cbx_2__0_/mux_bottom_ipin_3/in[0] +set_disable_timing cbx_2__0_/mux_top_ipin_2/in[0] set_disable_timing cbx_2__0_/mux_top_ipin_7/in[0] set_disable_timing cbx_2__0_/mux_bottom_ipin_4/in[1] set_disable_timing cbx_2__0_/mux_top_ipin_3/in[1] @@ -557,7 +571,6 @@ set_disable_timing cbx_2__0_/mux_top_ipin_3/in[2] ################################################## # Disable timing for Connection block cbx_1__1_ ################################################## -set_disable_timing cbx_2__1_/chanx_left_in[0] set_disable_timing cbx_2__1_/chanx_right_in[0] set_disable_timing cbx_2__1_/chanx_left_in[1] set_disable_timing cbx_2__1_/chanx_right_in[1] @@ -577,7 +590,6 @@ set_disable_timing cbx_2__1_/chanx_left_in[8] set_disable_timing cbx_2__1_/chanx_right_in[8] set_disable_timing cbx_2__1_/chanx_left_in[9] set_disable_timing cbx_2__1_/chanx_right_in[9] -set_disable_timing cbx_2__1_/chanx_left_out[0] set_disable_timing cbx_2__1_/chanx_right_out[0] set_disable_timing cbx_2__1_/chanx_left_out[1] set_disable_timing cbx_2__1_/chanx_right_out[1] @@ -621,7 +633,6 @@ set_disable_timing cbx_2__1_/mux_bottom_ipin_5/in[0] set_disable_timing cbx_2__2_/chanx_left_in[0] set_disable_timing cbx_2__2_/chanx_right_in[0] set_disable_timing cbx_2__2_/chanx_left_in[1] -set_disable_timing cbx_2__2_/chanx_right_in[1] set_disable_timing cbx_2__2_/chanx_left_in[2] set_disable_timing cbx_2__2_/chanx_right_in[2] set_disable_timing cbx_2__2_/chanx_left_in[3] @@ -641,7 +652,6 @@ set_disable_timing cbx_2__2_/chanx_right_in[9] set_disable_timing cbx_2__2_/chanx_left_out[0] set_disable_timing cbx_2__2_/chanx_right_out[0] set_disable_timing cbx_2__2_/chanx_left_out[1] -set_disable_timing cbx_2__2_/chanx_right_out[1] set_disable_timing cbx_2__2_/chanx_left_out[2] set_disable_timing cbx_2__2_/chanx_right_out[2] set_disable_timing cbx_2__2_/chanx_left_out[3] @@ -659,7 +669,6 @@ set_disable_timing cbx_2__2_/chanx_right_out[8] set_disable_timing cbx_2__2_/chanx_left_out[9] set_disable_timing cbx_2__2_/chanx_right_out[9] set_disable_timing cbx_2__2_/top_grid_bottom_width_0_height_0_subtile_0__pin_outpad_0_[0] -set_disable_timing cbx_2__2_/top_grid_bottom_width_0_height_0_subtile_1__pin_outpad_0_[0] set_disable_timing cbx_2__2_/top_grid_bottom_width_0_height_0_subtile_2__pin_outpad_0_[0] set_disable_timing cbx_2__2_/top_grid_bottom_width_0_height_0_subtile_3__pin_outpad_0_[0] set_disable_timing cbx_2__2_/top_grid_bottom_width_0_height_0_subtile_4__pin_outpad_0_[0] @@ -672,7 +681,6 @@ set_disable_timing cbx_2__2_/mux_bottom_ipin_0/in[0] set_disable_timing cbx_2__2_/mux_bottom_ipin_5/in[0] set_disable_timing cbx_2__2_/mux_bottom_ipin_1/in[1] set_disable_timing cbx_2__2_/mux_bottom_ipin_6/in[1] -set_disable_timing cbx_2__2_/mux_bottom_ipin_1/in[0] set_disable_timing cbx_2__2_/mux_bottom_ipin_6/in[0] set_disable_timing cbx_2__2_/mux_bottom_ipin_2/in[1] set_disable_timing cbx_2__2_/mux_bottom_ipin_7/in[1] @@ -702,6 +710,7 @@ set_disable_timing cbx_2__2_/mux_bottom_ipin_4/in[2] # Disable timing for Connection block cby_0__1_ ################################################## set_disable_timing cby_0__1_/chany_bottom_in[0] +set_disable_timing cby_0__1_/chany_top_in[0] set_disable_timing cby_0__1_/chany_bottom_in[1] set_disable_timing cby_0__1_/chany_top_in[1] set_disable_timing cby_0__1_/chany_bottom_in[2] @@ -721,6 +730,7 @@ set_disable_timing cby_0__1_/chany_top_in[8] set_disable_timing cby_0__1_/chany_bottom_in[9] set_disable_timing cby_0__1_/chany_top_in[9] set_disable_timing cby_0__1_/chany_bottom_out[0] +set_disable_timing cby_0__1_/chany_top_out[0] set_disable_timing cby_0__1_/chany_bottom_out[1] set_disable_timing cby_0__1_/chany_top_out[1] set_disable_timing cby_0__1_/chany_bottom_out[2] @@ -1043,7 +1053,6 @@ set_disable_timing cby_2__1_/chany_bottom_in[4] set_disable_timing cby_2__1_/chany_top_in[4] set_disable_timing cby_2__1_/chany_bottom_in[5] set_disable_timing cby_2__1_/chany_top_in[5] -set_disable_timing cby_2__1_/chany_bottom_in[6] set_disable_timing cby_2__1_/chany_top_in[6] set_disable_timing cby_2__1_/chany_bottom_in[7] set_disable_timing cby_2__1_/chany_top_in[7] @@ -1063,7 +1072,6 @@ set_disable_timing cby_2__1_/chany_bottom_out[4] set_disable_timing cby_2__1_/chany_top_out[4] set_disable_timing cby_2__1_/chany_bottom_out[5] set_disable_timing cby_2__1_/chany_top_out[5] -set_disable_timing cby_2__1_/chany_bottom_out[6] set_disable_timing cby_2__1_/chany_top_out[6] set_disable_timing cby_2__1_/chany_bottom_out[7] set_disable_timing cby_2__1_/chany_top_out[7] @@ -1144,7 +1152,6 @@ set_disable_timing cby_2__1_/mux_right_ipin_1/in[2] ################################################## # Disable timing for Connection block cby_2__1_ ################################################## -set_disable_timing cby_2__2_/chany_bottom_in[0] set_disable_timing cby_2__2_/chany_top_in[0] set_disable_timing cby_2__2_/chany_bottom_in[1] set_disable_timing cby_2__2_/chany_top_in[1] @@ -1152,19 +1159,16 @@ set_disable_timing cby_2__2_/chany_bottom_in[2] set_disable_timing cby_2__2_/chany_top_in[2] set_disable_timing cby_2__2_/chany_bottom_in[3] set_disable_timing cby_2__2_/chany_top_in[3] -set_disable_timing cby_2__2_/chany_bottom_in[4] set_disable_timing cby_2__2_/chany_top_in[4] set_disable_timing cby_2__2_/chany_bottom_in[5] set_disable_timing cby_2__2_/chany_top_in[5] set_disable_timing cby_2__2_/chany_bottom_in[6] set_disable_timing cby_2__2_/chany_top_in[6] -set_disable_timing cby_2__2_/chany_bottom_in[7] set_disable_timing cby_2__2_/chany_top_in[7] set_disable_timing cby_2__2_/chany_bottom_in[8] set_disable_timing cby_2__2_/chany_top_in[8] set_disable_timing cby_2__2_/chany_bottom_in[9] set_disable_timing cby_2__2_/chany_top_in[9] -set_disable_timing cby_2__2_/chany_bottom_out[0] set_disable_timing cby_2__2_/chany_top_out[0] set_disable_timing cby_2__2_/chany_bottom_out[1] set_disable_timing cby_2__2_/chany_top_out[1] @@ -1172,13 +1176,11 @@ set_disable_timing cby_2__2_/chany_bottom_out[2] set_disable_timing cby_2__2_/chany_top_out[2] set_disable_timing cby_2__2_/chany_bottom_out[3] set_disable_timing cby_2__2_/chany_top_out[3] -set_disable_timing cby_2__2_/chany_bottom_out[4] set_disable_timing cby_2__2_/chany_top_out[4] set_disable_timing cby_2__2_/chany_bottom_out[5] set_disable_timing cby_2__2_/chany_top_out[5] set_disable_timing cby_2__2_/chany_bottom_out[6] set_disable_timing cby_2__2_/chany_top_out[6] -set_disable_timing cby_2__2_/chany_bottom_out[7] set_disable_timing cby_2__2_/chany_top_out[7] set_disable_timing cby_2__2_/chany_bottom_out[8] set_disable_timing cby_2__2_/chany_top_out[8] @@ -1193,10 +1195,8 @@ set_disable_timing cby_2__2_/right_grid_left_width_0_height_0_subtile_5__pin_out set_disable_timing cby_2__2_/right_grid_left_width_0_height_0_subtile_6__pin_outpad_0_[0] set_disable_timing cby_2__2_/right_grid_left_width_0_height_0_subtile_7__pin_outpad_0_[0] set_disable_timing cby_2__2_/left_grid_right_width_0_height_0_subtile_0__pin_I_0_[0] -set_disable_timing cby_2__2_/left_grid_right_width_0_height_0_subtile_0__pin_I_1_[0] set_disable_timing cby_2__2_/left_grid_right_width_0_height_0_subtile_0__pin_I_2_[0] set_disable_timing cby_2__2_/left_grid_right_width_0_height_0_subtile_0__pin_I_3_[0] -set_disable_timing cby_2__2_/left_grid_right_width_0_height_0_subtile_0__pin_I_4_[0] set_disable_timing cby_2__2_/left_grid_right_width_0_height_0_subtile_0__pin_I_5_[0] set_disable_timing cby_2__2_/mux_left_ipin_0/in[1] set_disable_timing cby_2__2_/mux_left_ipin_5/in[1] @@ -1223,7 +1223,6 @@ set_disable_timing cby_2__2_/mux_left_ipin_3/in[0] set_disable_timing cby_2__2_/mux_right_ipin_0/in[0] set_disable_timing cby_2__2_/mux_right_ipin_5/in[0] set_disable_timing cby_2__2_/mux_left_ipin_4/in[1] -set_disable_timing cby_2__2_/mux_right_ipin_1/in[1] set_disable_timing cby_2__2_/mux_left_ipin_4/in[0] set_disable_timing cby_2__2_/mux_right_ipin_1/in[0] set_disable_timing cby_2__2_/mux_left_ipin_0/in[3] @@ -1240,7 +1239,6 @@ set_disable_timing cby_2__2_/mux_left_ipin_6/in[2] set_disable_timing cby_2__2_/mux_right_ipin_3/in[2] set_disable_timing cby_2__2_/mux_left_ipin_2/in[3] set_disable_timing cby_2__2_/mux_left_ipin_7/in[3] -set_disable_timing cby_2__2_/mux_right_ipin_4/in[3] set_disable_timing cby_2__2_/mux_left_ipin_2/in[2] set_disable_timing cby_2__2_/mux_left_ipin_7/in[2] set_disable_timing cby_2__2_/mux_right_ipin_4/in[2] @@ -1258,6 +1256,7 @@ set_disable_timing cby_2__2_/mux_right_ipin_1/in[2] # Disable timing for Switch block sb_0__0_ ################################################## set_disable_timing sb_0__0_/chany_top_out[0] +set_disable_timing sb_0__0_/chany_top_in[0] set_disable_timing sb_0__0_/chany_top_out[1] set_disable_timing sb_0__0_/chany_top_in[1] set_disable_timing sb_0__0_/chany_top_out[2] @@ -1278,8 +1277,10 @@ set_disable_timing sb_0__0_/chany_top_out[9] set_disable_timing sb_0__0_/chany_top_in[9] set_disable_timing sb_0__0_/chanx_right_out[0] set_disable_timing sb_0__0_/chanx_right_in[0] +set_disable_timing sb_0__0_/chanx_right_out[1] set_disable_timing sb_0__0_/chanx_right_in[1] set_disable_timing sb_0__0_/chanx_right_out[2] +set_disable_timing sb_0__0_/chanx_right_in[2] set_disable_timing sb_0__0_/chanx_right_out[3] set_disable_timing sb_0__0_/chanx_right_in[3] set_disable_timing sb_0__0_/chanx_right_out[4] @@ -1294,6 +1295,7 @@ set_disable_timing sb_0__0_/chanx_right_out[8] set_disable_timing sb_0__0_/chanx_right_in[8] set_disable_timing sb_0__0_/chanx_right_out[9] set_disable_timing sb_0__0_/chanx_right_in[9] +set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_1__pin_inpad_0_[0] set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_2__pin_inpad_0_[0] set_disable_timing sb_0__0_/top_left_grid_right_width_0_height_0_subtile_3__pin_inpad_0_[0] @@ -1333,6 +1335,7 @@ set_disable_timing sb_0__0_/mux_right_track_16/in[1] set_disable_timing sb_0__0_/mux_right_track_18/in[1] set_disable_timing sb_0__0_/mux_right_track_0/in[2] set_disable_timing sb_0__0_/mux_right_track_2/in[2] +set_disable_timing sb_0__0_/mux_right_track_2/in[0] set_disable_timing sb_0__0_/mux_right_track_4/in[0] set_disable_timing sb_0__0_/mux_right_track_6/in[0] set_disable_timing sb_0__0_/mux_right_track_8/in[0] @@ -1394,6 +1397,7 @@ set_disable_timing sb_0__1_/chanx_right_in[8] set_disable_timing sb_0__1_/chanx_right_out[9] set_disable_timing sb_0__1_/chanx_right_in[9] set_disable_timing sb_0__1_/chany_bottom_in[0] +set_disable_timing sb_0__1_/chany_bottom_out[0] set_disable_timing sb_0__1_/chany_bottom_in[1] set_disable_timing sb_0__1_/chany_bottom_out[1] set_disable_timing sb_0__1_/chany_bottom_in[2] @@ -1424,6 +1428,7 @@ set_disable_timing sb_0__1_/right_top_grid_bottom_width_0_height_0_subtile_0__pi set_disable_timing sb_0__1_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_5_[0] set_disable_timing sb_0__1_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_6_[0] set_disable_timing sb_0__1_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_7_[0] +set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_1__pin_inpad_0_[0] set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_2__pin_inpad_0_[0] set_disable_timing sb_0__1_/bottom_left_grid_right_width_0_height_0_subtile_3__pin_inpad_0_[0] @@ -1443,6 +1448,7 @@ set_disable_timing sb_0__1_/mux_right_track_0/in[1] set_disable_timing sb_0__1_/mux_right_track_2/in[2] set_disable_timing sb_0__1_/mux_right_track_4/in[2] set_disable_timing sb_0__1_/mux_right_track_6/in[2] +set_disable_timing sb_0__1_/mux_bottom_track_1/in[6] set_disable_timing sb_0__1_/mux_bottom_track_9/in[6] set_disable_timing sb_0__1_/mux_bottom_track_17/in[5] set_disable_timing sb_0__1_/mux_bottom_track_1/in[7] @@ -1510,7 +1516,6 @@ set_disable_timing sb_0__2_/chanx_right_in[0] set_disable_timing sb_0__2_/chanx_right_out[1] set_disable_timing sb_0__2_/chanx_right_in[1] set_disable_timing sb_0__2_/chanx_right_out[2] -set_disable_timing sb_0__2_/chanx_right_in[2] set_disable_timing sb_0__2_/chanx_right_out[3] set_disable_timing sb_0__2_/chanx_right_in[3] set_disable_timing sb_0__2_/chanx_right_out[4] @@ -1619,8 +1624,11 @@ set_disable_timing sb_1__0_/chany_top_in[9] set_disable_timing sb_1__0_/chanx_right_out[0] set_disable_timing sb_1__0_/chanx_right_in[0] set_disable_timing sb_1__0_/chanx_right_out[1] +set_disable_timing sb_1__0_/chanx_right_in[1] +set_disable_timing sb_1__0_/chanx_right_out[2] set_disable_timing sb_1__0_/chanx_right_in[2] set_disable_timing sb_1__0_/chanx_right_out[3] +set_disable_timing sb_1__0_/chanx_right_in[3] set_disable_timing sb_1__0_/chanx_right_out[4] set_disable_timing sb_1__0_/chanx_right_in[4] set_disable_timing sb_1__0_/chanx_right_out[5] @@ -1635,8 +1643,10 @@ set_disable_timing sb_1__0_/chanx_right_out[9] set_disable_timing sb_1__0_/chanx_right_in[9] set_disable_timing sb_1__0_/chanx_left_in[0] set_disable_timing sb_1__0_/chanx_left_out[0] +set_disable_timing sb_1__0_/chanx_left_in[1] set_disable_timing sb_1__0_/chanx_left_out[1] set_disable_timing sb_1__0_/chanx_left_in[2] +set_disable_timing sb_1__0_/chanx_left_out[2] set_disable_timing sb_1__0_/chanx_left_in[3] set_disable_timing sb_1__0_/chanx_left_out[3] set_disable_timing sb_1__0_/chanx_left_in[4] @@ -1658,6 +1668,7 @@ set_disable_timing sb_1__0_/top_left_grid_right_width_0_height_0_subtile_0__pin_ set_disable_timing sb_1__0_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_4_[0] set_disable_timing sb_1__0_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_5_[0] set_disable_timing sb_1__0_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_6_[0] +set_disable_timing sb_1__0_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_7_[0] set_disable_timing sb_1__0_/right_bottom_grid_top_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_1__0_/right_bottom_grid_top_width_0_height_0_subtile_1__pin_inpad_0_[0] set_disable_timing sb_1__0_/right_bottom_grid_top_width_0_height_0_subtile_2__pin_inpad_0_[0] @@ -1665,6 +1676,7 @@ set_disable_timing sb_1__0_/right_bottom_grid_top_width_0_height_0_subtile_3__pi set_disable_timing sb_1__0_/right_bottom_grid_top_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_1__0_/right_bottom_grid_top_width_0_height_0_subtile_5__pin_inpad_0_[0] set_disable_timing sb_1__0_/right_bottom_grid_top_width_0_height_0_subtile_6__pin_inpad_0_[0] +set_disable_timing sb_1__0_/right_bottom_grid_top_width_0_height_0_subtile_7__pin_inpad_0_[0] set_disable_timing sb_1__0_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_4_[0] set_disable_timing sb_1__0_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_5_[0] set_disable_timing sb_1__0_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_6_[0] @@ -1781,7 +1793,6 @@ set_disable_timing sb_1__1_/chany_top_out[8] set_disable_timing sb_1__1_/chany_top_in[8] set_disable_timing sb_1__1_/chany_top_out[9] set_disable_timing sb_1__1_/chany_top_in[9] -set_disable_timing sb_1__1_/chanx_right_out[0] set_disable_timing sb_1__1_/chanx_right_in[0] set_disable_timing sb_1__1_/chanx_right_out[1] set_disable_timing sb_1__1_/chanx_right_in[1] @@ -1848,7 +1859,6 @@ set_disable_timing sb_1__1_/top_left_grid_right_width_0_height_0_subtile_0__pin_ set_disable_timing sb_1__1_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_4_[0] set_disable_timing sb_1__1_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_5_[0] set_disable_timing sb_1__1_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_6_[0] -set_disable_timing sb_1__1_/right_top_grid_bottom_width_0_height_0_subtile_0__pin_O_7_[0] set_disable_timing sb_1__1_/bottom_left_grid_right_width_0_height_0_subtile_0__pin_O_0_[0] set_disable_timing sb_1__1_/bottom_left_grid_right_width_0_height_0_subtile_0__pin_O_1_[0] set_disable_timing sb_1__1_/bottom_left_grid_right_width_0_height_0_subtile_0__pin_O_2_[0] @@ -1864,7 +1874,6 @@ set_disable_timing sb_1__1_/mux_top_track_0/in[1] set_disable_timing sb_1__1_/mux_right_track_0/in[4] set_disable_timing sb_1__1_/mux_right_track_8/in[3] set_disable_timing sb_1__1_/mux_right_track_16/in[3] -set_disable_timing sb_1__1_/mux_right_track_0/in[5] set_disable_timing sb_1__1_/mux_bottom_track_1/in[7] set_disable_timing sb_1__1_/mux_bottom_track_9/in[5] set_disable_timing sb_1__1_/mux_bottom_track_17/in[5] @@ -1987,7 +1996,6 @@ set_disable_timing sb_1__1_/mux_bottom_track_9/in[8] set_disable_timing sb_1__2_/chanx_right_out[0] set_disable_timing sb_1__2_/chanx_right_in[0] set_disable_timing sb_1__2_/chanx_right_out[1] -set_disable_timing sb_1__2_/chanx_right_in[1] set_disable_timing sb_1__2_/chanx_right_out[2] set_disable_timing sb_1__2_/chanx_right_in[2] set_disable_timing sb_1__2_/chanx_right_out[3] @@ -2029,7 +2037,6 @@ set_disable_timing sb_1__2_/chanx_left_out[0] set_disable_timing sb_1__2_/chanx_left_in[1] set_disable_timing sb_1__2_/chanx_left_out[1] set_disable_timing sb_1__2_/chanx_left_in[2] -set_disable_timing sb_1__2_/chanx_left_out[2] set_disable_timing sb_1__2_/chanx_left_in[3] set_disable_timing sb_1__2_/chanx_left_out[3] set_disable_timing sb_1__2_/chanx_left_in[4] @@ -2150,7 +2157,6 @@ set_disable_timing sb_2__0_/chany_top_out[4] set_disable_timing sb_2__0_/chany_top_in[4] set_disable_timing sb_2__0_/chany_top_out[5] set_disable_timing sb_2__0_/chany_top_in[5] -set_disable_timing sb_2__0_/chany_top_out[6] set_disable_timing sb_2__0_/chany_top_in[6] set_disable_timing sb_2__0_/chany_top_out[7] set_disable_timing sb_2__0_/chany_top_in[7] @@ -2161,8 +2167,11 @@ set_disable_timing sb_2__0_/chany_top_in[9] set_disable_timing sb_2__0_/chanx_left_in[0] set_disable_timing sb_2__0_/chanx_left_out[0] set_disable_timing sb_2__0_/chanx_left_in[1] +set_disable_timing sb_2__0_/chanx_left_out[1] +set_disable_timing sb_2__0_/chanx_left_in[2] set_disable_timing sb_2__0_/chanx_left_out[2] set_disable_timing sb_2__0_/chanx_left_in[3] +set_disable_timing sb_2__0_/chanx_left_out[3] set_disable_timing sb_2__0_/chanx_left_in[4] set_disable_timing sb_2__0_/chanx_left_out[4] set_disable_timing sb_2__0_/chanx_left_in[5] @@ -2181,7 +2190,6 @@ set_disable_timing sb_2__0_/top_left_grid_right_width_0_height_0_subtile_0__pin_ set_disable_timing sb_2__0_/top_left_grid_right_width_0_height_0_subtile_0__pin_O_3_[0] set_disable_timing sb_2__0_/top_right_grid_left_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_2__0_/top_right_grid_left_width_0_height_0_subtile_1__pin_inpad_0_[0] -set_disable_timing sb_2__0_/top_right_grid_left_width_0_height_0_subtile_2__pin_inpad_0_[0] set_disable_timing sb_2__0_/top_right_grid_left_width_0_height_0_subtile_3__pin_inpad_0_[0] set_disable_timing sb_2__0_/top_right_grid_left_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_2__0_/top_right_grid_left_width_0_height_0_subtile_5__pin_inpad_0_[0] @@ -2190,6 +2198,7 @@ set_disable_timing sb_2__0_/top_right_grid_left_width_0_height_0_subtile_7__pin_ set_disable_timing sb_2__0_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_4_[0] set_disable_timing sb_2__0_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_5_[0] set_disable_timing sb_2__0_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_6_[0] +set_disable_timing sb_2__0_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_7_[0] set_disable_timing sb_2__0_/left_bottom_grid_top_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_2__0_/left_bottom_grid_top_width_0_height_0_subtile_1__pin_inpad_0_[0] set_disable_timing sb_2__0_/left_bottom_grid_top_width_0_height_0_subtile_2__pin_inpad_0_[0] @@ -2197,13 +2206,13 @@ set_disable_timing sb_2__0_/left_bottom_grid_top_width_0_height_0_subtile_3__pin set_disable_timing sb_2__0_/left_bottom_grid_top_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_2__0_/left_bottom_grid_top_width_0_height_0_subtile_5__pin_inpad_0_[0] set_disable_timing sb_2__0_/left_bottom_grid_top_width_0_height_0_subtile_6__pin_inpad_0_[0] +set_disable_timing sb_2__0_/left_bottom_grid_top_width_0_height_0_subtile_7__pin_inpad_0_[0] set_disable_timing sb_2__0_/mux_top_track_0/in[0] set_disable_timing sb_2__0_/mux_top_track_2/in[0] set_disable_timing sb_2__0_/mux_top_track_4/in[0] set_disable_timing sb_2__0_/mux_top_track_6/in[0] set_disable_timing sb_2__0_/mux_top_track_8/in[0] set_disable_timing sb_2__0_/mux_top_track_10/in[0] -set_disable_timing sb_2__0_/mux_top_track_12/in[0] set_disable_timing sb_2__0_/mux_top_track_14/in[0] set_disable_timing sb_2__0_/mux_top_track_16/in[0] set_disable_timing sb_2__0_/mux_top_track_18/in[0] @@ -2212,6 +2221,7 @@ set_disable_timing sb_2__0_/mux_top_track_2/in[1] set_disable_timing sb_2__0_/mux_left_track_1/in[1] set_disable_timing sb_2__0_/mux_left_track_3/in[1] set_disable_timing sb_2__0_/mux_left_track_5/in[1] +set_disable_timing sb_2__0_/mux_left_track_7/in[1] set_disable_timing sb_2__0_/mux_left_track_9/in[1] set_disable_timing sb_2__0_/mux_left_track_11/in[1] set_disable_timing sb_2__0_/mux_left_track_13/in[1] @@ -2219,6 +2229,7 @@ set_disable_timing sb_2__0_/mux_left_track_15/in[1] set_disable_timing sb_2__0_/mux_left_track_17/in[1] set_disable_timing sb_2__0_/mux_left_track_19/in[1] set_disable_timing sb_2__0_/mux_left_track_1/in[2] +set_disable_timing sb_2__0_/mux_left_track_3/in[2] set_disable_timing sb_2__0_/mux_left_track_1/in[0] set_disable_timing sb_2__0_/mux_left_track_19/in[0] set_disable_timing sb_2__0_/mux_left_track_17/in[0] @@ -2242,7 +2253,6 @@ set_disable_timing sb_2__0_/mux_top_track_2/in[2] ################################################## # Disable timing for Switch block sb_2__1_ ################################################## -set_disable_timing sb_2__1_/chany_top_out[0] set_disable_timing sb_2__1_/chany_top_in[0] set_disable_timing sb_2__1_/chany_top_out[1] set_disable_timing sb_2__1_/chany_top_in[1] @@ -2250,13 +2260,11 @@ set_disable_timing sb_2__1_/chany_top_out[2] set_disable_timing sb_2__1_/chany_top_in[2] set_disable_timing sb_2__1_/chany_top_out[3] set_disable_timing sb_2__1_/chany_top_in[3] -set_disable_timing sb_2__1_/chany_top_out[4] set_disable_timing sb_2__1_/chany_top_in[4] set_disable_timing sb_2__1_/chany_top_out[5] set_disable_timing sb_2__1_/chany_top_in[5] set_disable_timing sb_2__1_/chany_top_out[6] set_disable_timing sb_2__1_/chany_top_in[6] -set_disable_timing sb_2__1_/chany_top_out[7] set_disable_timing sb_2__1_/chany_top_in[7] set_disable_timing sb_2__1_/chany_top_out[8] set_disable_timing sb_2__1_/chany_top_in[8] @@ -2274,7 +2282,6 @@ set_disable_timing sb_2__1_/chany_bottom_in[4] set_disable_timing sb_2__1_/chany_bottom_out[4] set_disable_timing sb_2__1_/chany_bottom_in[5] set_disable_timing sb_2__1_/chany_bottom_out[5] -set_disable_timing sb_2__1_/chany_bottom_in[6] set_disable_timing sb_2__1_/chany_bottom_out[6] set_disable_timing sb_2__1_/chany_bottom_in[7] set_disable_timing sb_2__1_/chany_bottom_out[7] @@ -2282,7 +2289,6 @@ set_disable_timing sb_2__1_/chany_bottom_in[8] set_disable_timing sb_2__1_/chany_bottom_out[8] set_disable_timing sb_2__1_/chany_bottom_in[9] set_disable_timing sb_2__1_/chany_bottom_out[9] -set_disable_timing sb_2__1_/chanx_left_in[0] set_disable_timing sb_2__1_/chanx_left_out[0] set_disable_timing sb_2__1_/chanx_left_in[1] set_disable_timing sb_2__1_/chanx_left_out[1] @@ -2312,11 +2318,9 @@ set_disable_timing sb_2__1_/top_right_grid_left_width_0_height_0_subtile_2__pin_ set_disable_timing sb_2__1_/top_right_grid_left_width_0_height_0_subtile_3__pin_inpad_0_[0] set_disable_timing sb_2__1_/top_right_grid_left_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_2__1_/top_right_grid_left_width_0_height_0_subtile_5__pin_inpad_0_[0] -set_disable_timing sb_2__1_/top_right_grid_left_width_0_height_0_subtile_6__pin_inpad_0_[0] set_disable_timing sb_2__1_/top_right_grid_left_width_0_height_0_subtile_7__pin_inpad_0_[0] set_disable_timing sb_2__1_/bottom_right_grid_left_width_0_height_0_subtile_0__pin_inpad_0_[0] set_disable_timing sb_2__1_/bottom_right_grid_left_width_0_height_0_subtile_1__pin_inpad_0_[0] -set_disable_timing sb_2__1_/bottom_right_grid_left_width_0_height_0_subtile_2__pin_inpad_0_[0] set_disable_timing sb_2__1_/bottom_right_grid_left_width_0_height_0_subtile_3__pin_inpad_0_[0] set_disable_timing sb_2__1_/bottom_right_grid_left_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_2__1_/bottom_right_grid_left_width_0_height_0_subtile_5__pin_inpad_0_[0] @@ -2329,7 +2333,6 @@ set_disable_timing sb_2__1_/bottom_left_grid_right_width_0_height_0_subtile_0__p set_disable_timing sb_2__1_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_4_[0] set_disable_timing sb_2__1_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_5_[0] set_disable_timing sb_2__1_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_6_[0] -set_disable_timing sb_2__1_/left_top_grid_bottom_width_0_height_0_subtile_0__pin_O_7_[0] set_disable_timing sb_2__1_/mux_top_track_0/in[0] set_disable_timing sb_2__1_/mux_top_track_8/in[0] set_disable_timing sb_2__1_/mux_top_track_16/in[0] @@ -2340,7 +2343,6 @@ set_disable_timing sb_2__1_/mux_top_track_0/in[2] set_disable_timing sb_2__1_/mux_top_track_8/in[2] set_disable_timing sb_2__1_/mux_top_track_16/in[2] set_disable_timing sb_2__1_/mux_top_track_0/in[3] -set_disable_timing sb_2__1_/mux_top_track_8/in[3] set_disable_timing sb_2__1_/mux_top_track_16/in[3] set_disable_timing sb_2__1_/mux_bottom_track_1/in[3] set_disable_timing sb_2__1_/mux_bottom_track_9/in[2] @@ -2390,7 +2392,6 @@ set_disable_timing sb_2__1_/mux_left_track_5/in[2] set_disable_timing sb_2__1_/mux_top_track_0/in[6] set_disable_timing sb_2__1_/mux_left_track_13/in[1] set_disable_timing sb_2__1_/mux_left_track_7/in[2] -set_disable_timing sb_2__1_/mux_top_track_0/in[7] set_disable_timing sb_2__1_/mux_bottom_track_17/in[6] set_disable_timing sb_2__1_/mux_top_track_16/in[6] set_disable_timing sb_2__1_/mux_bottom_track_1/in[7] @@ -2413,7 +2414,6 @@ set_disable_timing sb_2__1_/mux_bottom_track_17/in[9] ################################################## # Disable timing for Switch block sb_2__2_ ################################################## -set_disable_timing sb_2__2_/chany_bottom_in[0] set_disable_timing sb_2__2_/chany_bottom_out[0] set_disable_timing sb_2__2_/chany_bottom_in[1] set_disable_timing sb_2__2_/chany_bottom_out[1] @@ -2421,13 +2421,11 @@ set_disable_timing sb_2__2_/chany_bottom_in[2] set_disable_timing sb_2__2_/chany_bottom_out[2] set_disable_timing sb_2__2_/chany_bottom_in[3] set_disable_timing sb_2__2_/chany_bottom_out[3] -set_disable_timing sb_2__2_/chany_bottom_in[4] set_disable_timing sb_2__2_/chany_bottom_out[4] set_disable_timing sb_2__2_/chany_bottom_in[5] set_disable_timing sb_2__2_/chany_bottom_out[5] set_disable_timing sb_2__2_/chany_bottom_in[6] set_disable_timing sb_2__2_/chany_bottom_out[6] -set_disable_timing sb_2__2_/chany_bottom_in[7] set_disable_timing sb_2__2_/chany_bottom_out[7] set_disable_timing sb_2__2_/chany_bottom_in[8] set_disable_timing sb_2__2_/chany_bottom_out[8] @@ -2436,7 +2434,6 @@ set_disable_timing sb_2__2_/chany_bottom_out[9] set_disable_timing sb_2__2_/chanx_left_in[0] set_disable_timing sb_2__2_/chanx_left_out[0] set_disable_timing sb_2__2_/chanx_left_in[1] -set_disable_timing sb_2__2_/chanx_left_out[1] set_disable_timing sb_2__2_/chanx_left_in[2] set_disable_timing sb_2__2_/chanx_left_out[2] set_disable_timing sb_2__2_/chanx_left_in[3] @@ -2459,7 +2456,6 @@ set_disable_timing sb_2__2_/bottom_right_grid_left_width_0_height_0_subtile_2__p set_disable_timing sb_2__2_/bottom_right_grid_left_width_0_height_0_subtile_3__pin_inpad_0_[0] set_disable_timing sb_2__2_/bottom_right_grid_left_width_0_height_0_subtile_4__pin_inpad_0_[0] set_disable_timing sb_2__2_/bottom_right_grid_left_width_0_height_0_subtile_5__pin_inpad_0_[0] -set_disable_timing sb_2__2_/bottom_right_grid_left_width_0_height_0_subtile_6__pin_inpad_0_[0] set_disable_timing sb_2__2_/bottom_right_grid_left_width_0_height_0_subtile_7__pin_inpad_0_[0] set_disable_timing sb_2__2_/bottom_left_grid_right_width_0_height_0_subtile_0__pin_O_0_[0] set_disable_timing sb_2__2_/bottom_left_grid_right_width_0_height_0_subtile_0__pin_O_1_[0] @@ -2493,7 +2489,6 @@ set_disable_timing sb_2__2_/mux_left_track_9/in[1] set_disable_timing sb_2__2_/mux_left_track_11/in[1] set_disable_timing sb_2__2_/mux_left_track_13/in[1] set_disable_timing sb_2__2_/mux_left_track_15/in[1] -set_disable_timing sb_2__2_/mux_left_track_3/in[0] set_disable_timing sb_2__2_/mux_left_track_5/in[0] set_disable_timing sb_2__2_/mux_left_track_7/in[0] set_disable_timing sb_2__2_/mux_left_track_9/in[0] @@ -2759,561 +2754,561 @@ set_disable_timing grid_clb_1__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_ # Disable Timing for grid[2][1] ####################################### ####################################### -# Disable Timing for unused resources in grid[2][1][0] -####################################### -####################################### -# Disable unused pins for pb_graph_node clb[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[4] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[5] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[6] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[9] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[10] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_I[11] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_O[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_O[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_O[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_O[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_O[4] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_O[5] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_O[6] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/clb_clk[0] -####################################### -# Disable unused mux_inputs for pb_graph_node clb[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[4] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[5] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[6] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[7] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[8] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[9] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[10] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[11] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//direct_interc_9_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//direct_interc_16_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[12] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[13] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//direct_interc_11_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[14] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[15] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//direct_interc_13_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[16] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[17] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//direct_interc_15_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[18] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[19] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0//direct_interc_8_/in[0] -####################################### -# Disable unused pins for pb_graph_node fle[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_out[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_clk[0] -####################################### -# Disable unused mux_inputs for pb_graph_node fle[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_5_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_6_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_7_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_8_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_0_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_2_/in[0] -####################################### -# Disable unused pins for pb_graph_node fabric[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_clk[0] -####################################### -# Disable unused mux_inputs for pb_graph_node fabric[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_2_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_9_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_6_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_7_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_8_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_1/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_0_D_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_1_D_0/in[1] -####################################### -# Disable unused pins for pb_graph_node frac_logic[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[1] -####################################### -# Disable unused mux_inputs for pb_graph_node frac_logic[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_2_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_0_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[0] -####################################### -# Disable unused pins for pb_graph_node frac_lut4[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut4_out[0] -####################################### -# Disable unused pins for pb_graph_node ff[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_D[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_Q[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_clk[0] -####################################### -# Disable unused pins for pb_graph_node ff[1] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_D[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_Q[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_clk[0] -####################################### -# Disable unused pins for pb_graph_node adder[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_a[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_b[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_sumout[0] -####################################### -# Disable unused pins for pb_graph_node fle[1] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_out[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_clk[0] -####################################### -# Disable unused mux_inputs for pb_graph_node fle[1] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_5_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_6_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_7_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_8_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_0_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_2_/in[0] -####################################### -# Disable unused pins for pb_graph_node fabric[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_clk[0] -####################################### -# Disable unused mux_inputs for pb_graph_node fabric[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_2_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_9_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_6_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_7_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_8_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_1/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_0_D_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_1_D_0/in[1] -####################################### -# Disable unused pins for pb_graph_node frac_logic[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[1] -####################################### -# Disable unused mux_inputs for pb_graph_node frac_logic[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_2_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_0_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[0] -####################################### -# Disable unused pins for pb_graph_node frac_lut4[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut4_out[0] -####################################### -# Disable unused pins for pb_graph_node ff[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_D[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_Q[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_clk[0] -####################################### -# Disable unused pins for pb_graph_node ff[1] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_D[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_Q[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_clk[0] -####################################### -# Disable unused pins for pb_graph_node adder[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_a[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_b[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_sumout[0] -####################################### -# Disable unused pins for pb_graph_node fle[2] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_out[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_clk[0] -####################################### -# Disable unused mux_inputs for pb_graph_node fle[2] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_5_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_6_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_7_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_8_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_0_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_2_/in[0] -####################################### -# Disable unused pins for pb_graph_node fabric[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_clk[0] -####################################### -# Disable unused mux_inputs for pb_graph_node fabric[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_2_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_9_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_6_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_7_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_8_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_1/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_0_D_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_1_D_0/in[1] -####################################### -# Disable unused pins for pb_graph_node frac_logic[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[1] -####################################### -# Disable unused mux_inputs for pb_graph_node frac_logic[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_2_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_0_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[0] -####################################### -# Disable unused pins for pb_graph_node frac_lut4[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[2] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut4_out[0] -####################################### -# Disable unused pins for pb_graph_node ff[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_D[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_Q[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_clk[0] -####################################### -# Disable unused pins for pb_graph_node ff[1] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_D[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_Q[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_clk[0] -####################################### -# Disable unused pins for pb_graph_node adder[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_a[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_b[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_sumout[0] -####################################### -# Disable unused pins for pb_graph_node fle[3] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_clk[0] -####################################### -# Disable unused mux_inputs for pb_graph_node fle[3] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_3_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_6_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_7_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_8_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_0_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_2_/in[0] -####################################### -# Disable unused pins for pb_graph_node fabric[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_clk[0] -####################################### -# Disable unused mux_inputs for pb_graph_node fabric[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_9_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_6_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_7_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_1/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_0_D_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_1_D_0/in[1] -####################################### -# Disable unused pins for pb_graph_node frac_logic[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[0] -####################################### -# Disable unused mux_inputs for pb_graph_node frac_logic[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_1_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_4_/in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[1] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[0] -####################################### -# Disable unused pins for pb_graph_node frac_lut4[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[3] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut4_out[0] -####################################### -# Disable unused pins for pb_graph_node ff[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_D[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_Q[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_clk[0] -####################################### -# Disable unused pins for pb_graph_node ff[1] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_D[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_Q[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_clk[0] -####################################### -# Disable unused pins for pb_graph_node adder[0] -####################################### -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_a[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_b[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cin[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cout[0] -set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_sumout[0] -####################################### -# Disable Timing for grid[2][2] -####################################### -####################################### -# Disable Timing for unused grid[2][2][0] +# Disable Timing for unused grid[2][1][0] ####################################### ####################################### # Disable all the ports for pb_graph_node clb[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/* ####################################### # Disable all the ports for pb_graph_node fle[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/* ####################################### # Disable all the ports for pb_graph_node fabric[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/* ####################################### # Disable all the ports for pb_graph_node frac_logic[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/* ####################################### # Disable all the ports for pb_graph_node frac_lut4[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/* ####################################### # Disable all the ports for pb_graph_node ff[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/* ####################################### # Disable all the ports for pb_graph_node ff[1] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/* ####################################### # Disable all the ports for pb_graph_node adder[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/* ####################################### # Disable all the ports for pb_graph_node fle[1] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/* ####################################### # Disable all the ports for pb_graph_node fabric[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/* ####################################### # Disable all the ports for pb_graph_node frac_logic[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/* ####################################### # Disable all the ports for pb_graph_node frac_lut4[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/* ####################################### # Disable all the ports for pb_graph_node ff[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/* ####################################### # Disable all the ports for pb_graph_node ff[1] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/* ####################################### # Disable all the ports for pb_graph_node adder[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/* ####################################### # Disable all the ports for pb_graph_node fle[2] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/* ####################################### # Disable all the ports for pb_graph_node fabric[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/* ####################################### # Disable all the ports for pb_graph_node frac_logic[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/* ####################################### # Disable all the ports for pb_graph_node frac_lut4[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/* ####################################### # Disable all the ports for pb_graph_node ff[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/* ####################################### # Disable all the ports for pb_graph_node ff[1] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/* ####################################### # Disable all the ports for pb_graph_node adder[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/* ####################################### # Disable all the ports for pb_graph_node fle[3] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/* ####################################### # Disable all the ports for pb_graph_node fabric[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/* ####################################### # Disable all the ports for pb_graph_node frac_logic[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/* ####################################### # Disable all the ports for pb_graph_node frac_lut4[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/* ####################################### # Disable all the ports for pb_graph_node ff[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/* ####################################### # Disable all the ports for pb_graph_node ff[1] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/* ####################################### # Disable all the ports for pb_graph_node adder[0] ####################################### -set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/* +set_disable_timing grid_clb_2__1_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/* +####################################### +# Disable Timing for grid[2][2] +####################################### +####################################### +# Disable Timing for unused resources in grid[2][2][0] +####################################### +####################################### +# Disable unused pins for pb_graph_node clb[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[5] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[6] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[7] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[8] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[9] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[10] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_I[11] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_O[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_O[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_O[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_O[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_O[4] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_O[5] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_O[6] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/clb_clk[0] +####################################### +# Disable unused mux_inputs for pb_graph_node clb[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[4] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[5] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[6] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[7] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[8] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[9] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[10] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[11] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//direct_interc_9_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//direct_interc_16_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[12] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[13] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//direct_interc_11_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[14] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[15] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//direct_interc_13_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[16] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[17] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//direct_interc_15_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[18] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//mux_fle_3_in_3/in[19] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0//direct_interc_8_/in[0] +####################################### +# Disable unused pins for pb_graph_node fle[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_out[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/fle_clk[0] +####################################### +# Disable unused mux_inputs for pb_graph_node fle[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_5_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_6_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_7_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_8_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_0_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0//direct_interc_2_/in[0] +####################################### +# Disable unused pins for pb_graph_node fabric[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_clk[0] +####################################### +# Disable unused mux_inputs for pb_graph_node fabric[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_2_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_9_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_6_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_7_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_8_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_1/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_0_D_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_1_D_0/in[1] +####################################### +# Disable unused pins for pb_graph_node frac_logic[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[1] +####################################### +# Disable unused mux_inputs for pb_graph_node frac_logic[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_2_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_0_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[0] +####################################### +# Disable unused pins for pb_graph_node frac_lut4[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut4_out[0] +####################################### +# Disable unused pins for pb_graph_node ff[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_D[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_Q[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_clk[0] +####################################### +# Disable unused pins for pb_graph_node ff[1] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_D[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_Q[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_clk[0] +####################################### +# Disable unused pins for pb_graph_node adder[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_a[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_b[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_sumout[0] +####################################### +# Disable unused pins for pb_graph_node fle[1] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_out[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/fle_clk[0] +####################################### +# Disable unused mux_inputs for pb_graph_node fle[1] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_5_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_6_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_7_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_8_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_0_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1//direct_interc_2_/in[0] +####################################### +# Disable unused pins for pb_graph_node fabric[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_clk[0] +####################################### +# Disable unused mux_inputs for pb_graph_node fabric[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_2_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_9_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_6_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_7_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_8_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_1/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_0_D_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_1_D_0/in[1] +####################################### +# Disable unused pins for pb_graph_node frac_logic[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[1] +####################################### +# Disable unused mux_inputs for pb_graph_node frac_logic[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_2_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_0_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[0] +####################################### +# Disable unused pins for pb_graph_node frac_lut4[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut4_out[0] +####################################### +# Disable unused pins for pb_graph_node ff[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_D[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_Q[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_clk[0] +####################################### +# Disable unused pins for pb_graph_node ff[1] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_D[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_Q[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_clk[0] +####################################### +# Disable unused pins for pb_graph_node adder[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_a[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_b[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_1/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_sumout[0] +####################################### +# Disable unused pins for pb_graph_node fle[2] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_out[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/fle_clk[0] +####################################### +# Disable unused mux_inputs for pb_graph_node fle[2] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_5_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_6_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_7_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_8_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_0_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2//direct_interc_2_/in[0] +####################################### +# Disable unused pins for pb_graph_node fabric[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_clk[0] +####################################### +# Disable unused mux_inputs for pb_graph_node fabric[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_2_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_9_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_6_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_7_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_8_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_1/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_0_D_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_1_D_0/in[1] +####################################### +# Disable unused pins for pb_graph_node frac_logic[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[1] +####################################### +# Disable unused mux_inputs for pb_graph_node frac_logic[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_2_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_0_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[0] +####################################### +# Disable unused pins for pb_graph_node frac_lut4[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[2] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut4_out[0] +####################################### +# Disable unused pins for pb_graph_node ff[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_D[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_Q[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_clk[0] +####################################### +# Disable unused pins for pb_graph_node ff[1] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_D[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_Q[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_clk[0] +####################################### +# Disable unused pins for pb_graph_node adder[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_a[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_b[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_2/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_sumout[0] +####################################### +# Disable unused pins for pb_graph_node fle[3] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/fle_clk[0] +####################################### +# Disable unused mux_inputs for pb_graph_node fle[3] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_3_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_6_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_7_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_8_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_0_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3//direct_interc_2_/in[0] +####################################### +# Disable unused pins for pb_graph_node fabric[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/fabric_clk[0] +####################################### +# Disable unused mux_inputs for pb_graph_node fabric[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_9_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_6_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//direct_interc_7_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_fabric_out_1/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_0_D_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0//mux_ff_1_D_0/in[1] +####################################### +# Disable unused pins for pb_graph_node frac_logic[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/frac_logic_out[0] +####################################### +# Disable unused mux_inputs for pb_graph_node frac_logic[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_1_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//direct_interc_4_/in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[1] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0//mux_frac_logic_out_0/in[0] +####################################### +# Disable unused pins for pb_graph_node frac_lut4[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_in[3] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut3_out[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0/frac_lut4_lut4_out[0] +####################################### +# Disable unused pins for pb_graph_node ff[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_D[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_Q[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_0/ff_clk[0] +####################################### +# Disable unused pins for pb_graph_node ff[1] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_D[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_Q[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__ff_1/ff_clk[0] +####################################### +# Disable unused pins for pb_graph_node adder[0] +####################################### +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_a[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_b[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cin[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_cout[0] +set_disable_timing grid_clb_2__2_/logical_tile_clb_mode_clb__0/logical_tile_clb_mode_default__fle_3/logical_tile_clb_mode_default__fle_mode_physical__fabric_0/logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__adder_0/adder_sumout[0] ####################################### # Disable Timing for grid[1][3] ####################################### @@ -3420,16 +3415,20 @@ set_disable_timing grid_io_top_2__3_/logical_tile_io_mode_io__0/* ####################################### set_disable_timing grid_io_top_2__3_/logical_tile_io_mode_io__0/logical_tile_io_mode_physical__iopad_0/* ####################################### -# Disable Timing for unused grid[2][3][1] +# Disable Timing for unused resources in grid[2][3][1] ####################################### ####################################### -# Disable all the ports for pb_graph_node io[0] +# Disable unused pins for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_top_2__3_/logical_tile_io_mode_io__1/* +set_disable_timing grid_io_top_2__3_/logical_tile_io_mode_io__1/io_inpad[0] ####################################### -# Disable all the ports for pb_graph_node iopad[0] +# Disable unused mux_inputs for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_top_2__3_/logical_tile_io_mode_io__1/logical_tile_io_mode_physical__iopad_0/* +set_disable_timing grid_io_top_2__3_/logical_tile_io_mode_io__1//direct_interc_0_/in[0] +####################################### +# Disable unused pins for pb_graph_node iopad[0] +####################################### +set_disable_timing grid_io_top_2__3_/logical_tile_io_mode_io__1/logical_tile_io_mode_physical__iopad_0/iopad_inpad[0] ####################################### # Disable Timing for unused grid[2][3][2] ####################################### @@ -3566,16 +3565,20 @@ set_disable_timing grid_io_right_3__2_/logical_tile_io_mode_io__5/* ####################################### set_disable_timing grid_io_right_3__2_/logical_tile_io_mode_io__5/logical_tile_io_mode_physical__iopad_0/* ####################################### -# Disable Timing for unused grid[3][2][6] +# Disable Timing for unused resources in grid[3][2][6] ####################################### ####################################### -# Disable all the ports for pb_graph_node io[0] +# Disable unused pins for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_right_3__2_/logical_tile_io_mode_io__6/* +set_disable_timing grid_io_right_3__2_/logical_tile_io_mode_io__6/io_outpad[0] ####################################### -# Disable all the ports for pb_graph_node iopad[0] +# Disable unused mux_inputs for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_right_3__2_/logical_tile_io_mode_io__6/logical_tile_io_mode_physical__iopad_0/* +set_disable_timing grid_io_right_3__2_/logical_tile_io_mode_io__6//direct_interc_1_/in[0] +####################################### +# Disable unused pins for pb_graph_node iopad[0] +####################################### +set_disable_timing grid_io_right_3__2_/logical_tile_io_mode_io__6/logical_tile_io_mode_physical__iopad_0/iopad_outpad[0] ####################################### # Disable Timing for unused grid[3][2][7] ####################################### @@ -3613,16 +3616,20 @@ set_disable_timing grid_io_right_3__1_/logical_tile_io_mode_io__1/* ####################################### set_disable_timing grid_io_right_3__1_/logical_tile_io_mode_io__1/logical_tile_io_mode_physical__iopad_0/* ####################################### -# Disable Timing for unused grid[3][1][2] +# Disable Timing for unused resources in grid[3][1][2] ####################################### ####################################### -# Disable all the ports for pb_graph_node io[0] +# Disable unused pins for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_right_3__1_/logical_tile_io_mode_io__2/* +set_disable_timing grid_io_right_3__1_/logical_tile_io_mode_io__2/io_outpad[0] ####################################### -# Disable all the ports for pb_graph_node iopad[0] +# Disable unused mux_inputs for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_right_3__1_/logical_tile_io_mode_io__2/logical_tile_io_mode_physical__iopad_0/* +set_disable_timing grid_io_right_3__1_/logical_tile_io_mode_io__2//direct_interc_1_/in[0] +####################################### +# Disable unused pins for pb_graph_node iopad[0] +####################################### +set_disable_timing grid_io_right_3__1_/logical_tile_io_mode_io__2/logical_tile_io_mode_physical__iopad_0/iopad_outpad[0] ####################################### # Disable Timing for unused grid[3][1][3] ####################################### @@ -3704,20 +3711,16 @@ set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__1/* ####################################### set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__1/logical_tile_io_mode_physical__iopad_0/* ####################################### -# Disable Timing for unused resources in grid[2][0][2] +# Disable Timing for unused grid[2][0][2] ####################################### ####################################### -# Disable unused pins for pb_graph_node io[0] +# Disable all the ports for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__2/io_inpad[0] +set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__2/* ####################################### -# Disable unused mux_inputs for pb_graph_node io[0] +# Disable all the ports for pb_graph_node iopad[0] ####################################### -set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__2//direct_interc_0_/in[0] -####################################### -# Disable unused pins for pb_graph_node iopad[0] -####################################### -set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__2/logical_tile_io_mode_physical__iopad_0/iopad_inpad[0] +set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__2/logical_tile_io_mode_physical__iopad_0/* ####################################### # Disable Timing for unused grid[2][0][3] ####################################### @@ -3763,20 +3766,16 @@ set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__6/* ####################################### set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__6/logical_tile_io_mode_physical__iopad_0/* ####################################### -# Disable Timing for unused resources in grid[2][0][7] +# Disable Timing for unused grid[2][0][7] ####################################### ####################################### -# Disable unused pins for pb_graph_node io[0] +# Disable all the ports for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__7/io_outpad[0] +set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__7/* ####################################### -# Disable unused mux_inputs for pb_graph_node io[0] +# Disable all the ports for pb_graph_node iopad[0] ####################################### -set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__7//direct_interc_1_/in[0] -####################################### -# Disable unused pins for pb_graph_node iopad[0] -####################################### -set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__7/logical_tile_io_mode_physical__iopad_0/iopad_outpad[0] +set_disable_timing grid_io_bottom_2__0_/logical_tile_io_mode_io__7/logical_tile_io_mode_physical__iopad_0/* ####################################### # Disable Timing for grid[1][0] ####################################### @@ -3872,20 +3871,16 @@ set_disable_timing grid_io_bottom_1__0_/logical_tile_io_mode_io__7/logical_tile_ # Disable Timing for grid[0][1] ####################################### ####################################### -# Disable Timing for unused resources in grid[0][1][0] +# Disable Timing for unused grid[0][1][0] ####################################### ####################################### -# Disable unused pins for pb_graph_node io[0] +# Disable all the ports for pb_graph_node io[0] ####################################### -set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__0/io_outpad[0] +set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__0/* ####################################### -# Disable unused mux_inputs for pb_graph_node io[0] +# Disable all the ports for pb_graph_node iopad[0] ####################################### -set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__0//direct_interc_1_/in[0] -####################################### -# Disable unused pins for pb_graph_node iopad[0] -####################################### -set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__0/logical_tile_io_mode_physical__iopad_0/iopad_outpad[0] +set_disable_timing grid_io_left_0__1_/logical_tile_io_mode_io__0/logical_tile_io_mode_physical__iopad_0/* ####################################### # Disable Timing for unused grid[0][1][1] ####################################### diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_top_formal_verification.v b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_top_formal_verification.v index 6f261adc1..5df277771 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_top_formal_verification.v +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/and2_top_formal_verification.v @@ -45,14 +45,14 @@ wire [0:0] clk_fm; // ----- End Connect Global ports of FPGA top module ----- // ----- Link BLIF Benchmark I/Os to FPGA I/Os ----- -// ----- Blif Benchmark input a is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[39] ----- - assign gfpga_pad_GPIO_PAD_fm[39] = a[0]; +// ----- Blif Benchmark input a is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[22] ----- + assign gfpga_pad_GPIO_PAD_fm[22] = a[0]; -// ----- Blif Benchmark input b is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[48] ----- - assign gfpga_pad_GPIO_PAD_fm[48] = b[0]; +// ----- Blif Benchmark input b is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[26] ----- + assign gfpga_pad_GPIO_PAD_fm[26] = b[0]; -// ----- Blif Benchmark output c is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[34] ----- - assign c[0] = gfpga_pad_GPIO_PAD_fm[34]; +// ----- Blif Benchmark output c is mapped to FPGA IOPAD gfpga_pad_GPIO_PAD_fm[9] ----- + assign c[0] = gfpga_pad_GPIO_PAD_fm[9]; // ----- Wire unused FPGA I/Os to constants ----- assign gfpga_pad_GPIO_PAD_fm[0] = 1'b0; @@ -64,7 +64,6 @@ wire [0:0] clk_fm; assign gfpga_pad_GPIO_PAD_fm[6] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[7] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[8] = 1'b0; - assign gfpga_pad_GPIO_PAD_fm[9] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[10] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[11] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[12] = 1'b0; @@ -77,11 +76,9 @@ wire [0:0] clk_fm; assign gfpga_pad_GPIO_PAD_fm[19] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[20] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[21] = 1'b0; - assign gfpga_pad_GPIO_PAD_fm[22] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[23] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[24] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[25] = 1'b0; - assign gfpga_pad_GPIO_PAD_fm[26] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[27] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[28] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[29] = 1'b0; @@ -89,10 +86,12 @@ wire [0:0] clk_fm; assign gfpga_pad_GPIO_PAD_fm[31] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[32] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[33] = 1'b0; + assign gfpga_pad_GPIO_PAD_fm[34] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[35] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[36] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[37] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[38] = 1'b0; + assign gfpga_pad_GPIO_PAD_fm[39] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[40] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[41] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[42] = 1'b0; @@ -101,6 +100,7 @@ wire [0:0] clk_fm; assign gfpga_pad_GPIO_PAD_fm[45] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[46] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[47] = 1'b0; + assign gfpga_pad_GPIO_PAD_fm[48] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[49] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[50] = 1'b0; assign gfpga_pad_GPIO_PAD_fm[51] = 1'b0; @@ -316,14 +316,14 @@ initial begin force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_2.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_0_D_0.mem_outb[0:2] = 3'b110; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_2.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_1_D_0.mem_out[0:2] = 3'b001; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_2.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_1_D_0.mem_outb[0:2] = 3'b110; - force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0.frac_lut4_DFFR_mem.mem_out[0:16] = 17'b00000000110000001; - force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0.frac_lut4_DFFR_mem.mem_outb[0:16] = 17'b11111111001111110; + force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0.frac_lut4_DFFR_mem.mem_out[0:16] = {17{1'b0}}; + force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0.frac_lut4_DFFR_mem.mem_outb[0:16] = {17{1'b1}}; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.mem_frac_logic_out_0.mem_out[0:2] = 3'b001; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.mem_frac_logic_out_0.mem_outb[0:2] = 3'b110; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_0.mem_out[0:3] = 4'b0001; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_0.mem_outb[0:3] = 4'b1110; - force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_1.mem_out[0:3] = 4'b0010; - force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_1.mem_outb[0:3] = 4'b1101; + force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_1.mem_out[0:3] = 4'b0001; + force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_1.mem_outb[0:3] = 4'b1110; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_0_D_0.mem_out[0:2] = 3'b001; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_0_D_0.mem_outb[0:2] = 3'b110; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_1_D_0.mem_out[0:2] = 3'b001; @@ -354,10 +354,10 @@ initial begin force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_2_in_3.mem_outb[0:9] = 10'b1111111110; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_0.mem_out[0:9] = 10'b0000000001; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_0.mem_outb[0:9] = 10'b1111111110; - force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_out[0:9] = 10'b0001001000; - force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_outb[0:9] = 10'b1110110111; - force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_2.mem_out[0:9] = 10'b0010001000; - force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_2.mem_outb[0:9] = 10'b1101110111; + force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_out[0:9] = 10'b0000000001; + force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_outb[0:9] = 10'b1111111110; + force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_2.mem_out[0:9] = 10'b0000000001; + force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_2.mem_outb[0:9] = 10'b1111111110; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_3.mem_out[0:9] = 10'b0000000001; force U0_formal_verification.grid_clb_2__1_.logical_tile_clb_mode_clb__0.mem_fle_3_in_3.mem_outb[0:9] = 10'b1111111110; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0.frac_lut4_DFFR_mem.mem_out[0:16] = {17{1'b0}}; @@ -396,14 +396,14 @@ initial begin force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_2.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_0_D_0.mem_outb[0:2] = 3'b110; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_2.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_1_D_0.mem_out[0:2] = 3'b001; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_2.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_1_D_0.mem_outb[0:2] = 3'b110; - force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0.frac_lut4_DFFR_mem.mem_out[0:16] = {17{1'b0}}; - force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0.frac_lut4_DFFR_mem.mem_outb[0:16] = {17{1'b1}}; + force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0.frac_lut4_DFFR_mem.mem_out[0:16] = 17'b00000000110000001; + force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_mode_default__frac_lut4_0.frac_lut4_DFFR_mem.mem_outb[0:16] = 17'b11111111001111110; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.mem_frac_logic_out_0.mem_out[0:2] = 3'b001; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.logical_tile_clb_mode_default__fle_mode_physical__fabric_mode_default__frac_logic_0.mem_frac_logic_out_0.mem_outb[0:2] = 3'b110; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_0.mem_out[0:3] = 4'b0001; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_0.mem_outb[0:3] = 4'b1110; - force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_1.mem_out[0:3] = 4'b0001; - force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_1.mem_outb[0:3] = 4'b1110; + force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_1.mem_out[0:3] = 4'b0010; + force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_fabric_out_1.mem_outb[0:3] = 4'b1101; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_0_D_0.mem_out[0:2] = 3'b001; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_0_D_0.mem_outb[0:2] = 3'b110; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.logical_tile_clb_mode_default__fle_3.logical_tile_clb_mode_default__fle_mode_physical__fabric_0.mem_ff_1_D_0.mem_out[0:2] = 3'b001; @@ -434,10 +434,10 @@ initial begin force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_2_in_3.mem_outb[0:9] = 10'b1111111110; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_0.mem_out[0:9] = 10'b0000000001; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_0.mem_outb[0:9] = 10'b1111111110; - force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_out[0:9] = 10'b0000000001; - force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_outb[0:9] = 10'b1111111110; - force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_2.mem_out[0:9] = 10'b0000000001; - force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_2.mem_outb[0:9] = 10'b1111111110; + force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_out[0:9] = 10'b0000110000; + force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_1.mem_outb[0:9] = 10'b1111001111; + force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_2.mem_out[0:9] = 10'b0100010000; + force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_2.mem_outb[0:9] = 10'b1011101111; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_3.mem_out[0:9] = 10'b0000000001; force U0_formal_verification.grid_clb_2__2_.logical_tile_clb_mode_clb__0.mem_fle_3_in_3.mem_outb[0:9] = 10'b1111111110; force U0_formal_verification.grid_io_top_1__3_.logical_tile_io_mode_io__0.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b1; @@ -458,8 +458,8 @@ initial begin force U0_formal_verification.grid_io_top_1__3_.logical_tile_io_mode_io__7.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b0; force U0_formal_verification.grid_io_top_2__3_.logical_tile_io_mode_io__0.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b1; force U0_formal_verification.grid_io_top_2__3_.logical_tile_io_mode_io__0.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b0; - force U0_formal_verification.grid_io_top_2__3_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b1; - force U0_formal_verification.grid_io_top_2__3_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b0; + force U0_formal_verification.grid_io_top_2__3_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b0; + force U0_formal_verification.grid_io_top_2__3_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b1; force U0_formal_verification.grid_io_top_2__3_.logical_tile_io_mode_io__2.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b1; force U0_formal_verification.grid_io_top_2__3_.logical_tile_io_mode_io__2.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b0; force U0_formal_verification.grid_io_top_2__3_.logical_tile_io_mode_io__3.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b1; @@ -508,8 +508,8 @@ initial begin force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__0.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b0; force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b1; force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__1.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b0; - force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__2.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b0; - force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__2.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b1; + force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__2.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b1; + force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__2.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b0; force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__3.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b1; force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__3.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_outb[0] = 1'b0; force U0_formal_verification.grid_io_bottom_2__0_.logical_tile_io_mode_io__4.logical_tile_io_mode_physical__iopad_0.GPIO_DFFR_mem.mem_out[0] = 1'b1; @@ -586,8 +586,8 @@ initial begin force U0_formal_verification.sb_0__0_.mem_top_track_14.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__0_.mem_right_track_0.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__0_.mem_right_track_0.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__0_.mem_right_track_2.mem_out[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__0_.mem_right_track_2.mem_outb[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__0_.mem_right_track_2.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_0__0_.mem_right_track_2.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__0_.mem_right_track_4.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__0_.mem_right_track_4.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__0_.mem_right_track_6.mem_out[0:1] = {2{1'b0}}; @@ -624,8 +624,8 @@ initial begin force U0_formal_verification.sb_0__1_.mem_right_track_10.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_0__1_.mem_right_track_12.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_0__1_.mem_right_track_12.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_0__1_.mem_bottom_track_1.mem_out[0:7] = 8'b00100100; - force U0_formal_verification.sb_0__1_.mem_bottom_track_1.mem_outb[0:7] = 8'b11011011; + force U0_formal_verification.sb_0__1_.mem_bottom_track_1.mem_out[0:7] = 8'b00000001; + force U0_formal_verification.sb_0__1_.mem_bottom_track_1.mem_outb[0:7] = 8'b11111110; force U0_formal_verification.sb_0__1_.mem_bottom_track_9.mem_out[0:7] = 8'b00000001; force U0_formal_verification.sb_0__1_.mem_bottom_track_9.mem_outb[0:7] = 8'b11111110; force U0_formal_verification.sb_0__1_.mem_bottom_track_17.mem_out[0:5] = 6'b010001; @@ -696,8 +696,8 @@ initial begin force U0_formal_verification.sb_1__1_.mem_top_track_8.mem_outb[0:7] = 8'b11111110; force U0_formal_verification.sb_1__1_.mem_top_track_16.mem_out[0:7] = 8'b00000001; force U0_formal_verification.sb_1__1_.mem_top_track_16.mem_outb[0:7] = 8'b11111110; - force U0_formal_verification.sb_1__1_.mem_right_track_0.mem_out[0:7] = 8'b01000001; - force U0_formal_verification.sb_1__1_.mem_right_track_0.mem_outb[0:7] = 8'b10111110; + force U0_formal_verification.sb_1__1_.mem_right_track_0.mem_out[0:7] = 8'b01000100; + force U0_formal_verification.sb_1__1_.mem_right_track_0.mem_outb[0:7] = 8'b10111011; force U0_formal_verification.sb_1__1_.mem_right_track_8.mem_out[0:7] = 8'b00000001; force U0_formal_verification.sb_1__1_.mem_right_track_8.mem_outb[0:7] = 8'b11111110; force U0_formal_verification.sb_1__1_.mem_right_track_16.mem_out[0:7] = 8'b00000001; @@ -752,8 +752,8 @@ initial begin force U0_formal_verification.sb_2__0_.mem_top_track_8.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_2__0_.mem_top_track_10.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__0_.mem_top_track_10.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_2__0_.mem_top_track_12.mem_out[0:1] = {2{1'b0}}; - force U0_formal_verification.sb_2__0_.mem_top_track_12.mem_outb[0:1] = {2{1'b1}}; + force U0_formal_verification.sb_2__0_.mem_top_track_12.mem_out[0:1] = {2{1'b1}}; + force U0_formal_verification.sb_2__0_.mem_top_track_12.mem_outb[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__0_.mem_top_track_14.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__0_.mem_top_track_14.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_2__0_.mem_top_track_16.mem_out[0:1] = {2{1'b0}}; @@ -762,12 +762,12 @@ initial begin force U0_formal_verification.sb_2__0_.mem_top_track_18.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_2__0_.mem_left_track_1.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__0_.mem_left_track_1.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_2__0_.mem_left_track_3.mem_out[0:1] = 2'b10; - force U0_formal_verification.sb_2__0_.mem_left_track_3.mem_outb[0:1] = 2'b01; + force U0_formal_verification.sb_2__0_.mem_left_track_3.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_2__0_.mem_left_track_3.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_2__0_.mem_left_track_5.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__0_.mem_left_track_5.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_2__0_.mem_left_track_7.mem_out[0:1] = 2'b01; - force U0_formal_verification.sb_2__0_.mem_left_track_7.mem_outb[0:1] = 2'b10; + force U0_formal_verification.sb_2__0_.mem_left_track_7.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.sb_2__0_.mem_left_track_7.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_2__0_.mem_left_track_9.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__0_.mem_left_track_9.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_2__0_.mem_left_track_11.mem_out[0:1] = {2{1'b0}}; @@ -780,10 +780,10 @@ initial begin force U0_formal_verification.sb_2__0_.mem_left_track_17.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_2__0_.mem_left_track_19.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__0_.mem_left_track_19.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_2__1_.mem_top_track_0.mem_out[0:7] = 8'b00000001; - force U0_formal_verification.sb_2__1_.mem_top_track_0.mem_outb[0:7] = 8'b11111110; - force U0_formal_verification.sb_2__1_.mem_top_track_8.mem_out[0:7] = 8'b00000001; - force U0_formal_verification.sb_2__1_.mem_top_track_8.mem_outb[0:7] = 8'b11111110; + force U0_formal_verification.sb_2__1_.mem_top_track_0.mem_out[0:7] = 8'b00010100; + force U0_formal_verification.sb_2__1_.mem_top_track_0.mem_outb[0:7] = 8'b11101011; + force U0_formal_verification.sb_2__1_.mem_top_track_8.mem_out[0:7] = 8'b00011000; + force U0_formal_verification.sb_2__1_.mem_top_track_8.mem_outb[0:7] = 8'b11100111; force U0_formal_verification.sb_2__1_.mem_top_track_16.mem_out[0:7] = 8'b00000001; force U0_formal_verification.sb_2__1_.mem_top_track_16.mem_outb[0:7] = 8'b11111110; force U0_formal_verification.sb_2__1_.mem_bottom_track_1.mem_out[0:7] = 8'b00000001; @@ -828,8 +828,8 @@ initial begin force U0_formal_verification.sb_2__2_.mem_bottom_track_19.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_2__2_.mem_left_track_1.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__2_.mem_left_track_1.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.sb_2__2_.mem_left_track_3.mem_out[0:1] = {2{1'b0}}; - force U0_formal_verification.sb_2__2_.mem_left_track_3.mem_outb[0:1] = {2{1'b1}}; + force U0_formal_verification.sb_2__2_.mem_left_track_3.mem_out[0:1] = {2{1'b1}}; + force U0_formal_verification.sb_2__2_.mem_left_track_3.mem_outb[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__2_.mem_left_track_5.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.sb_2__2_.mem_left_track_5.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.sb_2__2_.mem_left_track_7.mem_out[0:1] = {2{1'b0}}; @@ -900,10 +900,10 @@ initial begin force U0_formal_verification.cbx_1__2_.mem_bottom_ipin_7.mem_outb[0:5] = 6'b111110; force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_0.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_0.mem_outb[0:1] = {2{1'b1}}; - force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_1.mem_out[0:1] = 2'b01; - force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_1.mem_outb[0:1] = 2'b10; - force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_2.mem_out[0:1] = {2{1'b1}}; - force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_2.mem_outb[0:1] = {2{1'b0}}; + force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_1.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_1.mem_outb[0:1] = {2{1'b1}}; + force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_2.mem_out[0:1] = {2{1'b0}}; + force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_2.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_3.mem_out[0:1] = {2{1'b0}}; force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_3.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.cbx_2__0_.mem_bottom_ipin_4.mem_out[0:1] = {2{1'b0}}; @@ -914,8 +914,8 @@ initial begin force U0_formal_verification.cbx_2__0_.mem_top_ipin_0.mem_outb[0:5] = 6'b111110; force U0_formal_verification.cbx_2__0_.mem_top_ipin_1.mem_out[0:5] = 6'b000001; force U0_formal_verification.cbx_2__0_.mem_top_ipin_1.mem_outb[0:5] = 6'b111110; - force U0_formal_verification.cbx_2__0_.mem_top_ipin_2.mem_out[0:5] = 6'b010100; - force U0_formal_verification.cbx_2__0_.mem_top_ipin_2.mem_outb[0:5] = 6'b101011; + force U0_formal_verification.cbx_2__0_.mem_top_ipin_2.mem_out[0:5] = 6'b000001; + force U0_formal_verification.cbx_2__0_.mem_top_ipin_2.mem_outb[0:5] = 6'b111110; force U0_formal_verification.cbx_2__0_.mem_top_ipin_3.mem_out[0:5] = 6'b000001; force U0_formal_verification.cbx_2__0_.mem_top_ipin_3.mem_outb[0:5] = 6'b111110; force U0_formal_verification.cbx_2__0_.mem_top_ipin_4.mem_out[0:5] = 6'b000001; @@ -940,8 +940,8 @@ initial begin force U0_formal_verification.cbx_2__1_.mem_bottom_ipin_5.mem_outb[0:1] = {2{1'b1}}; force U0_formal_verification.cbx_2__2_.mem_bottom_ipin_0.mem_out[0:5] = 6'b000001; force U0_formal_verification.cbx_2__2_.mem_bottom_ipin_0.mem_outb[0:5] = 6'b111110; - force U0_formal_verification.cbx_2__2_.mem_bottom_ipin_1.mem_out[0:5] = 6'b000001; - force U0_formal_verification.cbx_2__2_.mem_bottom_ipin_1.mem_outb[0:5] = 6'b111110; + force U0_formal_verification.cbx_2__2_.mem_bottom_ipin_1.mem_out[0:5] = 6'b010100; + force U0_formal_verification.cbx_2__2_.mem_bottom_ipin_1.mem_outb[0:5] = 6'b101011; force U0_formal_verification.cbx_2__2_.mem_bottom_ipin_2.mem_out[0:5] = 6'b000001; force U0_formal_verification.cbx_2__2_.mem_bottom_ipin_2.mem_outb[0:5] = 6'b111110; force U0_formal_verification.cbx_2__2_.mem_bottom_ipin_3.mem_out[0:5] = 6'b000001; @@ -1064,14 +1064,14 @@ initial begin force U0_formal_verification.cby_2__2_.mem_left_ipin_7.mem_outb[0:5] = 6'b111110; force U0_formal_verification.cby_2__2_.mem_right_ipin_0.mem_out[0:5] = 6'b000001; force U0_formal_verification.cby_2__2_.mem_right_ipin_0.mem_outb[0:5] = 6'b111110; - force U0_formal_verification.cby_2__2_.mem_right_ipin_1.mem_out[0:5] = 6'b000001; - force U0_formal_verification.cby_2__2_.mem_right_ipin_1.mem_outb[0:5] = 6'b111110; + force U0_formal_verification.cby_2__2_.mem_right_ipin_1.mem_out[0:5] = 6'b100100; + force U0_formal_verification.cby_2__2_.mem_right_ipin_1.mem_outb[0:5] = 6'b011011; force U0_formal_verification.cby_2__2_.mem_right_ipin_2.mem_out[0:5] = 6'b000001; force U0_formal_verification.cby_2__2_.mem_right_ipin_2.mem_outb[0:5] = 6'b111110; force U0_formal_verification.cby_2__2_.mem_right_ipin_3.mem_out[0:5] = 6'b000001; force U0_formal_verification.cby_2__2_.mem_right_ipin_3.mem_outb[0:5] = 6'b111110; - force U0_formal_verification.cby_2__2_.mem_right_ipin_4.mem_out[0:5] = 6'b000001; - force U0_formal_verification.cby_2__2_.mem_right_ipin_4.mem_outb[0:5] = 6'b111110; + force U0_formal_verification.cby_2__2_.mem_right_ipin_4.mem_out[0:5] = 6'b001100; + force U0_formal_verification.cby_2__2_.mem_right_ipin_4.mem_outb[0:5] = 6'b110011; force U0_formal_verification.cby_2__2_.mem_right_ipin_5.mem_out[0:5] = 6'b000001; force U0_formal_verification.cby_2__2_.mem_right_ipin_5.mem_outb[0:5] = 6'b111110; end diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_bitstream.bit b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_bitstream.bit index a665d29db..3575fa16e 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_bitstream.bit +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_bitstream.bit @@ -415,9 +415,9 @@ 0 0 0 -1 0 0 +1 0 0 0 @@ -457,13 +457,11 @@ 0 0 0 -1 -0 -0 0 0 0 0 +1 0 0 0 @@ -473,6 +471,8 @@ 0 0 0 +1 +1 0 0 0 @@ -613,26 +613,26 @@ 1 0 0 -1 -0 -0 0 1 0 0 -0 1 0 0 0 +1 0 0 +1 0 0 0 0 0 0 +1 +1 0 0 0 @@ -749,10 +749,10 @@ 0 0 0 -1 -0 0 0 +1 +1 0 0 1 @@ -767,13 +767,13 @@ 0 0 0 -1 -0 0 0 +1 0 0 1 +1 0 0 0 @@ -901,36 +901,39 @@ 0 0 0 -1 0 0 0 +1 +1 +0 0 0 0 0 1 0 +1 0 0 0 +1 0 0 0 -1 0 0 0 0 0 0 +1 0 0 0 0 0 0 -1 0 0 0 @@ -940,11 +943,8 @@ 0 0 0 -1 0 0 -1 -0 0 0 1 @@ -1083,10 +1083,10 @@ 1 0 0 -0 1 0 0 +0 1 0 0 @@ -1094,15 +1094,15 @@ 1 0 0 -1 0 0 0 0 0 0 -1 -1 +0 +0 +0 0 0 0 @@ -1327,11 +1327,11 @@ 0 0 0 +1 +0 0 0 -1 0 -1 0 1 0 @@ -1351,9 +1351,6 @@ 0 0 0 -1 -1 -1 0 0 0 @@ -1369,12 +1366,10 @@ 0 0 0 -1 0 0 0 0 -1 0 0 0 @@ -1388,6 +1383,11 @@ 0 0 0 +1 +1 +0 +0 +0 0 0 0 @@ -1945,8 +1945,8 @@ 0 0 0 -1 -1 +0 +0 0 0 0 @@ -2041,12 +2041,12 @@ 0 0 0 +1 +0 0 0 -1 0 0 -1 0 0 0 @@ -2255,7 +2255,7 @@ 1 1 1 -1 +0 1 1 0 @@ -2293,15 +2293,13 @@ 0 0 0 -1 -0 -0 -0 0 0 1 0 +1 0 +1 0 0 0 @@ -2319,6 +2317,8 @@ 0 0 0 +1 +1 0 0 0 @@ -2362,7 +2362,7 @@ 1 1 1 -0 +1 1 1 1 diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_bitstream.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_bitstream.xml index 5004ccc7b..a2bf18b06 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_bitstream.xml +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_bitstream.xml @@ -834,11 +834,11 @@ - + - + @@ -918,7 +918,7 @@ - + @@ -926,7 +926,7 @@ - + @@ -934,11 +934,11 @@ - + - + @@ -946,9 +946,9 @@ - + - + @@ -1230,9 +1230,9 @@ - + - + @@ -1252,7 +1252,7 @@ - + @@ -1266,9 +1266,9 @@ - + - + @@ -1502,13 +1502,13 @@ - + - + - + @@ -1538,17 +1538,17 @@ - + - + - + @@ -1806,15 +1806,15 @@ - + - + - + @@ -1822,15 +1822,15 @@ - + - + - + @@ -1858,13 +1858,13 @@ - + - + @@ -1872,25 +1872,25 @@ - + - + - + - + @@ -2170,9 +2170,9 @@ - + - + @@ -2192,7 +2192,7 @@ - + @@ -2206,9 +2206,9 @@ - + - + @@ -2658,15 +2658,15 @@ - + - + - + @@ -2706,11 +2706,11 @@ - + - + - + @@ -2742,7 +2742,7 @@ - + @@ -2752,7 +2752,7 @@ - + @@ -2770,9 +2770,9 @@ - + - + @@ -3894,9 +3894,9 @@ - + - + @@ -4086,17 +4086,17 @@ - + - + - + @@ -4514,7 +4514,7 @@ - + @@ -4590,15 +4590,15 @@ - + - + - + @@ -4638,9 +4638,9 @@ - + - + @@ -4728,7 +4728,7 @@ - + diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_independent_bitstream.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_independent_bitstream.xml index 8e51c806a..a8cc1c0c7 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_independent_bitstream.xml +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_independent_bitstream.xml @@ -2227,15 +2227,15 @@ - - + + - + @@ -2287,19 +2287,14 @@ - - - - - - + - + - - + + @@ -2646,42 +2641,20 @@ - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + @@ -2691,42 +2664,20 @@ - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + @@ -3176,15 +3127,15 @@ - - + + - + @@ -3236,14 +3187,19 @@ - + + + + + + - + - - + + @@ -3590,20 +3546,42 @@ - + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - + @@ -3613,20 +3591,42 @@ - + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + @@ -3812,7 +3812,7 @@ - + @@ -4218,7 +4218,7 @@ - + @@ -4702,7 +4702,7 @@ - + @@ -4721,7 +4721,7 @@ - + @@ -4865,16 +4865,16 @@ - + - + - - - + + + @@ -5269,22 +5269,22 @@ - + - + - + - + - + - + @@ -5606,7 +5606,7 @@ - + @@ -5670,9 +5670,9 @@ - + - + @@ -5785,7 +5785,7 @@ - + @@ -5807,7 +5807,7 @@ - + @@ -5843,7 +5843,7 @@ - + @@ -5873,7 +5873,7 @@ - + @@ -5934,7 +5934,7 @@ - + @@ -6097,7 +6097,7 @@ - + @@ -6107,17 +6107,17 @@ - + - + - + - + @@ -6498,7 +6498,7 @@ - + @@ -6646,7 +6646,7 @@ - + @@ -6816,15 +6816,15 @@ - + - + - - - + + + @@ -6853,7 +6853,7 @@ - + @@ -6909,13 +6909,13 @@ - + - + - - + + @@ -6945,14 +6945,14 @@ - + - + - + - + @@ -7079,23 +7079,23 @@ - + - + - + - + - + - + @@ -7108,7 +7108,7 @@ - + @@ -7116,17 +7116,17 @@ - + - + - - + + - + @@ -7141,7 +7141,7 @@ - + @@ -7232,11 +7232,11 @@ - + - + @@ -7337,7 +7337,7 @@ - + @@ -7377,7 +7377,7 @@ - + @@ -7524,7 +7524,7 @@ - + @@ -7614,15 +7614,15 @@ - + - + - - - + + + @@ -7686,7 +7686,7 @@ - + @@ -7760,7 +7760,7 @@ - + @@ -7779,7 +7779,7 @@ - + @@ -7850,7 +7850,7 @@ - + @@ -7875,7 +7875,7 @@ - + @@ -7970,7 +7970,7 @@ - + @@ -7995,7 +7995,7 @@ - + @@ -8203,7 +8203,7 @@ - + @@ -8323,7 +8323,7 @@ - + @@ -8367,14 +8367,14 @@ - + - + - + - + @@ -8384,15 +8384,15 @@ - + - + - - - + + + @@ -8403,7 +8403,7 @@ - + @@ -8457,7 +8457,7 @@ - + @@ -8480,7 +8480,7 @@ - + @@ -8505,20 +8505,20 @@ - + - + - + - + - + - + @@ -8577,7 +8577,7 @@ - + @@ -8600,7 +8600,7 @@ - + @@ -8625,7 +8625,7 @@ - + @@ -8650,7 +8650,7 @@ - + @@ -8785,20 +8785,20 @@ - + - + - + - + - + - + @@ -8905,7 +8905,7 @@ - + @@ -8955,7 +8955,7 @@ - + @@ -9075,7 +9075,7 @@ - + @@ -9756,7 +9756,7 @@ - + @@ -9876,7 +9876,7 @@ - + @@ -9996,7 +9996,7 @@ - + @@ -10068,7 +10068,7 @@ - + @@ -10118,7 +10118,7 @@ - + @@ -10164,7 +10164,7 @@ - + @@ -10188,7 +10188,7 @@ - + @@ -10238,7 +10238,7 @@ - + @@ -10284,21 +10284,21 @@ - + - + - - + + - + - + @@ -10308,7 +10308,7 @@ - + @@ -10358,19 +10358,19 @@ - + - + - + - - + + - + diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_netlists.v b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_netlists.v index 246169183..e9c113a25 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_netlists.v +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/fabric_netlists.v @@ -58,6 +58,8 @@ `include "routing/cby_1__1_.v" `include "routing/cby_2__1_.v" +// ------ Include tile module netlists ----- + // ------ Include fabric top-level netlists ----- `include "fpga_top.v" diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/global_ports.sdc b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/global_ports.sdc index 8070cff56..f0d0e3c9b 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/global_ports.sdc +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/global_ports.sdc @@ -14,7 +14,7 @@ set_units -time s ################################################## # Create clock ################################################## -create_clock -name clk[0] -period 8.970345577e-10 -waveform {0 4.485172789e-10} [get_ports {clk[0]}] +create_clock -name clk[0] -period 9.732135098e-10 -waveform {0 4.866067549e-10} [get_ports {clk[0]}] ################################################## # Create programmable clock ################################################## diff --git a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/pin_mapping.xml b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/pin_mapping.xml index c107f9429..d15ba5ca0 100644 --- a/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/pin_mapping.xml +++ b/openfpga_flow/tasks/basic_tests/no_time_stamp/no_cout_in_gsb/golden_outputs_no_time_stamp/pin_mapping.xml @@ -3,7 +3,7 @@ --> - - - + + + diff --git a/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper/config/task.conf b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper/config/task.conf new file mode 100644 index 000000000..0655d77a2 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper/config/task.conf @@ -0,0 +1,43 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fpga_core_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_wrapper_io_naming_rules= +openfpga_testbench_dut_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 + +bench1_top = or2 + +bench2_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules/config/task.conf b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules/config/task.conf new file mode 100644 index 000000000..727ae668a --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules/config/task.conf @@ -0,0 +1,43 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fpga_core_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_wrapper_io_naming_rules=--io_naming ${PATH:TASK_DIR}/config/wrapper_io_naming.xml +openfpga_testbench_dut_module= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 + +bench1_top = or2 + +bench2_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules/config/wrapper_io_naming.xml b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules/config/wrapper_io_naming.xml new file mode 100644 index 000000000..616ce00dd --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules/config/wrapper_io_naming.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/task.conf b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/task.conf new file mode 100644 index 000000000..9cc41ce37 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/task.conf @@ -0,0 +1,43 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fpga_core_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_wrapper_io_naming_rules=--io_naming ${PATH:TASK_DIR}/config/wrapper_io_naming.xml +openfpga_testbench_dut_module= --dut_module fpga_core + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 + +bench1_top = or2 + +bench2_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/wrapper_io_naming.xml b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/wrapper_io_naming.xml new file mode 100644 index 000000000..616ce00dd --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/preconfig_testbench/fpga_core_wrapper_naming_rules_use_core_tb/config/wrapper_io_naming.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/fabric_tile_global_tile_clock_io_subtile/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/fabric_tile_global_tile_clock_io_subtile/config/task.conf new file mode 100644 index 000000000..1c477f704 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/fabric_tile_global_tile_clock_io_subtile/config/task.conf @@ -0,0 +1,42 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_registerable_io_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options= +openfpga_pb_pin_fixup_command= +openfpga_vpr_device=2x2_hybrid_io +openfpga_vpr_route_chan_width=20 +openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options=--explicit_port_mapping + + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_pipelined/and2_pipelined.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2_pipelined + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/fabric_tile_global_tile_clock_io_subtile/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/tile_organization/fabric_tile_global_tile_clock_io_subtile/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/fabric_tile_global_tile_clock_io_subtile/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/hetero_fabric_tile/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/hetero_fabric_tile/config/task.conf new file mode 100644 index 000000000..59b8ff81d --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/hetero_fabric_tile/config/task.conf @@ -0,0 +1,54 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_dsp8_caravel_io_skywater130nm_fdhd_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options=--constant_net_method route --skip_sync_clustering_and_routing_results on +openfpga_pb_pin_fixup_command = pb_pin_fixup --verbose +openfpga_vpr_device=3x2 +openfpga_vpr_route_chan_width=60 +openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_2/mac_2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_4/mac_4.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_6/mac_6.v +bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/mac/mac_8/mac_8.v + +[SYNTHESIS_PARAM] +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm_cell_sim.v +bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k4_frac_N8_tileable_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm_dsp_map.v +bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=8 -D DSP_B_MAXWIDTH=8 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_8x8 +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dsp_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys + +bench0_top = mac_2 +bench1_top = mac_4 +bench2_top = mac_6 +bench3_top = mac_8 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/hetero_fabric_tile/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/tile_organization/hetero_fabric_tile/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/hetero_fabric_tile/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile/config/task.conf new file mode 100644 index 000000000..c07a08d33 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile/config/task.conf @@ -0,0 +1,35 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_tile_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_2x2_preconfig/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_2x2_preconfig/config/task.conf new file mode 100644 index 000000000..127d9efc7 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_2x2_preconfig/config/task.conf @@ -0,0 +1,41 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options= +openfpga_pb_pin_fixup_command= +openfpga_vpr_device=2x2 +openfpga_vpr_route_chan_width=20 +openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options=--explicit_port_mapping + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_2x2_preconfig/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_2x2_preconfig/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_2x2_preconfig/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_4x4_preconfig/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_4x4_preconfig/config/task.conf new file mode 100644 index 000000000..38f1c7114 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_4x4_preconfig/config/task.conf @@ -0,0 +1,41 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options= +openfpga_pb_pin_fixup_command= +openfpga_vpr_device=4x4 +openfpga_vpr_route_chan_width=20 +openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options=--explicit_port_mapping + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_4x4_preconfig/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_4x4_preconfig/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_4x4_preconfig/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_adder_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_adder_chain/config/task.conf new file mode 100644 index 000000000..9268b12bc --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_adder_chain/config/task.conf @@ -0,0 +1,48 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options= +openfpga_pb_pin_fixup_command= +openfpga_vpr_device=auto +openfpga_vpr_route_chan_width=40 +openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/adder/adder_8/adder_8.v + +[SYNTHESIS_PARAM] +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_adders_sim.v +bench_yosys_adder_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_arith_map.v +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_adder_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys + +# Benchmark information +bench0_top = adder_8 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_adder_chain/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_adder_chain/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_adder_chain/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_clkntwk/config/clk_arch_1clk_2layer.xml b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_clkntwk/config/clk_arch_1clk_2layer.xml new file mode 100644 index 000000000..0570406fd --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_clkntwk/config/clk_arch_1clk_2layer.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_clkntwk/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_clkntwk/config/task.conf new file mode 100644 index 000000000..b348f342d --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_clkntwk/config/task.conf @@ -0,0 +1,40 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_tile_clkntwk_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_Ntwk1clk2lvl_cc_openfpga.xml +openfpga_clock_arch_file=${PATH:TASK_DIR}/config/clk_arch_1clk_2layer.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_device=2x2 +openfpga_vpr_route_chan_width=24 +openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options=--explicit_port_mapping + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_Ntwk1clk2lvl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_clkntwk/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_clkntwk/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_clkntwk/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_global_tile_clock/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_global_tile_clock/config/task.conf new file mode 100644 index 000000000..11708b954 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_global_tile_clock/config/task.conf @@ -0,0 +1,41 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options= +openfpga_pb_pin_fixup_command= +openfpga_vpr_device=auto +openfpga_vpr_route_chan_width=20 +openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options=--explicit_port_mapping + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2_latch + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_global_tile_clock/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_global_tile_clock/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_global_tile_clock/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_preconfig/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_preconfig/config/task.conf new file mode 100644 index 000000000..2c397c1ac --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_preconfig/config/task.conf @@ -0,0 +1,41 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = false +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/group_tile_preconfig_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_vpr_extra_options= +openfpga_pb_pin_fixup_command= +openfpga_vpr_device=auto +openfpga_vpr_route_chan_width=20 +openfpga_group_tile_config_file=${PATH:TASK_DIR}/config/tile_config.xml +openfpga_verilog_testbench_options=--explicit_port_mapping + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_preconfig/config/tile_config.xml b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_preconfig/config/tile_config.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/homo_fabric_tile_preconfig/config/tile_config.xml @@ -0,0 +1 @@ + diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/io_subtile/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/io_subtile/config/task.conf new file mode 100644 index 000000000..feba1d962 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/io_subtile/config/task.conf @@ -0,0 +1,37 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_IoSubtile_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=2x2 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_IoSubtile_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/io_subtile_strong/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/io_subtile_strong/config/task.conf new file mode 100644 index 000000000..8f20754ba --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/tile_organization/io_subtile_strong/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_IoSubtile_cc_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=3x3 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_IoSubtile_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = or2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +vpr_fpga_verilog_formal_verification_top_netlist= diff --git a/openfpga_flow/tasks/basic_tests/tile_organization/tileable_io/config/task.conf b/openfpga_flow/tasks/basic_tests/tile_organization/tileable_io/config/task.conf index d2359135e..291d214b4 100644 --- a/openfpga_flow/tasks/basic_tests/tile_organization/tileable_io/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/tile_organization/tileable_io/config/task.conf @@ -30,7 +30,6 @@ bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v [SYNTHESIS_PARAM] bench_read_verilog_options_common = -nolatches bench0_top = or2 -bench0_chan_width = 300 [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= diff --git a/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/fpga_core_wrapper/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/fpga_core_wrapper/config/task.conf new file mode 100644 index 000000000..9d6eb21a2 --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/generate_bitstream/fpga_core_wrapper/config/task.conf @@ -0,0 +1,33 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_bitstream_fpga_core_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SYNTHESIS_PARAM] +bench_read_verilog_options_common = -nolatches +bench0_top = and2 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] diff --git a/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/config/dummy_pin_constraints.xml b/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/config/dummy_pin_constraints.xml new file mode 100644 index 000000000..c7bb833ec --- /dev/null +++ b/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/config/dummy_pin_constraints.xml @@ -0,0 +1,4 @@ + + + + diff --git a/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/config/task.conf b/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/config/task.conf index 839bd3e09..d9a5f151a 100644 --- a/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/config/task.conf +++ b/openfpga_flow/tasks/fpga_verilog/adder/hard_adder/config/task.conf @@ -9,29 +9,34 @@ [GENERAL] run_engine=openfpga_shell power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml -power_analysis = true +power_analysis = false spice_output=false verilog_output=true timeout_each_job = 20*60 -fpga_flow=vpr_blif +fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml -openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml -openfpga_vpr_device_layout=2x2 +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml +openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/dummy_pin_constraints.xml [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/adder/adder_8/adder_8.v [SYNTHESIS_PARAM] -bench0_top = and2 -bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act -bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v -bench0_chan_width = 300 +# Yosys script parameters +bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_adders_sim.v +bench_yosys_adder_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_arith_map.v +bench_read_verilog_options_common = -nolatches +bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_adder_flow.ys +bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys + +# Benchmark information +bench0_top = adder_8 [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= diff --git a/openfpga_flow/vpr_arch/README.md b/openfpga_flow/vpr_arch/README.md index f4f215fde..cbec4f286 100644 --- a/openfpga_flow/vpr_arch/README.md +++ b/openfpga_flow/vpr_arch/README.md @@ -21,6 +21,7 @@ Please reveal the following architecture features in the names to help quickly s - multi\_io\_capacity: If I/O capacity is different on each side of FPGAs. - reduced\_io: If I/Os only appear a certain or multiple sides of FPGAs - registerable\_io: If I/Os are registerable (can be either combinational or sequential) +- IoSubtile: If I/O block contains sub tiles (more compact with a higher density of I/Os) - CustomIoLoc: Use OpenFPGA's extended custom I/O location syntax - rstOnLut: The reset signal of CLB can feed LUT inputs through a local routing architecture - localClkGen: The clock signal of CLB can be generated by internal programmable resources diff --git a/openfpga_flow/vpr_arch/k4_N4_tileableL_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileableL_40nm.xml new file mode 100644 index 000000000..73abed84a --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_N4_tileableL_40nm.xml @@ -0,0 +1,360 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + io_topL.outpad io_topL.inpad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml index 1f8022119..542527c53 100644 --- a/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_registerable_io_40nm.xml @@ -34,6 +34,11 @@ + + + + + @@ -55,6 +60,41 @@ + + + + + + + + + + + + io_input.inpad io_input.clk + io_input.inpad io_input.clk + io_input.inpad io_input.clk + io_input.inpad io_input.clk + + + + + + + + + + + + + + io.outpad io.inpad io.clk + io.outpad io.inpad io.clk + io.outpad io.inpad io.clk + io.outpad io.inpad io.clk + + + @@ -87,6 +127,13 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fpga_input_center[1:0].inpad + fpga_input_center[3:2].inpad + fpga_input_center[4:4].inpad + fpga_input_center[5:5].inpad + + + + + + + + + + fpga_output_center[1:0].outpad + + fpga_output_center[3:2].outpad + + + + + + + + + + + + + fpga_input.inpad + fpga_input.inpad + fpga_input.inpad + fpga_input.inpad + + + + + + + + + + fpga_output.outpad + fpga_output.outpad + fpga_output.outpad + fpga_output.outpad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml index da117fa5f..c51132506 100644 --- a/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_TileOrgzTl_40nm.xml @@ -87,6 +87,13 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + + clb.clk + clb.cin + clb.O[3:0] clb.I[5:0] + clb.cout clb.O[7:4] clb.I[11:6] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 + 1 + + + + 1 1 1 + 1 1 + + + + 1 1 1 1 1 + 1 1 1 1 + + + + 1 1 + 1 + + + + 1 1 1 + 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 195e-12 + 195e-12 + 195e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k4_frac_N4_tileable_adder_chain_mem1K_L124_ChanWidth0p8_40nm.xml b/openfpga_flow/vpr_arch/k4_frac_N4_tileable_adder_chain_mem1K_L124_ChanWidth0p8_40nm.xml new file mode 100644 index 000000000..35d56c98f --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_frac_N4_tileable_adder_chain_mem1K_L124_ChanWidth0p8_40nm.xml @@ -0,0 +1,723 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + + clb.clk + clb.cin + clb.O[3:0] clb.I[5:0] + clb.cout clb.O[7:4] clb.I[11:6] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 + 1 + + + + 1 1 1 + 1 1 + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 195e-12 + 195e-12 + 195e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/vpr_arch/k4_frac_N8_tileableL_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml b/openfpga_flow/vpr_arch/k4_frac_N8_tileableL_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml new file mode 100644 index 000000000..ec63d7779 --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_frac_N8_tileableL_reset_softadder_register_scan_chain_dsp8_nonLR_caravel_io_skywater130nm.xml @@ -0,0 +1,933 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io_top.outpad io_top.inpad + + + + + + + + + + + + + + io_right.outpad io_right.inpad + + + + + + + + + + + + + + io_bottom.outpad io_bottom.inpad + + + + + + + + + + + + + + io_left.outpad io_left.inpad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + clb.clk clb.reset + clb.reg_in clb.sc_in clb.cin clb.O[7:0] clb.I0 clb.I0i clb.I1 clb.I1i clb.I2 clb.I2i clb.I3 clb.I3i + clb.O[15:8] clb.I4 clb.I4i clb.I5 clb.I5i clb.I6 clb.I6i clb.I7 clb.I7i + clb.reg_out clb.sc_out clb.cout + + + + + + + + + + + + + + + + + + mult_8.a[0:2] mult_8.b[0:2] mult_8.out[0:5] + mult_8.a[3:5] mult_8.b[3:5] mult_8.out[6:10] + mult_8.a[6:7] mult_8.b[6:7] mult_8.out[11:15] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 + 1 + + + + 1 1 1 + 1 1 + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vtr-verilog-to-routing b/vtr-verilog-to-routing index 90ee6e663..254d38faa 160000 --- a/vtr-verilog-to-routing +++ b/vtr-verilog-to-routing @@ -1 +1 @@ -Subproject commit 90ee6e663a0e021604dff4552f5b7f9744cedd74 +Subproject commit 254d38faa02884c9b48d6a82e18fd54d9b567d44 diff --git a/yosys b/yosys index 51dd02902..73cb4977b 160000 --- a/yosys +++ b/yosys @@ -1 +1 @@ -Subproject commit 51dd0290241c521f5498f71f4fd4fb0598d83a76 +Subproject commit 73cb4977b2e493b840b23419919a63be7c83e6df diff --git a/yosys-plugins b/yosys-plugins index 6b69bc5ed..834794d59 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 6b69bc5ed8eafbaca6f143062dbe0c486a8a37b3 +Subproject commit 834794d592bf2f31e7125f9ef103d76110e63281