Merge branch 'lnis-uofu:master' into master

This commit is contained in:
chungshien 2024-06-17 20:49:39 -07:00 committed by GitHub
commit beb46c994b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
321 changed files with 28417 additions and 1483 deletions

View File

@ -1,13 +1,19 @@
name: Test
# Run CI on push, PR, and weekly.
on:
push:
workflow_dispatch:
pull_request:
push:
branches:
- 'master'
schedule:
- cron: "0 0 * * 0 " # weekly
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Environment variables
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
@ -22,7 +28,7 @@ env:
jobs:
change_detect:
name: "Detect code changes"
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
outputs:
# this is output as string, see https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs
source_modified: ${{ steps.changes.outputs.status_code == '1' }}
@ -36,7 +42,7 @@ jobs:
access_token: ${{ github.token }}
- name: Checkout OpenFPGA repo
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@ -67,7 +73,7 @@ jobs:
needs: change_detect
if: ${{ fromJSON(needs.change_detect.outputs.source_modified) }}
name: ${{ matrix.config.name }}
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
# Note: dependencies are installed in the container. See details about dependency list in docker/Dockerfile.master
# Comment the line out when base image is built again
#container: ghcr.io/${{ needs.change_detect.outputs.docker_repo }}/openfpga-build-${{ matrix.config.cc}}
@ -76,30 +82,38 @@ jobs:
fail-fast: false
matrix:
config:
- name: "Build Compatibility: GCC-8 (Ubuntu 20.04)"
cc: gcc-8
cxx: g++-8
- name: "Build Compatibility: GCC-9 (Ubuntu 20.04)"
- name: "Build Compatibility: GCC-9 (Ubuntu 22.04)"
cc: gcc-9
cxx: g++-9
- name: "Build Compatibility: GCC-10 (Ubuntu 20.04)"
dependency_version: "ubuntu22p04"
- name: "Build Compatibility: GCC-10 (Ubuntu 22.04)"
cc: gcc-10
cxx: g++-10
- name: "Build Compatibility: GCC-11 (Ubuntu 20.04)"
dependency_version: "ubuntu22p04"
- name: "Build Compatibility: GCC-11 (Ubuntu 22.04)"
cc: gcc-11
cxx: g++-11
- name: "Build Compatibility: Clang-6 (Ubuntu 20.04)"
cc: clang-6.0
cxx: clang++-6.0
- name: "Build Compatibility: Clang-7 (Ubuntu 20.04)"
cc: clang-7
cxx: clang++-7
- name: "Build Compatibility: Clang-8 (Ubuntu 20.04)"
cc: clang-8
cxx: clang++-8
- name: "Build Compatibility: Clang-10 (Ubuntu 20.04)"
cc: clang-10
cxx: clang++-10
dependency_version: "ubuntu22p04"
- name: "Build Compatibility: GCC-12 (Ubuntu 22.04)"
cc: gcc-12
cxx: g++-12
dependency_version: "ubuntu22p04"
- name: "Build Compatibility: Clang-11 (Ubuntu 22.04)"
cc: clang-11
cxx: clang++-11
dependency_version: "ubuntu22p04"
- name: "Build Compatibility: Clang-12 (Ubuntu 22.04)"
cc: clang-12
cxx: clang++-12
dependency_version: "ubuntu22p04"
- name: "Build Compatibility: Clang-13 (Ubuntu 22.04)"
cc: clang-13
cxx: clang++-13
dependency_version: "ubuntu22p04"
- name: "Build Compatibility: Clang-14 (Ubuntu 22.04)"
cc: clang-14
cxx: clang++-14
dependency_version: "ubuntu22p04"
# Define the steps to run the build job
env:
CC: ${{ matrix.config.cc }}
@ -111,10 +125,10 @@ jobs:
access_token: ${{ github.token }}
- name: Checkout OpenFPGA repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install dependencies
run: sudo bash ./.github/workflows/install_dependencies_build.sh
run: sudo bash ./.github/workflows/install_dependencies_build_${{ matrix.config.dependency_version }}.sh
- name: Dump tool versions
run: |
@ -129,12 +143,18 @@ jobs:
run: |
make all BUILD_TYPE=$BUILD_TYPE
- name: Clear error log
if: ${{ failure() }}
shell: bash
run: |
make all BUILD_TYPE=$BUILD_TYPE -j1
# Check the cache size and see if it is over the limit
- name: Check ccache size
run: ccache -s
- name: Upload artifact
uses: actions/upload-artifact@v2
if: ${{ matrix.config.cc == 'gcc-9'}}
if: ${{ matrix.config.cc == 'gcc-11'}}
with:
name: openfpga
path: |
@ -151,11 +171,12 @@ jobs:
openfpga_flow
openfpga.sh
linux_build_opt:
needs: change_detect
if: ${{ fromJSON(needs.change_detect.outputs.source_modified) }}
name: ${{ matrix.config.name }}
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
# Note: dependencies are installed in the container. See details about dependency list in docker/Dockerfile.master
# Comment the line out when base image is built again
#container: ghcr.io/${{ needs.change_detect.outputs.docker_repo }}/openfpga-build-${{ matrix.config.cc}}
@ -164,26 +185,31 @@ jobs:
fail-fast: false
matrix:
config:
- name: "Build w/o Yosys (Ubuntu 20.04)"
cc: gcc-9
cxx: g++-9
- name: "Build w/o Yosys (Ubuntu 22.04)"
cc: gcc-11
cxx: g++-11
cmake_flags: "-DOPENFPGA_WITH_YOSYS=OFF"
- name: "Build w/o Yosys plugin (Ubuntu 20.04)"
cc: gcc-9
cxx: g++-9
dependency_version: "ubuntu22p04"
- name: "Build w/o Yosys plugin (Ubuntu 22.04)"
cc: gcc-11
cxx: g++-11
cmake_flags: "-DOPENFPGA_WITH_YOSYS_PLUGIN=OFF"
- name: "Build w/o test (Ubuntu 20.04)"
cc: gcc-9
cxx: g++-9
dependency_version: "ubuntu22p04"
- name: "Build w/o test (Ubuntu 22.04)"
cc: gcc-11
cxx: g++-11
cmake_flags: "-DOPENFPGA_WITH_TEST=OFF"
- name: "Build w/o version number (Ubuntu 20.04)"
cc: gcc-9
cxx: g++-9
dependency_version: "ubuntu22p04"
- name: "Build w/o version number (Ubuntu 22.04)"
cc: gcc-11
cxx: g++-11
cmake_flags: "-DOPENFPGA_WITH_VERSION=OFF"
- name: "Build w/o SWIG support (Ubuntu 20.04)"
cc: gcc-9
cxx: g++-9
dependency_version: "ubuntu22p04"
- name: "Build w/o SWIG support (Ubuntu 22.04)"
cc: gcc-11
cxx: g++-11
cmake_flags: "-DOPENFPGA_WITH_SWIG=OFF"
dependency_version: "ubuntu22p04"
# Define the steps to run the build job
env:
CC: ${{ matrix.config.cc }}
@ -195,10 +221,10 @@ jobs:
access_token: ${{ github.token }}
- name: Checkout OpenFPGA repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install dependencies
run: sudo bash ./.github/workflows/install_dependencies_build.sh
run: sudo bash ./.github/workflows/install_dependencies_build_${{ matrix.config.dependency_version }}.sh
- name: Dump tool versions
run: |
@ -217,14 +243,19 @@ jobs:
needs: change_detect
if: ${{ fromJSON(needs.change_detect.outputs.source_modified) }}
name: ${{ matrix.config.name }}
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
config:
- name: "Build (Ubuntu 22.04)"
- name: "Build (GCC-11 on Ubuntu 20.04)"
cc: gcc-11
cxx: g++-11
dependency_version: "ubuntu20p04"
- name: "Build (Clang-10 on Ubuntu 20.04)"
cc: clang-10
cxx: clang++-10
dependency_version: "ubuntu20p04"
# Define the steps to run the build job
env:
CC: ${{ matrix.config.cc }}
@ -236,10 +267,10 @@ jobs:
access_token: ${{ github.token }}
- name: Checkout OpenFPGA repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install dependencies
run: sudo bash ./.github/workflows/install_dependencies_build_ubuntu22p04.sh
run: sudo bash ./.github/workflows/install_dependencies_build_${{ matrix.config.dependency_version }}.sh
- name: Dump tool versions
run: |
@ -270,6 +301,7 @@ jobs:
cxx: g++-11
build_type: debug
cores: 4
dependency_version: "ubuntu22p04"
# Define the steps to run the build job
env:
CC: ${{ matrix.config.cc }}
@ -281,12 +313,12 @@ jobs:
access_token: ${{ github.token }}
- name: Checkout OpenFPGA repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo bash ./.github/workflows/install_dependencies_build_ubuntu22p04.sh
sudo bash ./.github/workflows/install_dependencies_run_ubuntu22p04.sh
sudo bash ./.github/workflows/install_dependencies_build_${{ matrix.config.dependency_version }}.sh
sudo bash ./.github/workflows/install_dependencies_run_${{ matrix.config.dependency_version }}.sh
sudo python3 -m pip install -r requirements.txt
- name: Dump tool versions
@ -321,6 +353,7 @@ jobs:
cxx: g++-11
build_type: release
cores: 4
dependency_version: "ubuntu22p04"
# Define the steps to run the build job
env:
CC: ${{ matrix.config.cc }}
@ -332,12 +365,12 @@ jobs:
access_token: ${{ github.token }}
- name: Checkout OpenFPGA repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo bash ./.github/workflows/install_dependencies_build_ubuntu22p04.sh
sudo bash ./.github/workflows/install_dependencies_run_ubuntu22p04.sh
sudo bash ./.github/workflows/install_dependencies_build_${{ matrix.config.dependency_version }}.sh
sudo bash ./.github/workflows/install_dependencies_run_${{ matrix.config.dependency_version }}.sh
sudo python3 -m pip install -r requirements.txt
- name: Dump tool versions
@ -360,7 +393,7 @@ jobs:
docker_distribution:
name: Build docker image for distribution
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
needs: [linux_build, change_detect]
steps:
- name: Cancel previous
@ -369,7 +402,7 @@ jobs:
access_token: ${{ github.token }}
- name: Checkout OpenFPGA repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Download a built artifacts
uses: actions/download-artifact@v2
with:
@ -397,7 +430,7 @@ jobs:
linux_regression_tests:
name: linux_regression_tests
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
needs: [linux_build, change_detect]
container: ghcr.io/${{ needs.change_detect.outputs.docker_repo }}/openfpga-env
strategy:
@ -422,7 +455,7 @@ jobs:
access_token: ${{ github.token }}
- name: Checkout OpenFPGA repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Download a built artifacts
uses: actions/download-artifact@v2
with:
@ -438,7 +471,7 @@ jobs:
chmod +x build/yosys/bin/yosys-config
chmod +x build/yosys/bin/yosys-filterlib
chmod +x build/yosys/bin/yosys-smtbmc
- name: ${{matrix.config.name}}_GCC-9_(Ubuntu 20.04)
- name: ${{matrix.config.name}}_GCC-11_(Ubuntu 22.04)
shell: bash
run: source openfpga.sh && source openfpga_flow/regression_test_scripts/${{matrix.config.name}}.sh --debug --show_thread_logs
- name: Upload artifact
@ -454,7 +487,7 @@ jobs:
needs: change_detect
if: ${{ !fromJSON(needs.change_detect.outputs.source_modified) }}
name: docker_regression_tests
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
container:
image: ghcr.io/${{ needs.change_detect.outputs.docker_repo }}/openfpga-master:latest
options: --user root --workdir /home/openfpga_user
@ -480,12 +513,12 @@ jobs:
access_token: ${{ github.token }}
- name: Checkout OpenFPGA repo
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: ${{matrix.config.name}}_GCC-9_(Ubuntu 20.04)
- name: ${{matrix.config.name}}_GCC-11_(Ubuntu 22.04)
shell: bash
run: |
bash .github/workflows/install_dependencies_run.sh
bash .github/workflows/install_dependencies_run_ubuntu22p04.sh
${PYTHON_EXEC} -m pip install -r requirements.txt
rsync -am --exclude='openfpga_flow/**' /opt/openfpga/. .
unset OPENFPGA_PATH

View File

@ -1,13 +1,19 @@
name: Cell Library Tests
# Run CI on push, PR, and weekly.
on:
push:
workflow_dispatch:
pull_request:
push:
branches:
- 'master'
schedule:
- cron: "0 0 * * 0 " # weekly
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Multiple job to tests
jobs:
# Test the RTL compilation compatibility

View File

@ -7,10 +7,14 @@ env:
DOCKER_REPO: ${{ secrets.DOCKER_REPO }}
REPO_OWNER: ${{ github.repository_owner }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
change_detect:
name: "Detect code changes"
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
outputs:
docker_repo: ${{ steps.changes.outputs.docker_repo }}
steps:
@ -31,7 +35,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
@ -64,18 +68,17 @@ jobs:
strategy:
matrix:
compiler:
- gcc-7
- gcc-8
- gcc-9
- gcc-10
- gcc-11
- clang-6.0
- clang-7
- clang-8
- clang-10
- gcc-12
- clang-11
- clang-12
- clang-13
- clang-14
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx

View File

@ -3,26 +3,36 @@ name: Code Format
# Run CI on push, PR, and weekly.
on:
push:
workflow_dispatch:
pull_request:
push:
branches:
- 'master'
schedule:
- cron: "0 0 * * 0 " # weekly
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Multiple job to tests
jobs:
change_detect:
name: "Check"
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
config:
- name: "C/C++"
code_type: "-cpp"
dependency_version: "ubuntu22p04"
- name: "XML"
code_type: "-xml"
dependency_version: "ubuntu22p04"
- name: "Python"
code_type: "-py"
dependency_version: "ubuntu22p04"
steps:
- name: Cancel previous
uses: styfle/cancel-workflow-action@0.9.1
@ -34,12 +44,12 @@ jobs:
- name: Install dependencies
run: |
sudo bash ./.github/workflows/install_dependencies_build.sh
sudo bash ./.github/workflows/install_dependencies_build_${{ matrix.config.dependency_version }}.sh
sudo python3 -m pip install -r requirements.txt
- name: Dump tool versions
run: |
clang-format-10 --version
clang-format-14 --version
black --version
- name: Check format

View File

@ -53,6 +53,9 @@ apt-get install -y \
gcc-10 \
g++-11 \
gcc-11 \
clang-11 \
clang-12 \
clang-format-12 \
clang-13 \
clang-14 \
clang-format-14 \
libxml2-utils

View File

@ -1,8 +1,9 @@
name: Count Patches
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
push:
branches:
- 'master'
env:
TAG_COMMIT: 8ee3fb8..
@ -41,6 +42,7 @@ jobs:
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{env.BRANCH_NAME}}
force: true
- name: Create Auto PR
if: "!contains(steps.log.outputs.message, 'Updated Patch Count') && contains(steps.repo.outputs.message, 'lnis-uofu/OpenFPGA')"

View File

@ -42,7 +42,7 @@ endif
# Define executables
PYTHON_EXEC ?= python3
CLANG_FORMAT_EXEC ?= clang-format-10
CLANG_FORMAT_EXEC ?= clang-format-14
XML_FORMAT_EXEC ?= xmllint
PYTHON_FORMAT_EXEC ?= black

View File

@ -11,16 +11,19 @@ Version: see [`VERSION.md`](VERSION.md)
The award-winning OpenFPGA framework is the **first open-source FPGA IP generator with silicon proofs** supporting highly-customizable FPGA architectures. OpenFPGA provides complete EDA support for customized FPGAs, including Verilog-to-bitstream generation and self-testing verification. OpenFPGA opens the door to democratizing FPGA technology and EDA techniques with agile prototyping approaches and constantly evolving EDA tools for chip designers and researchers.
**If this is your first time working with OpenFPGA, we strongly **recommend you watch the** [introduction video about OpenFPGA](https://youtu.be/ocODUGcYGqo)**
> [!TIP]
> If this is your first time working with OpenFPGA, we strongly recommend you watch the [introduction video about OpenFPGA](https://youtu.be/ocODUGcYGqo)
A quick overview of OpenFPGA tools can be found [**here**](https://openfpga.readthedocs.io/en/master/tutorials/getting_started/tools/).
We also recommend potential users check out the summary of [**technical capabilities**](https://openfpga.readthedocs.io/en/master/overview/tech_highlights/#) before compiling.
**Before asking for help, please checkout the** [Frequently Asked Questions](https://github.com/lnis-uofu/OpenFPGA/discussions/937)
> [!TIP]
> Before asking for help, please checkout the [Frequently Asked Questions](https://github.com/lnis-uofu/OpenFPGA/discussions/937)
## Compilation
**A tutorial **video about **how to compile** can be** found [here](https://youtu.be/F9sMRmDewM0)**
> [!NOTE]
> A tutorial video about how to compile can be found [here](https://youtu.be/F9sMRmDewM0)
Detailed guidelines are available at [**compilation guidelines**](https://openfpga.readthedocs.io/en/master/tutorials/getting_started/compile/).
Before starting, we strongly recommend you read the required dependencies and ensure that they are correctly installed.
@ -36,7 +39,7 @@ You can find a set of [tutorials](https://openfpga.readthedocs.io/en/master/tuto
## Backward Compatibility
If you were using an old version of OpenFPGA and are now interested to move to the latest version, please check out the [developer guidelines](https://openfpga.readthedocs.io/en/master/dev_manual/back_compatibile).
If you were using an old version of OpenFPGA and are now interested to move to the latest version, please check out the [developer guidelines](https://openfpga.readthedocs.io/en/master/dev_manual/back_compatible/).
## License
@ -54,8 +57,8 @@ Bibtex:
@ARTICLE{9098028, author={Tang, Xifan and Giacomin, Edouard and Chauviere, Baudouin and Alacchi, Aurélien and Gaillardon, Pierre-Emmanuel}, journal={IEEE Micro}, title={OpenFPGA: An Open-Source Framework for Agile Prototyping Customizable FPGAs}, year={2020}, volume={40}, number={4}, pages={41-48}, doi={10.1109/MM.2020.2995854}}
```
A list of related publications can be found [here](https://openfpga.readthedocs.io/en/master/reference/).
A list of related publications can be found [here](https://openfpga.readthedocs.io/en/master/appendix/reference/).
## Contributing to OpenFPGA
Please read the [contributor guidelines](https://openfpga.readthedocs.io/en/master/dev_manual/contributor_guide) if you would like to contribute to OpenFPGA.
Please read the [contributor guidelines](https://openfpga.readthedocs.io/en/master/dev_manual/contributor_guide/) if you would like to contribute to OpenFPGA.

View File

@ -1 +1 @@
1.2.1961
1.2.2258

View File

@ -1,303 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2015 Justus Calvin
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# FindTBB
# -------
#
# Find TBB include directories and libraries.
#
# Usage:
#
# find_package(TBB [major[.minor]] [EXACT]
# [QUIET] [REQUIRED]
# [[COMPONENTS] [components...]]
# [OPTIONAL_COMPONENTS components...])
#
# where the allowed components are tbbmalloc and tbb_preview. Users may modify
# the behavior of this module with the following variables:
#
# * TBB_ROOT_DIR - The base directory the of TBB installation.
# * TBB_INCLUDE_DIR - The directory that contains the TBB headers files.
# * TBB_LIBRARY - The directory that contains the TBB library files.
# * TBB_<library>_LIBRARY - The path of the TBB the corresponding TBB library.
# These libraries, if specified, override the
# corresponding library search results, where <library>
# may be tbb, tbb_debug, tbbmalloc, tbbmalloc_debug,
# tbb_preview, or tbb_preview_debug.
# * TBB_USE_DEBUG_BUILD - The debug version of tbb libraries, if present, will
# be used instead of the release version.
#
# Users may modify the behavior of this module with the following environment
# variables:
#
# * TBB_INSTALL_DIR
# * TBBROOT
# * LIBRARY_PATH
#
# This module will set the following variables:
#
# * TBB_FOUND - Set to false, or undefined, if we havent found, or
# dont want to use TBB.
# * TBB_<component>_FOUND - If False, optional <component> part of TBB sytem is
# not available.
# * TBB_VERSION - The full version string
# * TBB_VERSION_MAJOR - The major version
# * TBB_VERSION_MINOR - The minor version
# * TBB_INTERFACE_VERSION - The interface version number defined in
# tbb/tbb_stddef.h.
# * TBB_<library>_LIBRARY_RELEASE - The path of the TBB release version of
# <library>, where <library> may be tbb, tbb_debug,
# tbbmalloc, tbbmalloc_debug, tbb_preview, or
# tbb_preview_debug.
# * TBB_<library>_LIBRARY_DEGUG - The path of the TBB release version of
# <library>, where <library> may be tbb, tbb_debug,
# tbbmalloc, tbbmalloc_debug, tbb_preview, or
# tbb_preview_debug.
#
# The following varibles should be used to build and link with TBB:
#
# * TBB_INCLUDE_DIRS - The include directory for TBB.
# * TBB_LIBRARIES - The libraries to link against to use TBB.
# * TBB_LIBRARIES_RELEASE - The release libraries to link against to use TBB.
# * TBB_LIBRARIES_DEBUG - The debug libraries to link against to use TBB.
# * TBB_DEFINITIONS - Definitions to use when compiling code that uses
# TBB.
# * TBB_DEFINITIONS_RELEASE - Definitions to use when compiling release code that
# uses TBB.
# * TBB_DEFINITIONS_DEBUG - Definitions to use when compiling debug code that
# uses TBB.
#
# This module will also create the "tbb" target that may be used when building
# executables and libraries.
include(FindPackageHandleStandardArgs)
if(NOT TBB_FOUND)
##################################
# Check the build type
##################################
if(NOT DEFINED TBB_USE_DEBUG_BUILD)
if(CMAKE_BUILD_TYPE MATCHES "(Debug|DEBUG|debug|RelWithDebInfo|RELWITHDEBINFO|relwithdebinfo)")
set(TBB_BUILD_TYPE DEBUG)
else()
set(TBB_BUILD_TYPE RELEASE)
endif()
elseif(TBB_USE_DEBUG_BUILD)
set(TBB_BUILD_TYPE DEBUG)
else()
set(TBB_BUILD_TYPE RELEASE)
endif()
##################################
# Set the TBB search directories
##################################
# Define search paths based on user input and environment variables
set(TBB_SEARCH_DIR ${TBB_ROOT_DIR} $ENV{TBB_INSTALL_DIR} $ENV{TBBROOT})
# Define the search directories based on the current platform
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(TBB_DEFAULT_SEARCH_DIR "C:/Program Files/Intel/TBB"
"C:/Program Files (x86)/Intel/TBB")
# Set the target architecture
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(TBB_ARCHITECTURE "intel64")
else()
set(TBB_ARCHITECTURE "ia32")
endif()
# Set the TBB search library path search suffix based on the version of VC
if(WINDOWS_STORE)
set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc11_ui")
elseif(MSVC14)
set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc14")
elseif(MSVC12)
set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc12")
elseif(MSVC11)
set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc11")
elseif(MSVC10)
set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc10")
endif()
# Add the library path search suffix for the VC independent version of TBB
list(APPEND TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc_mt")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# OS X
set(TBB_DEFAULT_SEARCH_DIR "/opt/intel/tbb")
# TODO: Check to see which C++ library is being used by the compiler.
if(NOT ${CMAKE_SYSTEM_VERSION} VERSION_LESS 13.0)
# The default C++ library on OS X 10.9 and later is libc++
set(TBB_LIB_PATH_SUFFIX "lib/libc++" "lib")
else()
set(TBB_LIB_PATH_SUFFIX "lib")
endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
# Linux
set(TBB_DEFAULT_SEARCH_DIR "/opt/intel/tbb")
# TODO: Check compiler version to see the suffix should be <arch>/gcc4.1 or
# <arch>/gcc4.1. For now, assume that the compiler is more recent than
# gcc 4.4.x or later.
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
set(TBB_LIB_PATH_SUFFIX "lib/intel64/gcc4.4")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$")
set(TBB_LIB_PATH_SUFFIX "lib/ia32/gcc4.4")
endif()
endif()
##################################
# Find the TBB include dir
##################################
find_path(TBB_INCLUDE_DIRS tbb/tbb.h
HINTS ${TBB_INCLUDE_DIR} ${TBB_SEARCH_DIR}
PATHS ${TBB_DEFAULT_SEARCH_DIR}
PATH_SUFFIXES include)
##################################
# Set version strings
##################################
if(TBB_INCLUDE_DIRS)
file(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _tbb_version_file)
string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1"
TBB_VERSION_MAJOR "${_tbb_version_file}")
string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1"
TBB_VERSION_MINOR "${_tbb_version_file}")
string(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1"
TBB_INTERFACE_VERSION "${_tbb_version_file}")
set(TBB_VERSION "${TBB_VERSION_MAJOR}.${TBB_VERSION_MINOR}")
endif()
##################################
# Find TBB components
##################################
if(TBB_VERSION VERSION_LESS 4.3)
set(TBB_SEARCH_COMPOMPONENTS tbb_preview tbbmalloc tbb)
else()
set(TBB_SEARCH_COMPOMPONENTS tbb_preview tbbmalloc_proxy tbbmalloc tbb)
endif()
# Find each component
foreach(_comp ${TBB_SEARCH_COMPOMPONENTS})
if(";${TBB_FIND_COMPONENTS};tbb;" MATCHES ";${_comp};")
# Search for the libraries
find_library(TBB_${_comp}_LIBRARY_RELEASE ${_comp}
HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR}
PATHS ${TBB_DEFAULT_SEARCH_DIR} ENV LIBRARY_PATH
PATH_SUFFIXES ${TBB_LIB_PATH_SUFFIX})
find_library(TBB_${_comp}_LIBRARY_DEBUG ${_comp}_debug
HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR}
PATHS ${TBB_DEFAULT_SEARCH_DIR} ENV LIBRARY_PATH
PATH_SUFFIXES ${TBB_LIB_PATH_SUFFIX})
if(TBB_${_comp}_LIBRARY_DEBUG)
list(APPEND TBB_LIBRARIES_DEBUG "${TBB_${_comp}_LIBRARY_DEBUG}")
endif()
if(TBB_${_comp}_LIBRARY_RELEASE)
list(APPEND TBB_LIBRARIES_RELEASE "${TBB_${_comp}_LIBRARY_RELEASE}")
endif()
if(TBB_${_comp}_LIBRARY_${TBB_BUILD_TYPE} AND NOT TBB_${_comp}_LIBRARY)
set(TBB_${_comp}_LIBRARY "${TBB_${_comp}_LIBRARY_${TBB_BUILD_TYPE}}")
endif()
if(TBB_${_comp}_LIBRARY AND EXISTS "${TBB_${_comp}_LIBRARY}")
set(TBB_${_comp}_FOUND TRUE)
else()
set(TBB_${_comp}_FOUND FALSE)
endif()
# Mark internal variables as advanced
mark_as_advanced(TBB_${_comp}_LIBRARY_RELEASE)
mark_as_advanced(TBB_${_comp}_LIBRARY_DEBUG)
mark_as_advanced(TBB_${_comp}_LIBRARY)
endif()
endforeach()
##################################
# Set compile flags and libraries
##################################
set(TBB_DEFINITIONS_RELEASE "")
set(TBB_DEFINITIONS_DEBUG "-DTBB_USE_DEBUG=1")
if(TBB_LIBRARIES_${TBB_BUILD_TYPE})
set(TBB_DEFINITIONS "${TBB_DEFINITIONS_${TBB_BUILD_TYPE}}")
set(TBB_LIBRARIES "${TBB_LIBRARIES_${TBB_BUILD_TYPE}}")
elseif(TBB_LIBRARIES_RELEASE)
set(TBB_DEFINITIONS "${TBB_DEFINITIONS_RELEASE}")
set(TBB_LIBRARIES "${TBB_LIBRARIES_RELEASE}")
elseif(TBB_LIBRARIES_DEBUG)
set(TBB_DEFINITIONS "${TBB_DEFINITIONS_DEBUG}")
set(TBB_LIBRARIES "${TBB_LIBRARIES_DEBUG}")
endif()
find_package_handle_standard_args(TBB
REQUIRED_VARS TBB_INCLUDE_DIRS TBB_LIBRARIES
HANDLE_COMPONENTS
VERSION_VAR TBB_VERSION)
##################################
# Create targets
##################################
if(NOT CMAKE_VERSION VERSION_LESS 3.0 AND TBB_FOUND)
add_library(tbb SHARED IMPORTED)
set_target_properties(tbb PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${TBB_INCLUDE_DIRS}
IMPORTED_LOCATION ${TBB_LIBRARIES})
if(TBB_LIBRARIES_RELEASE AND TBB_LIBRARIES_DEBUG)
set_target_properties(tbb PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "$<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:TBB_USE_DEBUG=1>"
IMPORTED_LOCATION_DEBUG ${TBB_LIBRARIES_DEBUG}
IMPORTED_LOCATION_RELWITHDEBINFO ${TBB_LIBRARIES_DEBUG}
IMPORTED_LOCATION_RELEASE ${TBB_LIBRARIES_RELEASE}
IMPORTED_LOCATION_MINSIZEREL ${TBB_LIBRARIES_RELEASE}
)
elseif(TBB_LIBRARIES_RELEASE)
set_target_properties(tbb PROPERTIES IMPORTED_LOCATION ${TBB_LIBRARIES_RELEASE})
else()
set_target_properties(tbb PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "${TBB_DEFINITIONS_DEBUG}"
IMPORTED_LOCATION ${TBB_LIBRARIES_DEBUG}
)
endif()
endif()
mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARIES)
unset(TBB_ARCHITECTURE)
unset(TBB_BUILD_TYPE)
unset(TBB_LIB_PATH_SUFFIX)
unset(TBB_DEFAULT_SEARCH_DIR)
endif()

View File

@ -1,9 +1,9 @@
FROM ubuntu:20.04
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install software-properties-common -y
# 18.04 includes 2.17 but github requires 2.18+ to support submodules.
RUN add-apt-repository ppa:git-core/ppa
ADD .github/workflows/install_dependencies_build.sh install_dependencies_build.sh
ADD .github/workflows/install_dependencies_build_ubuntu22p04.sh install_dependencies_build.sh
RUN bash install_dependencies_build.sh
ADD requirements.txt requirements.txt
RUN python3 -m pip install -r requirements.txt

View File

@ -1,2 +0,0 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y clang-format-7 clang-10

View File

@ -0,0 +1,2 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y clang-format-14 clang-11

View File

@ -0,0 +1,2 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y clang-format-14 clang-12

View File

@ -0,0 +1,2 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y clang-format-14 clang-13

View File

@ -0,0 +1,2 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y clang-format-14 clang-14

View File

@ -1,2 +0,0 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y clang-format-7 clang-6.0

View File

@ -1,2 +0,0 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y clang-format-7 clang-7

View File

@ -1,2 +0,0 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y clang-format-7 clang-8

View File

@ -1,15 +1,13 @@
FROM ubuntu:20.04
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install --no-install-recommends software-properties-common -y
# 18.04 includes 2.17 but github requires 2.18+ to support submodules.
#RUN add-apt-repository ppa:git-core/ppa
ADD .github/workflows/install_dependencies_run.sh install_dependencies_run.sh
ADD .github/workflows/install_dependencies_run_ubuntu22p04.sh install_dependencies_run.sh
RUN bash install_dependencies_run.sh
RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
RUN python3.8 get-pip.py && rm get-pip.py
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2
# Comment out this line since Ubuntu 20.04 does not support it
# RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1
RUN python3.10 get-pip.py && rm get-pip.py
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 2
ADD requirements.txt requirements.txt
ENV PYTHON_EXEC=python3.8
ENV PYTHON_EXEC=python3.10
RUN ${PYTHON_EXEC} -m pip install -r requirements.txt

2
docker/Dockerfile.gcc-12 Normal file
View File

@ -0,0 +1,2 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN add-apt-repository -y ppa:ubuntu-toolchain-r/test && apt-get update && apt-get install -y gcc-12 g++-12

View File

@ -1,2 +0,0 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y gcc-7 g++-7

View File

@ -1,2 +0,0 @@
FROM ghcr.io/lnis-uofu/openfpga-build-base
RUN apt-get update && apt-get install -y gcc-8 g++-8

View File

@ -1,4 +1,64 @@
.. dev_manual_cicd_setup::
.. _developer_ci:
Continous Integration
=====================
Motivation
----------
Continous Integration (CI) systems are built to ensure that input and output files of each teams are
- Correct
- Reproducable
- Consistent with other teams
CI system is automatically triggered on
- Main branch: the master branch of the codebase
- A pull request on main branch
Workflows
---------
Principles
^^^^^^^^^^
Continous Integration system consists a number of workflows, each of which is designed to validate a specific aspect of the codebase.
For the work of each team, there is at least 1 dedicated workflow.
Workflows can categorized in two types
.. option:: Generation flow
Such type of workflow is designed to ensure that golden files (netlists, bitstreams, etc.) are reproduciable.
A generation workflow consists of three steps:
- Detect changes on input files, e.g., architecture files, IPs and related scripts.
- If no changes detected, the workflow ends, since the golden outputs are not changed in a pull request
- If any changes are detected, the workflow will continue to the next steps
- Regenerate golden files by calling scripts. By the end of this step, it will compare the newly generated files with the golden reference (current branch)
- If there are no changes, the workflow ends.
- If any changes on golden reference are detected, this will error out. It means that the current golden reference are not reproduciable.
.. warning:: If any changes on golden references are detected, code review has to be enforced. Ensure that all the teams impacted agree on the changes.
.. option:: Validation flow
Such type of workflow is designed to verify the correctness of golden files
A validation workflow consists of three steps:
- Detect changes on golden reference (some pull requests update golden references)
- If no changes detected, the workflow ends. There is no need to validate the correctness of the golden reference (previous pull request should already do so).
- If any changes are detected, the workflow will continue to the next steps
- Run validation by calling scripts. For example, verification may call HDL simulations to verify the correctness of netlists.
- If the new golden reference passes all the tests, this will end.
- If the new golden reference fails any test, this will error out. It means that the current golden reference can not meet basic requirements.
.. warning:: If any validation flow failed, the pull request cannot be merged in general.
CI/CD setup
-----------

View File

@ -0,0 +1,44 @@
.. _developer_contributor_guidelines_general_rules:
General Rules
=============
Motivation
----------
Github projects involve many parties with different interests.
It is necessary to establish rules to
- guarantee the quality of each pull request by establishing a standard
- code review for each pull request is straightforward
- contributors have confidence when submitting changes
Create Pull requests
--------------------
- Contributors should state clearly their motivation and the principles of code changes in each pull request
- Contributors should be active in resolving conflicts with other contributors as well as maintainers. In principle, all the maintainers want every pull request in and are looking for reasons to approve it.
- Each pull request should pass all the existing tests in CI (See :ref:`developer_contributor_guidelines_checkin_system` for details). Otherwise, it should not be merged unless you get a waiver from all the maintainers.
- Contributors should not modify any codes/tests which are unrelated to the scope of their pull requests.
- The size of each pull request should be small. Large pull request takes weeks to be merged. The recommend size of pull request is up to 500 lines of codes changes. If you have one large file, this can be waived. However, the number of files to be changed should be as small as possible.
.. note:: For large pull requests, it is strongly recommended that contributors should talk to maintainers first or create an issue on the Github. Contributors should clearly define the motivation, detailed technical plan as well as deliverables. Through discussions, the technical plan may be requested to change. Please do not start code changes blindly before the technical plan is approved.
- For any new feature/functionality to be added, there should be
- Dedicated test cases in CI which validates its correctness
- An update on the documentation, if it changes user interface
- Provide sufficient code comments to ease the maintenance
.. _developer_contributor_guidelines_checkin_system:
Check-in System
---------------
.. seealso:: The check-in system is based on continous integration (CI). See details in :ref:`developer_ci`
The check-in system aims to offer a standardized way to
- ensure quailty of each contribution
- resolve conflicts between teams
It is designed for efficient communication between teams.

View File

@ -0,0 +1,11 @@
.. _developer_contributor_guidelines:
Contributor Guidelines
======================
.. toctree::
:maxdepth: 2
general_rules
naming_convention

View File

@ -0,0 +1,224 @@
.. _developer_naming_convention:
Naming Convention
=================
.. _developer_naming_convention_cell_names:
Cell Names
----------
.. warning:: This is a different concept than the cell names in :ref:`developer_naming_convention_ff_model_names`!
.. note:: we refer to standard cell wrapper here. Wrappers are built to make netlists portable between PDKs as well as across standard cell libraries in a PDK.
For code readability, the cell name should follow the convention
::
<Cell_Function><Set_Features><Reset_Features><Output_Features><Drive_Strength>_<Wrapper>
.. option:: Cell_Function
Name of logic function, e.g., AND2, XNOR3, etc.
.. option:: Set_Features
This is mainly for sequential cells, e.g., D-type flip-flops. If a cell contains a set signal, its existence and polarity must be inferreable by the cell name. The available options are
- S: Asynchronous active-high set
- SYNS: Synchronous active-hight set
- SN: Asynchronous active-low set
- SYNSN: Synchronous active-low set
.. note:: For cells without set, this keyword should be empty
.. option:: Reset_Features
This is mainly for sequential cells, e.g., D-type flip-flops. If a cell contains a reset signal, its existence and polarity must be inferreable by the cell name. The available options are
- R: Asynchronous active-high reset
- SYNR: Synchronous active-hight reset
- RN: Asynchronous active-low reset
- SYNRN: Synchronous active-low reset
.. note:: For cells without reset, this keyword should be empty
.. option:: Output_Features
This is mainly for sequential cells, e.g., D-type flip-flops.
- If not specified, the sequential cell contains a pair of differential outputs, e.g., ``Q`` and ``QN``
- If specified, the sequential cell only contains single output, e.g., ``Q``
The available options are
- Q: single output which is positive
- QN: single ouput which is negative
.. note:: For cells without reset, this keyword should be empty
.. option:: Drive_Strength
This is to specify the drive strength of a cell
- If not specified, we assume minimum drive strength, i.e., ``D0``.
- If specified, we expect a format of ``D<int>``, where the integer indicates the drive strength
.. option:: Wrapper
This is to specify if the cell is a wrapper of an existing standard cell
- If not specified, we assume this cell contains RTL
- If specified, we assume this cell is a wrapper of an existing standard cell
A quick example
::
NAND2D4_WRAPPER
represents a wrapper for a standard cell that is a 2-input NAND gate with a drive strength of 4
Another example
::
SDFFSSYNRNQ
represents a scan-chain flip-flop which contains
- Asynchronous active-high set
- Synchronous active-low reset
- Single output
Pin Names
---------
.. note:: Please use lowercase as much as you can
For code readability, the pin name should follow the convention
::
<Pin_Name>_<Polarity><Direction>
.. option:: Pin_Name
Represents the pin name
.. option:: Polarity
Represents polarity of the pin, it can be
- ``n`` denotes a negative-enable (active_low) signal
.. note:: When not specified, by default we assume this is a postive-enable (active-high) signal
.. option:: Direction
Represents the direction of a pin, it can be
- ``i`` denotes an input signal
- ``o`` denotes an output signal
A quick example
::
clk_ni
represents an input clock signal which is negative-enable
Another example
::
q_no
represents an output Q signal which is negative to the input
.. _developer_naming_convention_ff_model_names:
Flip-flop Model Names
---------------------
.. warning:: This is a different concept than the cell names in :ref:`developer_naming_convention_cell_names`!
.. note:: we refer to virtual cell model (used by VPR and Yosys for cell mapping) here.
For code readability, D-type flip-flop model names should follow the convention
::
<Sync_Type>dff<Trigger_Type><Set_Type><Reset_Type>
.. option:: Sync_Features
Represents if the reset/set is synchronous or asynchronous to the clock, it can be
- ``s`` denotes a synchronous behavior
- an empty string "" denotes an asynchronous behavior, e.g., ``ffr``
.. option:: Trigger_Type
Represents if the flip-flop is triggered by rising edge or falling edge of a clock, it can be
- ``n`` means triggered by failling edge
- an empty string "" means triggered by rising edge, e.g., ``ff``
.. option:: Set_Type
Represents if the flip-flop has a set and the polarity of the set, it can be
- ``s`` means that the flip-flop has an active-high set pin
- ``sn`` means that the flip-flop has an active-low set pin
- an empty string "" means the flip-flop does not have a set pin, e.g., ``ff``
.. option:: Reset_Type
Represents if the flip-flop has a reset and the polarity of the reset, it can be
- ``r`` means that the flip-flop has an active-high reset pin
- ``rn`` means that the flip-flop has an active-low reset pin
- an empty string "" means the flip-flop does not have a reset pin, e.g., ``ff``
A quick example
::
ffnrn
represents a flip-flop
- triggered by falling edge
- with an asynchronous active-low reset
Another example
::
sffs
represents a flip-flop
- triggered by rising edge
- with a synchronous active-high set
.. _developer_naming_convention_mux_model_names:
Multiplexer Model Names
-----------------------
.. warning:: This is a different concept than the cell names in :ref:`developer_naming_convention_cell_names`!
.. note:: Here, we refer to the circuit model name used in OpenFPGA architecture file.
For code readability, a routing multiplexer circuit model name should follow the convention
::
<Location>_mux_<Load>
.. option:: Location
Represents the location of the routing multiplexers, it can be
- ``cb`` denotes a routing multiplexer in a connection block
- ``sb`` denotes a routing multiplexer in a switch block
- ``pb`` denotes a routing multiplexer in a programmable block
.. option:: Load
Represents the output load condition of the routing multiplexers, it can be
- ``highload`` means that the routing multiplexer has to drive a very high capacitive load, which potentially requires a big buffer at output
- an empty string "" means the routing multiplexer requires only a typical buffer size.
A quick example
::
pb_mux_highload
represents a routing multiplexer used in a programmable block which drives a high capacitive load

View File

@ -1,16 +1,22 @@
.. _developer:
Developer Guidelines
.. toctree::
:maxdepth: 1
:maxdepth: 2
version_number
back_compatible
contributor_guidelines
cicd_setup
ci
regression_tests
tcl_api
.. toctree::
:maxdepth: 2
:caption: Contributor Guidelines
contributor_guidelines/index

View File

@ -7,6 +7,17 @@ Configuration protocol is the circuitry designed to program an FPGA.
As an interface, configuration protocol could be really different in FPGAs, depending on the application context.
OpenFPGA supports versatile configuration protocol, providing different trade-offs between speed and area.
Under configuration protocol, if the configuration is QL Memory Bank with flatten BL/WL protocol, there might be
optional configuration setting call <ql_memory_bank_config_setting>.
In QL Memory Bank configuration protocol, configuration bits are organized as BitLine (BL) x WordLine (WL)
By default, OpenFPGA will keep BL and WL in square shape if possible where BL might be one bit longer than WL in some cases
For example:
- If the configuration bits of a PB is 9 bits, then BL=3 and WL=3
- If the configuration bits of a PB is 11 bits, then BL=4 and WL=3 (where there is one extra bit as phantom bit)
- If the configuration bits of a PB is 14 bits, then BL=4 and WL=4 (where there is two extra bits as phantom bits)
This QL Memory Bank configuration setting allow OpenFPGA to use a fixed WL size, instead of default approach
Template
~~~~~~~~
@ -14,6 +25,9 @@ Template
<configuration_protocol>
<organization type="<string>" circuit_model_name="<string>" num_regions="<int>"/>
<ql_memory_bank_config_setting>
<pb_type name="<string>" num_wl="<int>"/>
</ql_memory_bank_config_setting>
</configuration_protocol>
.. option:: type="scan_chain|memory_bank|standalone|frame_based|ql_memory_bank"
@ -54,6 +68,29 @@ Template
.. note:: For ``ql_memory_bank`` configuration protocol when BL/WL protocol ``shift_register`` is selected, different configuration regions **cannot** share any WLs on the same row! In such case, the default fabric key may not work. Strongly recommend to craft your own fabric key based on your configuration region plannning!
.. option:: name="<string>"
Specify the name of PB type, for example: clb, dsp, bram and etc
.. option:: num_wl="<int>"
Fix the size of WL
For example:
Considered that the configuration bits of a PB is 400 bits.
If num_wl is not defined, then
- BL will be 20 [=ceiling(square_root(400))]
- WL will be 20 [=ceiling(400/20)]
If num_wl is defined as 10, then
- WL will be fixed as 10
- BL will be 40 [=ceiling(400/10)]
If num_wl is defined as 32, then
- WL will be fixed as 32
- BL will be 13 [=ceiling(400/32)]
- There will be 16 bits [=(32x13)-400] as phantom bits.
Configuration Chain Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -1,12 +1,12 @@
.. _direct_interconnect:
Inter-Tile Direct Interconnection extensions
--------------------------------------------
Direct Interconnect
-------------------
This section introduces extensions on the architecture description file about existing interconnection description.
This section introduces extensions on the architecture description file about direct connections between programmable blocks.
Directlist
~~~~~~~~~~
Syntax
~~~~~~
The original direct connections in the directlist section are documented here_. Its description is given below:
@ -20,20 +20,26 @@ The original direct connections in the directlist section are documented here_.
.. note:: These options are required
Our extension include three more options:
In the OpenFPGA architecture file, you may define additional attributes for each VPR's direct connection:
.. code-block:: xml
<directlist>
<direct name="string" from_pin="string" to_pin="string" x_offset="int" y_offset="int" z_offset="int" switch_name="string" interconnection_type="string" x_dir="string" y_dir="string"/>
<direct_connection>
<direct name="string" circuit_model_name="string" interconnection_type="string" x_dir="string" y_dir="string"/>
</directlist>
.. note:: these options are optional. However, if `interconnection_type` is set `x_dir` and `y_dir` are required.
.. note:: these options are optional. However, if ``interconnection_type`` is set to ``inter_column`` or ``inter_row``, then ``x_dir`` and ``y_dir`` are required.
.. option:: interconnection_type="<string>"
the type of interconnection should be a string.
Available types are ``NONE`` | ``column`` | ``row``, specifies if it applies on a column or a row ot if it doesn't apply.
Available types are ``inner_column_or_row`` | ``part_of_cb`` | ``inter_column`` | ``inter_row``
- ``inner_column_or_row`` indicates the direct connections are between tiles in the same column or row. This is the default value.
- ``part_of_cb`` indicates the direct connections will drive routing multiplexers in connection blocks. Therefore, it is no longer a strict point-to-point direct connection.
- ``inter_column`` indicates the direct connections are between tiles in two columns
- ``inter_row`` indicates the direct connections are between tiles in two rows
.. note:: The following syntax is only applicable to ``inter_column`` and ``inter_row``
.. option:: x_dir="<string>"
@ -42,15 +48,15 @@ Our extension include three more options:
- x_dir="positive":
- interconnection_type="column": a column will be connected to a column on the ``right``, if it exists.
- interconnection_type="inter_column": a column will be connected to a column on the ``right``, if it exists.
- interconnection_type="row": the most on the ``right`` cell from a row connection will connect the most on the ``left`` cell of next row, if it exists.
- interconnection_type="inter_row": the most on the ``right`` cell from a row connection will connect the most on the ``left`` cell of next row, if it exists.
- x_dir="negative":
- interconnection_type="column": a column will be connected to a column on the ``left``, if it exists.
- interconnection_type="inter_column": a column will be connected to a column on the ``left``, if it exists.
- interconnection_type="row": the most on the ``left`` cell from a row connection will connect the most on the ``right`` cell of next row, if it exists.
- interconnection_type="inter_row": the most on the ``left`` cell from a row connection will connect the most on the ``right`` cell of next row, if it exists.
.. option:: y_dir="<string>"
@ -59,27 +65,96 @@ Our extension include three more options:
- y_dir="positive":
- interconnection_type="column": the ``bottom`` cell of a column will be connected to the next column ``top`` cell, if it exists.
- interconnection_type="inter_column": the ``bottom`` cell of a column will be connected to the next column ``top`` cell, if it exists.
- interconnection_type="row": a row will be connected on an ``above`` row, if it exists.
- interconnection_type="inter_row": a row will be connected on an ``above`` row, if it exists.
- y_dir="negative":
- interconnection_type="column": the ``top`` cell of a column will be connected to the next column ``bottom`` cell, if it exists.
- interconnection_type="inter_column": the ``top`` cell of a column will be connected to the next column ``bottom`` cell, if it exists.
- interconnection_type="row": a row will be connected on a row ``below``, if it exists.
- interconnection_type="inter_row": a row will be connected on a row ``below``, if it exists.
Example
~~~~~~~
Enhanced Connection Block
~~~~~~~~~~~~~~~~~~~~~~~~~
For this example, we will study a scan-chain implementation. The description could be:
The direct connection can also drive routing multiplexers of connection blocks. When such connection occures in a connection block, it is called enhanced connection block.
:numref:`fig_ecb` illustrates the difference between a regular connection block and an enhanced connection block.
.. _fig_ecb:
.. figure:: ./figures/ecb.png
Enhanced connection block vs. Regular connection block
In such scenario, the type ``part_of_cb`` is required.
.. warning:: Restrictions may be applied when building the direct connections as part of a connection block.
Direct connections can be inside a tile or across two tiles. Currently, across more than two tiles are not supported!
:numref:`fig_ecb_allowed_direct_connection` illustrates the region (in red) where any input pin is allowed to be driven by any output pin.
.. _fig_ecb_allowed_direct_connection:
.. figure:: ./figures/ecb_allowed_direct_connection.png
Allowed connections inside a tile for enhanced connection block (see the highlighted region)
:numref:`fig_ecb_allowed_direct_connection_inner_tile_example` shows a few feedback connections which can be built inside connection blocks. Note that feedback connections are fully allowed between any pins on the same side of a programmable block.
.. _fig_ecb_allowed_direct_connection_inner_tile_example:
.. figure:: ./figures/ecb_allowed_direct_connection_inner_tile_example.png
Example of feedback connections inside a tile for enhanced connection block
For instance, VPR architecture defines feedback connections like:
.. code-block:: xml
<directlist>
<direct name="scff_chain" from_pin="clb.sc_out" to_pin="clb.sc_in" x_offset="0" y_offset="-1" z_offset="0" interconnection_type="column" x_dir="positive" y_dir="positive"/>
<!-- Add 2 inputs to the routing multiplexers inside a connection block which drives pin 'clb.I_top[0]' -->
<direct name="feedback" from_pin="clb.O_top[0:0]" to_pin="clb.I_top[0:0]" x_offset="0" y_offset="0" z_offset="0"/>
<direct name="feedback" from_pin="clb.O_top[1:1]" to_pin="clb.I_top[0:0]" x_offset="0" y_offset="0" z_offset="0"/>
</directlist>
:numref:`fig_ecb_allowed_direct_connection_inter_tile_example` shows a few inter-tile connections which can be built inside connection blocks. Note that inter-tile connections are subjected to the restrictions depicted in :numref:`fig_ecb_allowed_direct_connection`
.. _fig_ecb_allowed_direct_connection_inter_tile_example:
.. figure:: ./figures/ecb_allowed_direct_connection_inter_tile_example.png
Example of connections across two tiles for enhanced connection block
:numref:`fig_ecb_forbid_direct_connection_example` illustrates some inner-tile and inter-tile connections which are not allowed. Note that feedback connections across different sides are restricted!
.. _fig_ecb_forbid_direct_connection_example:
.. figure:: ./figures/ecb_forbid_direct_connection_example.png
Restrictions on building direct connections as part of a connection block
Inter-tile Connections
~~~~~~~~~~~~~~~~~~~~~~
For this example, we will study a scan-chain implementation. The description could be:
In VPR architecture:
.. code-block:: xml
<directlist>
<direct name="scff_chain" from_pin="clb.sc_out" to_pin="clb.sc_in" x_offset="0" y_offset="-1" z_offset="0"/>
</directlist>
In OpenFPGA architecture:
.. code-block:: xml
<direct_connection>
<direct name="scff_chain" interconnection_type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
:numref:`fig_p2p_exple` is the graphical representation of the above scan-chain description on a 4x4 FPGA.
.. _fig_p2p_exple:
@ -91,9 +166,6 @@ For this example, we will study a scan-chain implementation. The description cou
In this figure, the red arrows represent the initial direct connection. The green arrows represent the point to point connection to connect all the columns of CLB.
Truth table
~~~~~~~~~~~
A point to point connection can be applied in different ways than showed in the example section. To help the designer implement his point to point connection, a truth table with our new parameters id provided below.
:numref:`fig_p2p_trtable` provides all possible variable combination and the connection it will generate.

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

View File

@ -0,0 +1,62 @@
.. _file_format_fabric_hierarchy_file:
Fabric Hierarchy File (.yaml)
----------------------------------------
This file is generated by command :ref:`openfpga_setup_commands_write_fabric_hierarchy`
The fabric hierarchy file aims to show module trees of a number of given roots
This file is created for netlist manipulation and detailed floorplanning during physical design steps
By using the options of the command :ref:`openfpga_setup_commands_write_fabric_hierarchy`, user can selectively output the module tree on their needs.
An example of the file is shown as follows.
.. code-block:: yaml
fpga_top:
tile_0__2_:
sb_0__1_:
mux_tree_tapbuf_size2:
INVTX1
const1
tap_buf4
mux_tree_tapbuf_basis_input2_mem1:
- TGATE
mux_tree_tapbuf_size2_feedthrough_mem
sb_1__config_group_mem_size40:
mux_tree_tapbuf_size2_mem:
- DFF
tile_1__2_:
grid_io_top:
logical_tile_io_mode_io_:
logical_tile_io_mode_physical__iopad:
- GPIO
- GPIO_feedthrough_DFF_mem
direct_interc
In this example, the root module is ``fpga_top``.
The child modules under ``fpga_top`` are ``tile_0__2_`` and ``tile_1__2_``.
Note that the leaf nodes are shown as a list, e.g., ``GPIO`` and ``GPIO_feedthrough_DFF_mem``.
When multiple root modules are defined, the output could be
.. code-block:: yaml
sb_0__1_:
- mux_tree_tapbuf_size2
sb_1__0_:
- mux_tree_tapbuf_size2
sb_1__1_:
- mux_tree_tapbuf_size2
cbx_1__0_:
- mux_tree_tapbuf_size4
cbx_1__1_:
- mux_tree_tapbuf_size4
cby_0__1_:
- mux_tree_tapbuf_size2
- mux_tree_tapbuf_size4
cby_1__1_:
- mux_tree_tapbuf_size4

View File

@ -0,0 +1,109 @@
.. _file_format_fabric_pin_physical_location_file:
Fabric Pin Physical Location File (.xml)
----------------------------------------
This file is generated by command :ref:`openfpga_setup_commands_write_fabric_pin_physical_location`
The fabric pin physical location file aims to show
- Pin names of each module in an eFPGA fabric
- Preferred physical side of each pin on its module
This file is created for pin guidelines during physical design steps
An example of the file is shown as follows.
.. code-block:: xml
<pin_location>
<module name="sb_1__1_">
<loc pin="chany_bottom_in[0:0]" side="bottom"/>
<loc pin="chany_bottom_in[1:1]" side="bottom"/>
<loc pin="chany_bottom_in[2:2]" side="bottom"/>
<loc pin="chany_bottom_in[3:3]" side="bottom"/>
<loc pin="chany_bottom_in[4:4]" side="bottom"/>
<loc pin="chany_bottom_in[5:5]" side="bottom"/>
<loc pin="chany_bottom_in[6:6]" side="bottom"/>
<loc pin="chany_bottom_in[7:7]" side="bottom"/>
<loc pin="chany_bottom_in[8:8]" side="bottom"/>
<loc pin="chany_bottom_in[9:9]" side="bottom"/>
<loc pin="chany_bottom_in[10:10]" side="bottom"/>
<loc pin="chany_bottom_in[11:11]" side="bottom"/>
<loc pin="chany_bottom_in[12:12]" side="bottom"/>
<loc pin="chany_bottom_out[0:0]" side="bottom"/>
<loc pin="chany_bottom_out[1:1]" side="bottom"/>
<loc pin="chany_bottom_out[2:2]" side="bottom"/>
<loc pin="chany_bottom_out[3:3]" side="bottom"/>
<loc pin="chany_bottom_out[4:4]" side="bottom"/>
<loc pin="chany_bottom_out[5:5]" side="bottom"/>
<loc pin="chany_bottom_out[6:6]" side="bottom"/>
<loc pin="chany_bottom_out[7:7]" side="bottom"/>
<loc pin="chany_bottom_out[8:8]" side="bottom"/>
<loc pin="chany_bottom_out[9:9]" side="bottom"/>
<loc pin="chany_bottom_out[10:10]" side="bottom"/>
<loc pin="chany_bottom_out[11:11]" side="bottom"/>
<loc pin="chany_bottom_out[12:12]" side="bottom"/>
<loc pin="bottom_right_grid_left_width_0_height_0_subtile_0__pin_inpad_0_[0:0]" side="bottom"/>
<loc pin="bottom_right_grid_left_width_0_height_0_subtile_1__pin_inpad_0_[0:0]" side="bottom"/>
<loc pin="bottom_right_grid_left_width_0_height_0_subtile_2__pin_inpad_0_[0:0]" side="bottom"/>
<loc pin="bottom_right_grid_left_width_0_height_0_subtile_3__pin_inpad_0_[0:0]" side="bottom"/>
<loc pin="bottom_right_grid_left_width_0_height_0_subtile_4__pin_inpad_0_[0:0]" side="bottom"/>
<loc pin="bottom_right_grid_left_width_0_height_0_subtile_5__pin_inpad_0_[0:0]" side="bottom"/>
<loc pin="bottom_right_grid_left_width_0_height_0_subtile_6__pin_inpad_0_[0:0]" side="bottom"/>
<loc pin="bottom_right_grid_left_width_0_height_0_subtile_7__pin_inpad_0_[0:0]" side="bottom"/>
<loc pin="bottom_left_grid_right_width_0_height_0_subtile_0__pin_O_3_[0:0]" side="bottom"/>
<loc pin="chanx_left_in[0:0]" side="left"/>
<loc pin="chanx_left_in[1:1]" side="left"/>
<loc pin="chanx_left_in[2:2]" side="left"/>
<loc pin="chanx_left_in[3:3]" side="left"/>
<loc pin="chanx_left_in[4:4]" side="left"/>
<loc pin="chanx_left_in[5:5]" side="left"/>
<loc pin="chanx_left_in[6:6]" side="left"/>
<loc pin="chanx_left_in[7:7]" side="left"/>
<loc pin="chanx_left_in[8:8]" side="left"/>
<loc pin="chanx_left_in[9:9]" side="left"/>
<loc pin="chanx_left_in[10:10]" side="left"/>
<loc pin="chanx_left_in[11:11]" side="left"/>
<loc pin="chanx_left_in[12:12]" side="left"/>
<loc pin="chanx_left_out[0:0]" side="left"/>
<loc pin="chanx_left_out[1:1]" side="left"/>
<loc pin="chanx_left_out[2:2]" side="left"/>
<loc pin="chanx_left_out[3:3]" side="left"/>
<loc pin="chanx_left_out[4:4]" side="left"/>
<loc pin="chanx_left_out[5:5]" side="left"/>
<loc pin="chanx_left_out[6:6]" side="left"/>
<loc pin="chanx_left_out[7:7]" side="left"/>
<loc pin="chanx_left_out[8:8]" side="left"/>
<loc pin="chanx_left_out[9:9]" side="left"/>
<loc pin="chanx_left_out[10:10]" side="left"/>
<loc pin="chanx_left_out[11:11]" side="left"/>
<loc pin="chanx_left_out[12:12]" side="left"/>
<loc pin="left_top_grid_bottom_width_0_height_0_subtile_0__pin_inpad_0_[0:0]" side="left"/>
<loc pin="left_top_grid_bottom_width_0_height_0_subtile_1__pin_inpad_0_[0:0]" side="left"/>
<loc pin="left_top_grid_bottom_width_0_height_0_subtile_2__pin_inpad_0_[0:0]" side="left"/>
<loc pin="left_top_grid_bottom_width_0_height_0_subtile_3__pin_inpad_0_[0:0]" side="left"/>
<loc pin="left_top_grid_bottom_width_0_height_0_subtile_4__pin_inpad_0_[0:0]" side="left"/>
<loc pin="left_top_grid_bottom_width_0_height_0_subtile_5__pin_inpad_0_[0:0]" side="left"/>
<loc pin="left_top_grid_bottom_width_0_height_0_subtile_6__pin_inpad_0_[0:0]" side="left"/>
<loc pin="left_top_grid_bottom_width_0_height_0_subtile_7__pin_inpad_0_[0:0]" side="left"/>
<loc pin="left_bottom_grid_top_width_0_height_0_subtile_0__pin_O_2_[0:0]" side="left"/>
</module>
</pin_location>
.. option:: name="<string>"
The module name in FPGA fabric, which should be a valid module defined in output Verilog netlist.
.. note:: You should be find the exact module in the FPGA fabric if you output the Verilog netlists.
.. option:: pin="<string>"
The name of the pin in FPGA fabric. Note that all the bus port will be flatten in this file.
.. note:: You should be find the exact pin in the module if you output the Verilog netlists.
.. option:: side="<string>"
The physical side of the pin should appear on the perimeter of the module.

View File

@ -41,3 +41,7 @@ OpenFPGA widely uses XML format for interchangeable files
module_naming_file
tile_config_file
fabric_pin_physical_location_file
fabric_hierarchy_file

View File

@ -176,6 +176,10 @@ __ iverilog_website_
.. warning:: Signal initialization is only applied to the datapath inputs of routing multiplexers (considering the fact that they are indispensible cells of FPGAs)! If your FPGA does not contain any multiplexer cells, signal initialization is not applicable.
.. option:: --dump_waveform
Enable waveform output when runnign HDL simulation on the preconfigured wrapper. When enabled, waveform files can be outputted in two formats: ``fsdb`` and ``vcd`` through preprocessing flags ``DUMP_FSDB`` and ``DUMP_VCD`` respectively. For example, when using VCS,. the flag can be activiated by ``+define+DUMP_FSDB=1``.
.. option:: --no_time_stamp
Do not print time stamp in Verilog netlists

View File

@ -359,20 +359,33 @@ add_fpga_core_to_fabric
Show verbose log
.. _openfpga_setup_commands_write_fabric_hierarchy:
write_fabric_hierarchy
~~~~~~~~~~~~~~~~~~~~~~
Write the hierarchy of FPGA fabric graph to a plain-text file
Write the hierarchy of FPGA fabric graph to a YAML file
.. option:: --file <string> or -f <string>
Specify the file name to write the hierarchy.
Specify the file name to write the hierarchy. See details in :ref:`file_format_fabric_hierarchy_file`.
.. option:: --depth <int>
Specify at which depth of the fabric module graph should the writer stop outputting. The root module start from depth 0. For example, if you want a two-level hierarchy, you should specify depth as 1.
.. option:: --module <regexp>
Specify the root module name(s) which should be considered. By default, it is ``fpga_top``. Note that regular expression is supported. For example, ``grid_*`` will output all the modules with a prefix of ``grid_``
.. option:: --filter <regexp>
Specify the filter which allows user to select modules to appear under each root module tree. By default, it is ``*``. Regular expression is supported. For example, ``*mux*`` will output all the modules which contains ``mux``. In the other words, the filter defines a white list.
.. option:: --exclude_empty_modules
Exclude modules with no qualified children (match the names defined through filter) from the output file
.. option:: --verbose
Show verbose log
@ -392,7 +405,7 @@ write_fabric_io_info
.. option:: --no_time_stamp
Do not print time stamp in bitstream files
Do not print time stamp in output files
.. option:: --verbose
@ -433,7 +446,7 @@ pcf2place
.. option:: --no_time_stamp
Do not print time stamp in bitstream files
Do not print time stamp in output files
.. option:: --verbose
@ -467,7 +480,34 @@ write_module_naming_rules
.. option:: --no_time_stamp
Do not print time stamp in bitstream files
Do not print time stamp in output files
.. option:: --verbose
Show verbose log
.. _openfpga_setup_commands_write_fabric_pin_physical_location:
write_fabric_pin_physical_location
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Output the physical location of each pin for each module of an FPGA fabric to a given file
.. option:: --file <string>
Specify the file path to be written to. See details in :ref:`file_format_fabric_pin_physical_location_file`.
.. option:: --module <string>
Specify the name of modules to be considered. Support regular expression, e.g., ``tile*``. When provided, only pins of selected modules will be outputted. By default, a wildcard ``*`` is considered, which means all the modules will be considered.
.. option:: --show_invalid_side
Show sides for each pin, even these pin does not have a specific valid side. This is mainly used for debugging.
.. option:: --no_time_stamp
Do not print time stamp in output files
.. option:: --verbose

View File

@ -12,7 +12,7 @@ How to Compile
Supported Operating Systems
~~~~~~~~~~~~~~~~~~~~~~~~~~~
OpenFPGA is continously tested with Ubuntu 20.04 and partially on Ubuntu 22.04
OpenFPGA is continously tested with Ubuntu 22.04 and partially on Ubuntu 20.04
It might work with earlier versions and other distributions.
In addition to continous integration, our community users have tested OpenFPGA on their local machines using the following operating systems:
@ -21,7 +21,6 @@ In addition to continous integration, our community users have tested OpenFPGA o
- CentOS 8
- Ubuntu 18.04
- Ubuntu 21.04
- Ubuntu 22.04
Build Steps
~~~~~~~~~~~
@ -34,7 +33,7 @@ In general, please follow the steps to compile
cd OpenFPGA
make all
.. note:: OpenFPGA requires gcc/g++ version > 7 and clang version > 6.
.. note:: OpenFPGA requires gcc/g++ version > 9 and clang version > 10.
.. note:: cmake3.12+ is recommended to compile OpenFPGA with GUI
@ -111,7 +110,7 @@ Ubuntu 20.04
- Dependencies required to run regression tests
.. include:: regtest_dependencies.sh
.. include:: ubuntu20p04_regtest_dependencies.sh
:code: shell
.. note:: Python packages are also required
@ -135,7 +134,7 @@ Ubuntu 22.04
- Dependencies required to run regression tests
.. include:: regtest_dependencies.sh
.. include:: ubuntu22p04_regtest_dependencies.sh
:code: shell
.. note:: Python packages are also required

View File

@ -1 +1 @@
../../../../.github/workflows/install_dependencies_run.sh
../../../../.github/workflows/install_dependencies_run_ubuntu22p04.sh

View File

@ -1 +1 @@
../../../../.github/workflows/install_dependencies_build.sh
../../../../.github/workflows/install_dependencies_build_ubuntu20p04.sh

View File

@ -0,0 +1 @@
../../../../.github/workflows/install_dependencies_run_ubuntu20p04.sh

View File

@ -0,0 +1 @@
../../../../.github/workflows/install_dependencies_run_ubuntu22p04.sh

View File

@ -71,7 +71,7 @@ ArchDirectId ArchDirect::add_direct(const std::string& name) {
direct_ids_.push_back(direct);
names_.push_back(name);
circuit_models_.push_back(CircuitModelId::INVALID());
types_.emplace_back(NUM_DIRECT_TYPES);
types_.emplace_back(e_direct_type::NUM_DIRECT_TYPES);
directions_.emplace_back(vtr::Point<e_direct_direction>(
NUM_DIRECT_DIRECTIONS, NUM_DIRECT_DIRECTIONS));

View File

@ -14,15 +14,16 @@
* These types are supplementary to the original VPR direct connections
* Here we extend to the cross-row and cross-column connections
********************************************************************/
enum e_direct_type {
INNER_COLUMN,
INNER_ROW,
enum class e_direct_type {
INNER_COLUMN_OR_ROW,
PART_OF_CB,
INTER_COLUMN,
INTER_ROW,
NUM_DIRECT_TYPES
};
constexpr std::array<const char*, NUM_DIRECT_TYPES> DIRECT_TYPE_STRING = {
{"inner_column", "inner_row", "inter_column", "inter_row"}};
constexpr std::array<const char*, (size_t)e_direct_type::NUM_DIRECT_TYPES>
DIRECT_TYPE_STRING = {
{"inner_column_or_row", "part_of_cb", "inter_column", "inter_row"}};
enum e_direct_direction { POSITIVE_DIR, NEGATIVE_DIR, NUM_DIRECT_DIRECTIONS };
constexpr std::array<const char*, NUM_DIRECT_DIRECTIONS>

View File

@ -116,6 +116,11 @@ CircuitModelId ConfigProtocol::wl_memory_model() const {
size_t ConfigProtocol::wl_num_banks() const { return wl_num_banks_; }
const QLMemoryBankConfigSetting* ConfigProtocol::ql_memory_bank_config_setting()
const {
return &ql_memory_bank_config_setting_;
}
/************************************************************************
* Public Mutators
***********************************************************************/
@ -256,6 +261,10 @@ void ConfigProtocol::set_wl_num_banks(const size_t& num_banks) {
wl_num_banks_ = num_banks;
}
QLMemoryBankConfigSetting* ConfigProtocol::get_ql_memory_bank_config_setting() {
return &ql_memory_bank_config_setting_;
}
/************************************************************************
* Private Validators
***********************************************************************/

View File

@ -7,6 +7,7 @@
#include "circuit_library_fwd.h"
#include "circuit_types.h"
#include "openfpga_port.h"
#include "ql_memory_bank_config_setting.h"
/* Data type to define the protocol through which BL/WL can be manipulated */
enum e_blwl_protocol_type {
@ -54,6 +55,9 @@ class ConfigProtocol {
CircuitModelId wl_memory_model() const;
size_t wl_num_banks() const;
/* QL Memory Bank Config Setting */
const QLMemoryBankConfigSetting* ql_memory_bank_config_setting() const;
public: /* Public Mutators */
void set_type(const e_config_protocol_type& type);
void set_memory_model_name(const std::string& memory_model_name);
@ -76,6 +80,9 @@ class ConfigProtocol {
void set_wl_memory_model(const CircuitModelId& memory_model);
void set_wl_num_banks(const size_t& num_banks);
/* QL Memory Bank Config Setting */
QLMemoryBankConfigSetting* get_ql_memory_bank_config_setting();
public: /* Public validators */
/* Check if internal data has any conflicts to each other. Return number of
* errors detected */
@ -131,6 +138,9 @@ class ConfigProtocol {
std::string wl_memory_model_name_;
CircuitModelId wl_memory_model_;
size_t wl_num_banks_;
/* QL Memory Bank Config Setting */
QLMemoryBankConfigSetting ql_memory_bank_config_setting_;
};
#endif

View File

@ -0,0 +1,34 @@
#include "ql_memory_bank_config_setting.h"
#include "openfpga_tokenizer.h"
#include "vtr_assert.h"
#include "vtr_log.h"
/************************************************************************
* Member functions for class QLMemoryBankConfigSetting
***********************************************************************/
/************************************************************************
* Constructors
***********************************************************************/
QLMemoryBankConfigSetting::QLMemoryBankConfigSetting() {}
/************************************************************************
* Public Accessors
***********************************************************************/
QLMemoryBankPBSetting QLMemoryBankConfigSetting::pb_setting(
const std::string& name) const {
if (settings_.find(name) != settings_.end()) {
return settings_.at(name);
}
return QLMemoryBankPBSetting();
}
/************************************************************************
* Public Mutators
***********************************************************************/
void QLMemoryBankConfigSetting::add_pb_setting(const std::string& name,
uint32_t num_wl) {
VTR_ASSERT(settings_.find(name) == settings_.end());
settings_[name] = QLMemoryBankPBSetting(num_wl);
}

View File

@ -0,0 +1,30 @@
#ifndef QL_MEMORY_BANK_CONFIG_SETTING_H
#define QL_MEMORY_BANK_CONFIG_SETTING_H
#include <cstdint>
#include <map>
#include <string>
struct QLMemoryBankPBSetting {
QLMemoryBankPBSetting(uint32_t n = 0) : num_wl(n) {}
uint32_t num_wl = 0;
};
/********************************************************************
* A data structure to store QL Memory Bank configuration setting
*******************************************************************/
class QLMemoryBankConfigSetting {
public: /* Constructors */
QLMemoryBankConfigSetting();
public: /* Public Accessors */
QLMemoryBankPBSetting pb_setting(const std::string& name) const;
public: /* Public Mutators */
void add_pb_setting(const std::string& name, uint32_t num_wl);
private: /* Internal data */
std::map<std::string, QLMemoryBankPBSetting> settings_;
};
#endif

View File

@ -249,6 +249,32 @@ static void read_xml_config_organization(pugi::xml_node& xml_config_orgz,
}
}
/********************************************************************
* Parse XML codes about <ql_memory_bank_config_setting> to
*QLMemoryBankConfigSetting
*******************************************************************/
static void read_xml_ql_memory_bank_config_setting(
QLMemoryBankConfigSetting* setting, pugi::xml_node& Node,
const pugiutil::loc_data& loc_data) {
/* Parse configuration protocol root node */
pugi::xml_node config_setting =
get_single_child(Node, "ql_memory_bank_config_setting", loc_data,
pugiutil::ReqOpt::OPTIONAL);
if (config_setting) {
/* Add to ql_memory_bank_config_setting_ */
for (pugi::xml_node xml_child : config_setting.children()) {
if (xml_child.name() != std::string("pb_type")) {
bad_tag(xml_child, loc_data, config_setting, {"pb_type"});
}
const std::string& name_attr =
get_attribute(xml_child, "name", loc_data).as_string();
uint32_t num_wl = get_attribute(xml_child, "num_wl", loc_data).as_uint();
setting->add_pb_setting(name_attr, num_wl);
}
}
}
/********************************************************************
* Parse XML codes about <configuration_protocol> to an object of ConfigProtocol
*******************************************************************/
@ -264,5 +290,14 @@ ConfigProtocol read_xml_config_protocol(pugi::xml_node& Node,
get_single_child(xml_config, "organization", loc_data);
read_xml_config_organization(xml_config_orgz, loc_data, config_protocol);
/* Parse QL Memory Bank configuration setting */
if (config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK &&
config_protocol.bl_protocol_type() == BLWL_PROTOCOL_FLATTEN &&
config_protocol.wl_protocol_type() == BLWL_PROTOCOL_FLATTEN) {
read_xml_ql_memory_bank_config_setting(
config_protocol.get_ql_memory_bank_config_setting(), xml_config,
loc_data);
}
return config_protocol;
}

View File

@ -11,6 +11,7 @@
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from libarchfpga */
#include "arch_error.h"
@ -198,15 +199,20 @@ std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(
* Convert string to the enumerate of direct type
*******************************************************************/
static e_direct_type string_to_direct_type(const std::string& type_string) {
if (std::string("column") == type_string) {
return INTER_COLUMN;
if (std::string("part_of_cb") == type_string) {
return e_direct_type::PART_OF_CB;
}
if (std::string("inner_column_or_row") == type_string) {
return e_direct_type::INNER_COLUMN_OR_ROW;
}
if (std::string("inter_column") == type_string) {
return e_direct_type::INTER_COLUMN;
}
if (std::string("inter_row") == type_string) {
return e_direct_type::INTER_ROW;
}
if (std::string("row") == type_string) {
return INTER_ROW;
}
return NUM_DIRECT_TYPES;
return e_direct_type::NUM_DIRECT_TYPES;
}
/********************************************************************
@ -255,13 +261,6 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
std::string direct_name =
get_attribute(xml_direct, "name", loc_data).as_string();
/* Get the routing segment circuit model name */
std::string direct_model_name =
get_attribute(xml_direct, "circuit_model_name", loc_data).as_string();
CircuitModelId direct_model = find_routing_circuit_model(
xml_direct, loc_data, circuit_lib, direct_model_name, CIRCUIT_MODEL_WIRE);
/* Add to the Arch direct database */
ArchDirectId direct = arch_direct.add_direct(direct_name);
if (false == arch_direct.valid_direct_id(direct)) {
@ -269,28 +268,48 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
"Direct name '%s' has been defined more than once!\n",
direct_name.c_str());
}
arch_direct.set_circuit_model(direct, direct_model);
/* Add more information*/
std::string direct_type_name =
get_attribute(xml_direct, "type", loc_data, pugiutil::ReqOpt::OPTIONAL)
.as_string("none");
/* If not defined, we go to the next */
if (std::string("none") == direct_type_name) {
continue;
}
.as_string(
DIRECT_TYPE_STRING[size_t(e_direct_type::INNER_COLUMN_OR_ROW)]);
e_direct_type direct_type = string_to_direct_type(direct_type_name);
if (NUM_DIRECT_TYPES == direct_type) {
if (e_direct_type::NUM_DIRECT_TYPES == direct_type) {
archfpga_throw(
loc_data.filename_c_str(), loc_data.line(xml_direct),
"Direct type '%s' is not support! Acceptable values are [column|row]\n",
"Direct type '%s' is not support! Acceptable values are "
"[inner_column_or_row|part_of_cb|inter_column|inter_row]\n",
direct_type_name.c_str());
}
arch_direct.set_type(direct, direct_type);
/* Get the routing segment circuit model name */
std::string direct_model_name =
get_attribute(xml_direct, "circuit_model_name", loc_data).as_string();
/* If a direct connection is part of a connection block, the circuit model
* should be a MUX */
e_circuit_model_type expected_circuit_model_type = CIRCUIT_MODEL_WIRE;
if (arch_direct.type(direct) == e_direct_type::PART_OF_CB) {
VTR_LOG("Direct '%s' will modelled as part of a connection block.\n",
direct_name.c_str());
expected_circuit_model_type = CIRCUIT_MODEL_MUX;
}
CircuitModelId direct_model = find_routing_circuit_model(
xml_direct, loc_data, circuit_lib, direct_model_name,
expected_circuit_model_type);
arch_direct.set_circuit_model(direct, direct_model);
/* The following syntax is only available for inter-column/row */
if (arch_direct.type(direct) != e_direct_type::INTER_COLUMN &&
arch_direct.type(direct) != e_direct_type::INTER_ROW) {
continue;
}
std::string x_dir_name =
get_attribute(xml_direct, "x_dir", loc_data).as_string();
std::string y_dir_name =

View File

@ -57,7 +57,7 @@ static void write_xml_direct_component_circuit(
fp, "circuit_model_name",
circuit_lib.model_name(arch_direct.circuit_model(direct_id)).c_str());
write_xml_attribute(fp, "type",
DIRECT_TYPE_STRING[arch_direct.type(direct_id)]);
DIRECT_TYPE_STRING[size_t(arch_direct.type(direct_id))]);
write_xml_attribute(fp, "x_dir",
DIRECT_DIRECTION_STRING[arch_direct.x_dir(direct_id)]);
write_xml_attribute(fp, "y_dir",

View File

@ -4,7 +4,10 @@
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <array>
#include <map>
#include <string>
#include <vector>
#include "openfpga_port.h"

View File

@ -398,6 +398,9 @@ static RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx,
temp_ipin_rr_nodes.clear();
}
/* Build OPIN node lists for connection blocks */
rr_gsb.build_cb_opin_nodes(vpr_device_ctx.rr_graph);
return rr_gsb;
}
@ -701,14 +704,26 @@ static void annotate_direct_circuit_models(
}
/* Check the circuit model type */
if (CIRCUIT_MODEL_WIRE !=
openfpga_arch.circuit_lib.model_type(circuit_model)) {
if (openfpga_arch.arch_direct.type(direct_id) !=
e_direct_type::PART_OF_CB &&
CIRCUIT_MODEL_WIRE !=
openfpga_arch.circuit_lib.model_type(circuit_model)) {
VTR_LOG_ERROR(
"Require circuit model type '%s' for a direct connection '%s'!\nPlease "
"check your OpenFPGA architecture XML!\n",
CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_WIRE], direct_name.c_str());
exit(1);
}
if (openfpga_arch.arch_direct.type(direct_id) ==
e_direct_type::PART_OF_CB &&
CIRCUIT_MODEL_MUX !=
openfpga_arch.circuit_lib.model_type(circuit_model)) {
VTR_LOG_ERROR(
"Require circuit model type '%s' for a direct connection '%s'!\nPlease "
"check your OpenFPGA architecture XML!\n",
CIRCUIT_MODEL_TYPE_STRING[CIRCUIT_MODEL_MUX], direct_name.c_str());
exit(1);
}
/* Now update the device annotation */
vpr_device_annotation.add_direct_annotation(idirect, direct_id);

View File

@ -166,7 +166,7 @@ static void write_rr_gsb_chan_connection_to_xml(
fp << "\" node_id=\"" << size_t(driver_rr_node) << "\" grid_side=\""
<< grid_side.to_string() << "\" sb_module_pin_name=\""
<< generate_sb_module_grid_port_name(
gsb_side, driver_node_side, vpr_device_grid,
gsb_side, grid_side.get_side(), vpr_device_grid,
vpr_device_annotation, rr_graph, driver_rr_node);
}
fp << "\"/>" << std::endl;

View File

@ -23,6 +23,7 @@
#include "rename_modules.h"
#include "vtr_log.h"
#include "vtr_time.h"
#include "write_xml_fabric_pin_physical_location.h"
#include "write_xml_module_name_map.h"
/* begin namespace openfpga */
@ -269,6 +270,8 @@ template <class T>
int write_fabric_hierarchy_template(const T& openfpga_ctx, const Command& cmd,
const CommandContext& cmd_context) {
CommandOptionId opt_verbose = cmd.option("verbose");
CommandOptionId opt_exclude_empty_modules =
cmd.option("exclude_empty_modules");
/* Check the option '--file' is enabled or not
* Actually, it must be enabled as the shell interface will check
@ -278,6 +281,19 @@ int write_fabric_hierarchy_template(const T& openfpga_ctx, const Command& cmd,
VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file));
VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty());
CommandOptionId opt_module = cmd.option("module");
std::string root_module =
openfpga_ctx.module_name_map().name(generate_fpga_top_module_name());
if (true == cmd_context.option_enable(cmd, opt_module)) {
root_module = cmd_context.option_value(cmd, opt_module);
}
CommandOptionId opt_filter = cmd.option("filter");
std::string filter("*");
if (true == cmd_context.option_enable(cmd, opt_filter)) {
filter = cmd_context.option_value(cmd, opt_filter);
}
/* Default depth requirement, will not stop until the leaf */
int depth = -1;
CommandOptionId opt_depth = cmd.option("depth");
@ -296,7 +312,9 @@ int write_fabric_hierarchy_template(const T& openfpga_ctx, const Command& cmd,
/* Write hierarchy to a file */
return write_fabric_hierarchy_to_text_file(
openfpga_ctx.module_graph(), openfpga_ctx.module_name_map(), hie_file_name,
size_t(depth), cmd_context.option_enable(cmd, opt_verbose));
root_module, filter, size_t(depth),
cmd_context.option_enable(cmd, opt_exclude_empty_modules),
cmd_context.option_enable(cmd, opt_verbose));
}
/********************************************************************
@ -419,6 +437,41 @@ int write_module_naming_rules_template(const T& openfpga_ctx,
cmd_context.option_enable(cmd, opt_verbose));
}
/********************************************************************
* Write fabric pin physical location to a file
*******************************************************************/
template <class T>
int write_fabric_pin_physical_location_template(
const T& openfpga_ctx, const Command& cmd,
const CommandContext& cmd_context) {
CommandOptionId opt_verbose = cmd.option("verbose");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
CommandOptionId opt_show_invalid_side = cmd.option("show_invalid_side");
/* 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());
std::string file_name = cmd_context.option_value(cmd, opt_file);
std::string module_name("*"); /* Use a wildcard for everything */
CommandOptionId opt_module = cmd.option("module");
if (true == cmd_context.option_enable(cmd, opt_module)) {
module_name = cmd_context.option_value(cmd, opt_module);
}
/* Write hierarchy to a file */
return write_xml_fabric_pin_physical_location(
file_name.c_str(), module_name, openfpga_ctx.module_graph(),
cmd_context.option_enable(cmd, opt_show_invalid_side),
!cmd_context.option_enable(cmd, opt_no_time_stamp),
cmd_context.option_enable(cmd, opt_verbose));
}
} /* end namespace openfpga */
#endif

View File

@ -86,6 +86,9 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd,
openfpga_ctx.mutable_vpr_routing_annotation().init(
g_vpr_ctx.device().rr_graph);
// Incase the incoming edges are not built. This may happen when loading
// rr_graph from an external file
g_vpr_ctx.mutable_device().rr_graph_builder.build_in_edges();
annotate_vpr_rr_node_nets(g_vpr_ctx.device(), g_vpr_ctx.clustering(),
g_vpr_ctx.routing(),
openfpga_ctx.mutable_vpr_routing_annotation(),
@ -105,7 +108,6 @@ int link_arch_template(T& openfpga_ctx, const Command& cmd,
}
/* Build incoming edges as VPR only builds fan-out edges for each node */
g_vpr_ctx.mutable_device().rr_graph_builder.build_in_edges();
VTR_LOG("Built %ld incoming edges for routing resource graph\n",
g_vpr_ctx.device().rr_graph.in_edges_count());
VTR_ASSERT(g_vpr_ctx.device().rr_graph.validate_in_edges());

View File

@ -413,6 +413,35 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type,
return port_name;
}
/*********************************************************************
* Get the physical side for a routing track in a Connection Block module
* Upper_location: specify if an upper/lower prefix to be added.
* The location indicates where the bus port should be
* placed on the perimeter of the connection block
* - For X-directional CB:
* - upper is the left side
* - lower is the right side
* - For Y-directional CB:
* - upper is the bottom side
* - lower is the top side
*********************************************************************/
e_side get_cb_module_track_port_side(const t_rr_type& chan_type,
const bool& upper_location) {
/* Channel must be either CHANX or CHANY */
VTR_ASSERT((CHANX == chan_type) || (CHANY == chan_type));
/* Create a map between chan_type and module_prefix */
std::map<t_rr_type, std::map<bool, e_side>> port_side_map;
/* TODO: use a constexpr string to replace the fixed name? */
/* IMPORTANT: This part must be consistent with the mapping in the
* generate_cb_module_track_port_name() !!! */
port_side_map[CHANX][true] = LEFT;
port_side_map[CHANX][false] = RIGHT;
port_side_map[CHANY][true] = BOTTOM;
port_side_map[CHANY][false] = TOP;
return port_side_map[chan_type][upper_location];
}
/*********************************************************************
* Generate the port name for a routing track in a Connection Block module
* This function is created to ease the PnR for each unique routing module

View File

@ -97,6 +97,9 @@ std::string generate_sb_module_track_port_name(const t_rr_type& chan_type,
const e_side& module_side,
const PORTS& port_direction);
e_side get_cb_module_track_port_side(const t_rr_type& chan_type,
const bool& upper_location);
std::string generate_cb_module_track_port_name(const t_rr_type& chan_type,
const PORTS& port_direction,
const bool& upper_location);

View File

@ -461,12 +461,29 @@ ShellCommandId add_write_fabric_hierarchy_command_template(
shell_cmd.set_option_short_name(opt_file, "f");
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
/* Add an option '--module' */
CommandOptionId opt_module = shell_cmd.add_option(
"module", false,
"Specify the root module name(s) which should be considered. By default, "
"it is fpga_top. Regular expression is supported");
shell_cmd.set_option_require_value(opt_module, openfpga::OPT_STRING);
CommandOptionId opt_filter =
shell_cmd.add_option("filter", false,
"Specify the filter which allows user to select "
"modules to appear under each root module tree. By "
"default, it is *. Regular expression is supported");
shell_cmd.set_option_require_value(opt_filter, openfpga::OPT_STRING);
/* Add an option '--depth' */
CommandOptionId opt_depth = shell_cmd.add_option(
"depth", false,
"Specify the depth of hierarchy to which the writer should stop");
shell_cmd.set_option_require_value(opt_depth, openfpga::OPT_INT);
shell_cmd.add_option("exclude_empty_modules", false,
"Exclude modules with no qualified children (match the "
"names defined through filter) from the output file");
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Show verbose outputs");
@ -858,6 +875,55 @@ ShellCommandId add_write_module_naming_rules_command_template(
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: write_pin_physical_location
* - Add associated options
* - Add command dependency
*******************************************************************/
template <class T>
ShellCommandId add_write_fabric_pin_physical_location_command_template(
openfpga::Shell<T>& shell, const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds, const bool& hidden) {
Command shell_cmd("write_fabric_pin_physical_location");
/* Add an option '--file' in short '-f'*/
CommandOptionId opt_file = shell_cmd.add_option(
"file", true,
"file path to the XML file that contains pin physical location");
shell_cmd.set_option_short_name(opt_file, "f");
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
/* Add an option '--module'*/
CommandOptionId opt_module = shell_cmd.add_option(
"module", false,
"specify the module whose pin physical location should be outputted");
shell_cmd.set_option_require_value(opt_module, openfpga::OPT_STRING);
/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false,
"Do not print time stamp in output files");
shell_cmd.add_option(
"show_invalid_side", false,
"Include pins with invalid sides in output files. Recommended for "
"debugging as the output file may include a lot of useless information");
shell_cmd.add_option("verbose", false, "Show verbose outputs");
/* Add command to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(
shell_cmd,
"Output the pin physical location of an FPGA fabric to a given file",
hidden);
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_const_execute_function(
shell_cmd_id, write_fabric_pin_physical_location_template<T>);
/* Add command dependency to the Shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
template <class T>
void add_setup_command_templates(openfpga::Shell<T>& shell,
const bool& hidden = false) {
@ -1098,6 +1164,17 @@ void add_setup_command_templates(openfpga::Shell<T>& shell,
add_write_module_naming_rules_command_template<T>(
shell, openfpga_setup_cmd_class, cmd_dependency_write_module_naming_rules,
hidden);
/********************************
* Command 'write_fabric_pin_physical_location'
*/
/* The command should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> cmd_dependency_write_fabric_pin_physical_location;
cmd_dependency_write_fabric_pin_physical_location.push_back(
build_fabric_cmd_id);
add_write_fabric_pin_physical_location_command_template<T>(
shell, openfpga_setup_cmd_class,
cmd_dependency_write_fabric_pin_physical_location, hidden);
}
} /* end namespace openfpga */

View File

@ -250,6 +250,10 @@ ShellCommandId add_write_preconfigured_fabric_wrapper_command_template(
shell_cmd.add_option("include_signal_init", false,
"initialize all the signals in verilog testbenches");
/* add an option '--dump_waveform' */
shell_cmd.add_option("dump_waveform", false,
"add waveform output commands to the output file");
/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false,
"Do not print a time stamp in the output files");

View File

@ -169,6 +169,7 @@ int write_preconfigured_fabric_wrapper_template(
CommandOptionId opt_include_signal_init = cmd.option("include_signal_init");
CommandOptionId opt_embed_bitstream = cmd.option("embed_bitstream");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
CommandOptionId opt_dump_waveform = cmd.option("dump_waveform");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the
@ -184,6 +185,7 @@ int write_preconfigured_fabric_wrapper_template(
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_include_signal_init(
cmd_context.option_enable(cmd, opt_include_signal_init));
options.set_dump_waveform(cmd_context.option_enable(cmd, opt_dump_waveform));
options.set_print_formal_verification_top_netlist(true);
if (true == cmd_context.option_enable(cmd, opt_dut_module)) {

View File

@ -88,8 +88,9 @@ int build_device_module_graph(
module_manager, decoder_lib, vpr_device_ctx,
openfpga_ctx.vpr_device_annotation(), openfpga_ctx.arch().circuit_lib,
openfpga_ctx.mux_lib(), openfpga_ctx.arch().tile_annotations,
openfpga_ctx.arch().config_protocol.type(), sram_model, duplicate_grid_pin,
group_config_block, verbose);
openfpga_ctx.arch().config_protocol.type(), sram_model,
openfpga_ctx.arch().config_protocol.ql_memory_bank_config_setting(),
duplicate_grid_pin, group_config_block, verbose);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}

View File

@ -123,8 +123,10 @@ void add_grid_module_duplicated_pb_type_ports(
}
BasicPort grid_port(port_name, 0, 0);
/* Add the port to the module */
module_manager.add_port(grid_module, grid_port,
pin_type2type_map[pin_class_type]);
ModulePortId grid_port_id = module_manager.add_port(
grid_module, grid_port, pin_type2type_map[pin_class_type]);
/* Set port side */
module_manager.set_port_side(grid_module, grid_port_id, side);
} else {
/* For each DRIVER pin, we create two copies.
* One with a postfix of upper, indicating it is located on the
@ -136,15 +138,19 @@ void add_grid_module_duplicated_pb_type_ports(
iwidth, iheight, subtile_index, side, pin_info, true);
BasicPort grid_upper_port(upper_port_name, 0, 0);
/* Add the port to the module */
module_manager.add_port(grid_module, grid_upper_port,
pin_type2type_map[pin_class_type]);
ModulePortId grid_upper_port_id = module_manager.add_port(
grid_module, grid_upper_port, pin_type2type_map[pin_class_type]);
/* Set port side */
module_manager.set_port_side(grid_module, grid_upper_port_id, side);
std::string lower_port_name = generate_grid_duplicated_port_name(
iwidth, iheight, subtile_index, side, pin_info, false);
BasicPort grid_lower_port(lower_port_name, 0, 0);
/* Add the port to the module */
module_manager.add_port(grid_module, grid_lower_port,
pin_type2type_map[pin_class_type]);
ModulePortId grid_lower_port_id = module_manager.add_port(
grid_module, grid_lower_port, pin_type2type_map[pin_class_type]);
/* Set port side */
module_manager.set_port_side(grid_module, grid_lower_port_id, side);
}
}
}

View File

@ -103,8 +103,10 @@ static void add_grid_module_pb_type_ports(
}
BasicPort grid_port(port_name, 0, 0);
/* Add the port to the module */
module_manager.add_port(grid_module, grid_port,
pin_type2type_map[pin_class_type]);
ModulePortId grid_port_id = module_manager.add_port(
grid_module, grid_port, pin_type2type_map[pin_class_type]);
/* Set port side */
module_manager.set_port_side(grid_module, grid_port_id, side);
}
}
}
@ -1164,6 +1166,7 @@ static int build_physical_tile_module(
const e_config_protocol_type& sram_orgz_type,
const CircuitModelId& sram_model, t_physical_tile_type_ptr phy_block_type,
const TileAnnotation& tile_annotation, const e_side& border_side,
const QLMemoryBankConfigSetting* ql_memory_bank_config_setting,
const bool& duplicate_grid_pin, const bool& group_config_block,
const bool& verbose) {
int status = CMD_EXEC_SUCCESS;
@ -1332,9 +1335,10 @@ static int build_physical_tile_module(
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,
module_num_config_bits);
add_pb_sram_ports_to_module_manager(
module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type,
module_num_config_bits,
ql_memory_bank_config_setting->pb_setting(phy_block_type->name).num_wl);
}
/* Add module nets to connect memory cells inside
@ -1372,8 +1376,10 @@ int build_grid_modules(
const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib,
const TileAnnotation& tile_annotation,
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) {
const CircuitModelId& sram_model,
const QLMemoryBankConfigSetting* ql_memory_bank_config_setting,
const bool& duplicate_grid_pin, const bool& group_config_block,
const bool& verbose) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Build grid modules");
@ -1429,7 +1435,8 @@ int build_grid_modules(
status = build_physical_tile_module(
module_manager, decoder_lib, device_annotation, circuit_lib,
sram_orgz_type, sram_model, &physical_tile, tile_annotation,
io_type_side, duplicate_grid_pin, group_config_block, verbose);
io_type_side, ql_memory_bank_config_setting, duplicate_grid_pin,
group_config_block, verbose);
if (status != CMD_EXEC_SUCCESS) {
return CMD_EXEC_FATAL_ERROR;
}
@ -1439,7 +1446,8 @@ int build_grid_modules(
status = build_physical_tile_module(
module_manager, decoder_lib, device_annotation, circuit_lib,
sram_orgz_type, sram_model, &physical_tile, tile_annotation, NUM_SIDES,
duplicate_grid_pin, group_config_block, verbose);
ql_memory_bank_config_setting, duplicate_grid_pin, group_config_block,
verbose);
if (status != CMD_EXEC_SUCCESS) {
return CMD_EXEC_FATAL_ERROR;
}

View File

@ -7,6 +7,7 @@
#include "decoder_library.h"
#include "module_manager.h"
#include "mux_library.h"
#include "ql_memory_bank_config_setting.h"
#include "tile_annotation.h"
#include "vpr_context.h"
#include "vpr_device_annotation.h"
@ -24,8 +25,10 @@ int build_grid_modules(
const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib,
const TileAnnotation& tile_annotation,
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);
const CircuitModelId& sram_model,
const QLMemoryBankConfigSetting* ql_memory_bank_config_setting,
const bool& duplicate_grid_pin, const bool& group_config_block,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -320,19 +320,58 @@ ModulePortId find_connection_block_module_ipin_port(
return ipin_port_id;
}
/*********************************************************************
* Generate a port for a connection block
********************************************************************/
ModulePortId find_connection_block_module_opin_port(
const ModuleManager& module_manager, const ModuleId& cb_module,
const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraphView& rr_graph, const RRGSB& rr_gsb,
const RRNodeId& src_rr_node) {
/* Ensure the src_rr_node is an input pin of a CLB */
VTR_ASSERT(OPIN == rr_graph.node_type(src_rr_node));
/* Search all the sides of a SB, see this drive_rr_node is an INPUT of this SB
*/
enum e_side cb_opin_side = NUM_SIDES;
int cb_opin_index = -1;
rr_gsb.get_node_side_and_index(rr_graph, src_rr_node, IN_PORT, cb_opin_side,
cb_opin_index);
/* We need to be sure that drive_rr_node is part of the CB */
VTR_ASSERT((-1 != cb_opin_index) && (NUM_SIDES != cb_opin_side));
std::string port_name = generate_cb_module_grid_port_name(
cb_opin_side, grids, vpr_device_annotation, rr_graph,
rr_gsb.get_opin_node(cb_opin_side, cb_opin_index));
/* Must find a valid port id in the Switch Block module */
ModulePortId opin_port_id =
module_manager.find_module_port(cb_module, port_name);
VTR_ASSERT(true ==
module_manager.valid_module_port_id(cb_module, opin_port_id));
return opin_port_id;
}
/*********************************************************************
* Generate a list of routing track middle output ports
* for routing multiplexer inside the connection block
********************************************************************/
std::vector<ModulePinInfo> find_connection_block_module_input_ports(
const ModuleManager& module_manager, const ModuleId& cb_module,
const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type,
const std::vector<RRNodeId>& input_rr_nodes) {
std::vector<ModulePinInfo> input_ports;
for (auto input_rr_node : input_rr_nodes) {
input_ports.push_back(find_connection_block_module_chan_port(
module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_node));
if (OPIN == rr_graph.node_type(input_rr_node)) {
input_ports.push_back(ModulePinInfo(
find_connection_block_module_opin_port(module_manager, cb_module, grids,
vpr_device_annotation, rr_graph,
rr_gsb, input_rr_node),
0));
} else {
input_ports.push_back(find_connection_block_module_chan_port(
module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_node));
}
}
return input_ports;

View File

@ -62,8 +62,15 @@ ModulePortId find_connection_block_module_ipin_port(
const RRGraphView& rr_graph, const RRGSB& rr_gsb,
const RRNodeId& src_rr_node);
ModulePortId find_connection_block_module_opin_port(
const ModuleManager& module_manager, const ModuleId& cb_module,
const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraphView& rr_graph, const RRGSB& rr_gsb,
const RRNodeId& src_rr_node);
std::vector<ModulePinInfo> find_connection_block_module_input_ports(
const ModuleManager& module_manager, const ModuleId& cb_module,
const DeviceGrid& grids, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraphView& rr_graph, const RRGSB& rr_gsb, const t_rr_type& cb_type,
const std::vector<RRNodeId>& input_rr_nodes);

View File

@ -435,6 +435,9 @@ static void build_switch_block_module(
BasicPort chan_input_port(chan_input_port_name, chan_input_port_size);
ModulePortId chan_input_port_id = module_manager.add_port(
sb_module, chan_input_port, ModuleManager::MODULE_INPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(sb_module, chan_input_port_id,
side_manager.get_side());
/* Cache the input net */
for (const size_t& pin : chan_input_port.pins()) {
@ -446,8 +449,11 @@ static void build_switch_block_module(
std::string chan_output_port_name = generate_sb_module_track_port_name(
chan_type, side_manager.get_side(), OUT_PORT);
BasicPort chan_output_port(chan_output_port_name, chan_output_port_size);
module_manager.add_port(sb_module, chan_output_port,
ModuleManager::MODULE_OUTPUT_PORT);
ModulePortId chan_output_port_id = module_manager.add_port(
sb_module, chan_output_port, ModuleManager::MODULE_OUTPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(sb_module, chan_output_port_id,
side_manager.get_side());
}
/* Dump OPINs of adjacent CLBs */
@ -468,6 +474,9 @@ static void build_switch_block_module(
/* Grid outputs are inputs of switch blocks */
ModulePortId input_port_id = module_manager.add_port(
sb_module, module_port, ModuleManager::MODULE_INPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(sb_module, input_port_id,
side_manager.get_side());
/* Cache the input net */
ModuleNetId net = create_module_source_pin_net(
@ -682,8 +691,9 @@ static void build_connection_block_mux_module(
/* TODO: Generate input ports that are wired to the input bus of the routing
* multiplexer */
std::vector<ModulePinInfo> cb_input_port_ids =
find_connection_block_module_input_ports(
module_manager, cb_module, rr_graph, rr_gsb, cb_type, driver_rr_nodes);
find_connection_block_module_input_ports(module_manager, cb_module, grids,
device_annotation, rr_graph,
rr_gsb, cb_type, driver_rr_nodes);
/* Link input bus port to Switch Block inputs */
std::vector<CircuitPortId> mux_model_input_ports =
@ -925,6 +935,9 @@ static void build_connection_block_module(
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_upper_input_port_id = module_manager.add_port(
cb_module, chan_upper_input_port, ModuleManager::MODULE_INPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(cb_module, chan_upper_input_port_id,
get_cb_module_track_port_side(cb_type, true));
/* Lower input port: W/2 == 1 tracks */
std::string chan_lower_input_port_name =
@ -933,6 +946,9 @@ static void build_connection_block_module(
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_lower_input_port_id = module_manager.add_port(
cb_module, chan_lower_input_port, ModuleManager::MODULE_INPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(cb_module, chan_lower_input_port_id,
get_cb_module_track_port_side(cb_type, false));
/* Upper output port: W/2 == 0 tracks */
std::string chan_upper_output_port_name =
@ -941,6 +957,9 @@ static void build_connection_block_module(
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_upper_output_port_id = module_manager.add_port(
cb_module, chan_upper_output_port, ModuleManager::MODULE_OUTPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(cb_module, chan_upper_output_port_id,
get_cb_module_track_port_side(cb_type, true));
/* Lower output port: W/2 == 1 tracks */
std::string chan_lower_output_port_name =
@ -949,6 +968,9 @@ static void build_connection_block_module(
rr_gsb.get_cb_chan_width(cb_type) / 2);
ModulePortId chan_lower_output_port_id = module_manager.add_port(
cb_module, chan_lower_output_port, ModuleManager::MODULE_OUTPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(cb_module, chan_lower_output_port_id,
get_cb_module_track_port_side(cb_type, false));
/* Add the input pins of grids, which are output ports of the connection block
*/
@ -957,16 +979,39 @@ static void build_connection_block_module(
enum e_side cb_ipin_side = cb_ipin_sides[iside];
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side);
++inode) {
const RRNodeId& ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode);
vtr::Point<size_t> port_coord(rr_graph.node_xlow(ipin_node),
rr_graph.node_ylow(ipin_node));
RRNodeId ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode);
std::string port_name = generate_cb_module_grid_port_name(
cb_ipin_side, grids, device_annotation, rr_graph, ipin_node);
BasicPort module_port(port_name,
1); /* Every grid output has a port size of 1 */
/* Grid outputs are inputs of switch blocks */
module_manager.add_port(cb_module, module_port,
ModuleManager::MODULE_OUTPUT_PORT);
ModulePortId module_port_id = module_manager.add_port(
cb_module, module_port, ModuleManager::MODULE_OUTPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(cb_module, module_port_id, cb_ipin_side);
}
}
/* Add the output pins of grids which are input ports of the connection block,
* if there is any */
std::vector<ModulePortId> opin_module_port_ids;
std::vector<enum e_side> cb_opin_sides = rr_gsb.get_cb_opin_sides(cb_type);
for (size_t iside = 0; iside < cb_opin_sides.size(); ++iside) {
enum e_side cb_opin_side = cb_opin_sides[iside];
for (size_t inode = 0;
inode < rr_gsb.get_num_cb_opin_nodes(cb_type, cb_opin_side); ++inode) {
RRNodeId opin_node =
rr_gsb.get_cb_opin_node(cb_type, cb_opin_side, inode);
std::string port_name = generate_cb_module_grid_port_name(
cb_opin_side, grids, device_annotation, rr_graph, opin_node);
BasicPort module_port(port_name,
1); /* Every grid output has a port size of 1 */
/* Grid outputs are inputs of switch blocks */
ModulePortId module_port_id = module_manager.add_port(
cb_module, module_port, ModuleManager::MODULE_INPUT_PORT);
/* Add side to the port */
module_manager.set_port_side(cb_module, module_port_id, cb_opin_side);
opin_module_port_ids.push_back(module_port_id);
}
}
@ -1011,6 +1056,13 @@ static void build_connection_block_module(
chan_lower_input_port_id, chan_lower_input_port.pins()[pin_id])] = net;
}
for (ModulePortId opin_module_port_id : opin_module_port_ids) {
ModuleNetId net = create_module_source_pin_net(
module_manager, cb_module, cb_module, 0, opin_module_port_id, 0);
/* Cache the module net */
input_port_to_module_nets[ModulePinInfo(opin_module_port_id, 0)] = net;
}
/* Add sub modules of routing multiplexers or direct interconnect*/
for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) {
enum e_side cb_ipin_side = cb_ipin_sides[iside];

View File

@ -211,6 +211,10 @@ static int build_tile_module_port_and_nets_between_sb_and_pb(
ModulePortId src_tile_port_id = module_manager.add_port(
tile_module, src_grid_port,
ModuleManager::e_module_port_type::MODULE_INPUT_PORT);
/* Set port side, inherit from the child module */
module_manager.set_port_side(
tile_module, src_tile_port_id,
module_manager.port_side(sink_sb_module, sink_sb_port_id));
VTR_LOGV(
verbose,
"Adding ports '%s' to tile as required by the switch block '%s'...\n",
@ -442,6 +446,10 @@ static int build_tile_module_port_and_nets_between_cb_and_pb(
ModulePortId sink_tile_port_id = module_manager.add_port(
tile_module, src_cb_port,
ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT);
/* Set port side, inherit from the child module */
module_manager.set_port_side(
tile_module, sink_tile_port_id,
module_manager.port_side(src_cb_module, src_cb_port_id));
VTR_LOGV(verbose,
"Adding ports '%s' to tile as required by the connection "
"block '%s'...\n",
@ -463,6 +471,158 @@ static int build_tile_module_port_and_nets_between_cb_and_pb(
}
}
}
/* Iterate over the output pins of the Connection Block */
std::vector<enum e_side> cb_opin_sides = module_cb.get_cb_opin_sides(cb_type);
for (size_t iside = 0; iside < cb_opin_sides.size(); ++iside) {
enum e_side cb_opin_side = cb_opin_sides[iside];
for (size_t inode = 0;
inode < module_cb.get_num_cb_opin_nodes(cb_type, cb_opin_side);
++inode) {
/* Collect source-related information */
RRNodeId module_opin_node =
module_cb.get_cb_opin_node(cb_type, cb_opin_side, inode);
vtr::Point<size_t> cb_src_port_coord(
rr_graph.node_xlow(module_opin_node),
rr_graph.node_ylow(module_opin_node));
std::string src_cb_port_name = generate_cb_module_grid_port_name(
cb_opin_side, grids, vpr_device_annotation, rr_graph, module_opin_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_opin_node =
rr_gsb.get_cb_opin_node(cb_type, cb_opin_side, inode);
vtr::Point<size_t> grid_coordinate(
rr_graph.node_xlow(instance_opin_node),
rr_graph.node_ylow(instance_opin_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_opin_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_cb_opin_node(cb_type, cb_opin_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. Note that the sink and source tags are
* reverted in the following code!!! */
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, sink_grid_module, sink_grid_instance,
sink_grid_port_id, sink_grid_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(tile_module, net, src_cb_module,
src_cb_instance, src_cb_port_id,
src_cb_port.pins()[pin_id]);
}
}
} else {
/* Special: No need to create a new port! Since we only support OPINs
* from Switch blocks. Walk through all the switch blocks and find the
* new port that it is created when connecting pb and sb */
if (!frame_view) {
/* This is the source sb that is added to the top module */
const RRGSB& module_sb = device_rr_gsb.get_gsb(module_gsb_coordinate);
vtr::Point<size_t> 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 isb = fabric_tile.find_sb_index_in_tile(fabric_tile_id,
module_sb_coordinate);
std::string temp_sb_module_name = generate_switch_block_module_name(
fabric_tile.sb_coordinates(fabric_tile_id)[isb]);
if (name_module_using_index) {
temp_sb_module_name =
generate_switch_block_module_name_using_index(isb);
}
/* FIXME: may find a way to determine the side. Currently using
* cb_opin_side is fine */
vtr::Point<size_t> sink_sb_port_coord(
rr_graph.node_xlow(module_sb.get_opin_node(cb_opin_side, inode)),
rr_graph.node_ylow(module_sb.get_opin_node(cb_opin_side, inode)));
std::string sink_sb_port_name = generate_sb_module_grid_port_name(
cb_opin_side,
get_rr_graph_single_node_side(
rr_graph, module_sb.get_opin_node(cb_opin_side, inode)),
grids, vpr_device_annotation, rr_graph,
module_sb.get_opin_node(cb_opin_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);
sink_sb_port.set_name(generate_tile_module_port_name(
temp_sb_module_name, sink_sb_port.get_name()));
ModulePortId src_tile_port_id = module_manager.find_module_port(
tile_module, sink_sb_port.get_name());
/* Create a net for each pin */
VTR_ASSERT(src_cb_port.pins().size() == sink_sb_port.pins().size());
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, tile_module, 0, src_tile_port_id,
sink_sb_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(tile_module, net, src_cb_module,
src_cb_instance, src_cb_port_id,
src_cb_port.pins()[pin_id]);
}
}
}
}
}
return CMD_EXEC_SUCCESS;
}
@ -739,6 +899,10 @@ static int build_tile_module_port_and_nets_between_sb_and_cb(
ModulePortId tile_chan_output_port_id = module_manager.add_port(
tile_module, chan_output_port,
ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT);
/* Set port side, inherit from the child module */
module_manager.set_port_side(
tile_module, tile_chan_output_port_id,
module_manager.port_side(sb_module_id, sb_chan_output_port_id));
VTR_LOGV(
verbose,
"Adding ports '%s' to tile as required by the switch block '%s'...\n",
@ -816,6 +980,10 @@ static int build_tile_module_one_port_from_cb(
* avoid naming conflicts */
ModulePortId tile_module_port_id =
module_manager.add_port(tile_module, tile_chan_port, chan_port_type);
/* Set port side, inherit from the child module */
module_manager.set_port_side(
tile_module, tile_module_port_id,
module_manager.port_side(cb_module, chan_port_id));
if (!frame_view) {
for (size_t pin_id = 0; pin_id < chan_port.pins().size(); ++pin_id) {
@ -1161,6 +1329,10 @@ static int build_tile_port_and_nets_from_pb(
ModulePortId tile_module_port_id = module_manager.add_port(
tile_module, pb_port,
ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT);
/* Set port side, inherit from the child module */
module_manager.set_port_side(
tile_module, tile_module_port_id,
module_manager.port_side(pb_module, pb_module_port_id));
if (!frame_view) {
ModuleNetId net = create_module_source_pin_net(
module_manager, tile_module, pb_module, pb_instance,

View File

@ -563,6 +563,90 @@ static void add_top_module_nets_connect_grids_and_cb(
}
}
}
/* Iterate over the input pins of the Connection Block */
std::vector<enum e_side> cb_opin_sides = module_cb.get_cb_opin_sides(cb_type);
for (size_t iside = 0; iside < cb_opin_sides.size(); ++iside) {
enum e_side cb_opin_side = cb_opin_sides[iside];
for (size_t inode = 0;
inode < module_cb.get_num_cb_opin_nodes(cb_type, cb_opin_side);
++inode) {
/* Collect source-related information */
RRNodeId module_opin_node =
module_cb.get_cb_opin_node(cb_type, cb_opin_side, inode);
vtr::Point<size_t> cb_src_port_coord(
rr_graph.node_xlow(module_opin_node),
rr_graph.node_ylow(module_opin_node));
std::string src_cb_port_name = generate_cb_module_grid_port_name(
cb_opin_side, grids, vpr_device_annotation, rr_graph, module_opin_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_opin_node =
rr_gsb.get_cb_opin_node(cb_type, cb_opin_side, inode);
vtr::Point<size_t> grid_coordinate(
rr_graph.node_xlow(instance_opin_node),
rr_graph.node_ylow(instance_opin_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_instance =
grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()];
size_t sink_grid_pin_index = rr_graph.node_pin_num(instance_opin_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_cb_opin_node(cb_type, cb_opin_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);
/* 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. Note that the src/sink tag is reverted in
* the following code. */
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, sink_grid_module, sink_grid_instance,
sink_grid_port_id, sink_grid_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(top_module, net, src_cb_module,
src_cb_instance, src_cb_port_id,
src_cb_port.pins()[pin_id]);
}
}
}
}
/********************************************************************

View File

@ -1110,14 +1110,14 @@ static void add_top_module_nets_cmos_memory_bank_config_bus(
/* Each memory bank has a unified number of BL/WLs */
size_t num_bls = 0;
for (const auto& curr_config_bits : num_config_bits) {
num_bls =
std::max(num_bls, find_memory_decoder_data_size(curr_config_bits.first));
num_bls = std::max(
num_bls, find_memory_decoder_data_size(curr_config_bits.first, 0, true));
}
size_t num_wls = 0;
for (const auto& curr_config_bits : num_config_bits) {
num_wls =
std::max(num_wls, find_memory_decoder_data_size(curr_config_bits.first));
num_wls = std::max(
num_wls, find_memory_decoder_data_size(curr_config_bits.first, 0, false));
}
/* Create separated memory bank circuitry, i.e., BL/WL decoders for each

View File

@ -1,12 +1,14 @@
/***************************************************************************************
* Output internal structure of Module Graph hierarchy to file formats
***************************************************************************************/
#include <regex>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "command_exit_codes.h"
#include "fabric_hierarchy_writer.h"
#include "openfpga_digest.h"
#include "openfpga_naming.h"
@ -14,6 +16,32 @@
/* begin namespace openfpga */
namespace openfpga {
/** Identify if the module has no child whose name matches the filter */
static bool module_filter_all_children(const ModuleManager& module_manager,
const ModuleId& curr_module,
const ModuleNameMap& module_name_map,
const std::string& module_name_filter) {
for (const ModuleId& child_module :
module_manager.child_modules(curr_module)) {
/* Filter out the names which do not match the pattern */
std::string child_module_name = module_manager.module_name(child_module);
if (module_name_map.name_exist(child_module_name)) {
child_module_name = module_name_map.name(child_module_name);
}
std::string pattern = module_name_filter;
std::regex star_replace("\\*");
std::regex questionmark_replace("\\?");
std::string wildcard_pattern =
std::regex_replace(std::regex_replace(pattern, star_replace, ".*"),
questionmark_replace, ".");
std::regex wildcard_regex(wildcard_pattern);
if (std::regex_match(child_module_name, wildcard_regex)) {
return false;
}
}
return true;
}
/***************************************************************************************
* Recursively output child module of the parent_module to a text file
* We use Depth-First Search (DFS) here so that we can output a tree down to
@ -23,52 +51,88 @@ namespace openfpga {
static int rec_output_module_hierarchy_to_text_file(
std::fstream& fp, const size_t& hie_depth_to_stop,
const size_t& current_hie_depth, const ModuleManager& module_manager,
const ModuleId& parent_module, const bool& verbose) {
const ModuleId& parent_module, const ModuleNameMap& module_name_map,
const std::string& module_name_filter, const bool& verbose) {
/* Stop if hierarchy depth is beyond the stop line */
if (hie_depth_to_stop < current_hie_depth) {
return 0;
return CMD_EXEC_SUCCESS;
}
if (false == valid_file_stream(fp)) {
return 2;
return CMD_EXEC_FATAL_ERROR;
}
/* Check if all the child module has not qualified grand-child, use leaf for
* this level */
bool use_list = true;
for (const ModuleId& child_module :
module_manager.child_modules(parent_module)) {
if (!module_filter_all_children(module_manager, child_module,
module_name_map, module_name_filter)) {
use_list = false;
break;
}
}
/* For debug use only
VTR_LOGV(verbose, "Current depth: %lu, Target depth: %lu\n",
current_hie_depth, hie_depth_to_stop);
*/
std::string parent_module_name = module_manager.module_name(parent_module);
if (module_name_map.name_exist(parent_module_name)) {
parent_module_name = module_name_map.name(parent_module_name);
}
VTR_LOGV(
use_list && verbose, "Use list as module '%s' contains only leaf nodes\n",
module_name_map.name(module_manager.module_name(parent_module)).c_str());
/* Iterate over all the child module */
for (const ModuleId& child_module :
module_manager.child_modules(parent_module)) {
if (false == write_space_to_file(fp, current_hie_depth * 2)) {
return 2;
}
if (true != module_manager.valid_module_id(child_module)) {
VTR_LOGV_ERROR(verbose, "Unable to find the child module '%u'!\n",
size_t(child_module));
return 1;
VTR_LOGV_ERROR(
verbose,
"Unable to find the child module '%s' under its parent '%s'!\n",
module_manager.module_name(child_module).c_str(),
module_manager.module_name(parent_module).c_str());
return CMD_EXEC_FATAL_ERROR;
}
fp << "- ";
fp << module_manager.module_name(child_module);
/* If this is the leaf node, we leave a new line
* Otherwise, we will leave a ':' to be compatible to YAML file format
*/
if ((0 != module_manager.child_modules(child_module).size()) &&
(hie_depth_to_stop >= current_hie_depth + 1)) {
fp << ":";
/* Filter out the names which do not match the pattern */
std::string child_module_name = module_manager.module_name(child_module);
if (module_name_map.name_exist(child_module_name)) {
child_module_name = module_name_map.name(child_module_name);
}
std::string pattern = module_name_filter;
std::regex star_replace("\\*");
std::regex questionmark_replace("\\?");
std::string wildcard_pattern =
std::regex_replace(std::regex_replace(pattern, star_replace, ".*"),
questionmark_replace, ".");
std::regex wildcard_regex(wildcard_pattern);
if (!std::regex_match(child_module_name, wildcard_regex)) {
continue;
}
fp << "\n";
if (false == write_space_to_file(fp, current_hie_depth * 2)) {
return CMD_EXEC_FATAL_ERROR;
}
if (hie_depth_to_stop == current_hie_depth || use_list) {
fp << "- " << child_module_name.c_str() << "\n";
} else {
fp << child_module_name.c_str() << ":\n";
}
/* Go to next level */
int status = rec_output_module_hierarchy_to_text_file(
fp, hie_depth_to_stop,
current_hie_depth + 1, /* Increment the depth for the next level */
module_manager, child_module, verbose);
if (0 != status) {
module_manager, child_module, module_name_map, module_name_filter,
verbose);
if (status != CMD_EXEC_SUCCESS) {
return status;
}
}
return 0;
return CMD_EXEC_SUCCESS;
}
/***************************************************************************************
@ -83,11 +147,11 @@ static int rec_output_module_hierarchy_to_text_file(
* Return 1 if there are more serious bugs in the architecture
* Return 2 if fail when creating files
***************************************************************************************/
int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager,
const ModuleNameMap& module_name_map,
const std::string& fname,
const size_t& hie_depth_to_stop,
const bool& verbose) {
int write_fabric_hierarchy_to_text_file(
const ModuleManager& module_manager, const ModuleNameMap& module_name_map,
const std::string& fname, const std::string& root_module_names,
const std::string& module_name_filter, const size_t& hie_depth_to_stop,
const bool& exclude_empty_modules, const bool& verbose) {
std::string timer_message =
std::string("Write fabric hierarchy to plain-text file '") + fname +
std::string("'");
@ -111,35 +175,61 @@ int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager,
/* Validate the file stream */
check_file_stream(fname.c_str(), fp);
/* Find top-level module */
std::string top_module_name =
module_name_map.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;
size_t cnt = 0;
/* Use regular expression to capture the module whose name matches the pattern
*/
for (ModuleId curr_module : module_manager.modules()) {
std::string curr_module_name = module_manager.module_name(curr_module);
if (module_name_map.name_exist(curr_module_name)) {
curr_module_name = module_name_map.name(curr_module_name);
}
std::string pattern = root_module_names;
std::regex star_replace("\\*");
std::regex questionmark_replace("\\?");
std::string wildcard_pattern =
std::regex_replace(std::regex_replace(pattern, star_replace, ".*"),
questionmark_replace, ".");
std::regex wildcard_regex(wildcard_pattern);
if (!std::regex_match(curr_module_name, wildcard_regex)) {
continue;
}
/* Filter out module without children if required */
if (exclude_empty_modules &&
module_filter_all_children(module_manager, curr_module, module_name_map,
module_name_filter)) {
continue;
}
VTR_LOGV(verbose, "Select module '%s' as root\n", curr_module_name.c_str());
/* Record current depth of module: top module is the root with 0 depth */
size_t hie_depth = 0;
fp << curr_module_name << ":"
<< "\n";
/* Visit child module recursively and output the hierarchy */
int err_code = rec_output_module_hierarchy_to_text_file(
fp, hie_depth_to_stop, hie_depth + 1, /* Start with level 1 */
module_manager, curr_module, module_name_map, module_name_filter,
verbose);
/* Catch error code and exit if required */
if (err_code == CMD_EXEC_FATAL_ERROR) {
return err_code;
}
cnt++;
}
/* Record current depth of module: top module is the root with 0 depth */
size_t hie_depth = 0;
if (hie_depth_to_stop < hie_depth) {
return 0;
if (cnt == 0) {
VTR_LOG_ERROR(
"Unable to find any module matching the root module name pattern '%s'!\n",
root_module_names.c_str());
return CMD_EXEC_FATAL_ERROR;
}
fp << top_module_name << ":"
<< "\n";
/* Visit child module recursively and output the hierarchy */
int err_code = rec_output_module_hierarchy_to_text_file(
fp, hie_depth_to_stop, hie_depth + 1, /* Start with level 1 */
module_manager, top_module, verbose);
VTR_LOG("Outputted %lu modules as root\n", cnt);
/* close a file */
fp.close();
return err_code;
return CMD_EXEC_SUCCESS;
}
} /* end namespace openfpga */

View File

@ -14,11 +14,11 @@
/* begin namespace openfpga */
namespace openfpga {
int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager,
const ModuleNameMap& module_name_map,
const std::string& fname,
const size_t& hie_depth_to_stop,
const bool& verbose);
int write_fabric_hierarchy_to_text_file(
const ModuleManager& module_manager, const ModuleNameMap& module_name_map,
const std::string& fname, const std::string& root_module_names,
const std::string& module_name_filter, const size_t& hie_depth_to_stop,
const bool& exclude_empty_modules, const bool& verbose);
} /* end namespace openfpga */

View File

@ -0,0 +1,13 @@
#ifndef FABRIC_PIN_PHYSICAL_LOCATION_XML_CONSTANTS_H
#define FABRIC_PIN_PHYSICAL_LOCATION_XML_CONSTANTS_H
/* Constants required by XML parser */
constexpr const char* XML_PINLOC_ROOT_NAME = "pin_location";
constexpr const char* XML_MODULE_NODE_NAME = "module";
constexpr const char* XML_MODULE_ATTRIBUTE_NAME = "name";
constexpr const char* XML_MODULE_PINLOC_NODE_NAME = "loc";
constexpr const char* XML_MODULE_PINLOC_ATTRIBUTE_PIN = "pin";
constexpr const char* XML_MODULE_PINLOC_ATTRIBUTE_SIDE = "side";
#endif

View File

@ -304,6 +304,12 @@ std::vector<BasicPort> ModuleManager::module_ports_by_type(
return ports;
}
e_side ModuleManager::port_side(const ModuleId& module_id,
const ModulePortId& port_id) const {
VTR_ASSERT(valid_module_port_id(module_id, port_id));
return port_sides_[module_id][port_id];
}
/* Find a list of port ids of a module by a given types */
std::vector<ModulePortId> ModuleManager::module_port_ids_by_type(
const ModuleId& module_id, const enum e_module_port_type& port_type) const {
@ -746,6 +752,7 @@ ModuleId ModuleManager::add_module(const std::string& name) {
port_is_wire_.emplace_back();
port_is_mappable_io_.emplace_back();
port_is_register_.emplace_back();
port_sides_.emplace_back();
port_preproc_flags_.emplace_back();
num_nets_.emplace_back(0);
@ -789,6 +796,8 @@ ModulePortId ModuleManager::add_port(const ModuleId& module,
port_ids_[module].push_back(port);
ports_[module].push_back(port_info);
port_types_[module].push_back(port_type);
/* Deposit invalid value for each side */
port_sides_[module].push_back(NUM_SIDES);
port_is_wire_[module].push_back(false);
port_is_mappable_io_[module].push_back(false);
port_is_register_[module].push_back(false);
@ -893,6 +902,15 @@ void ModuleManager::set_port_preproc_flag(const ModuleId& module,
port_preproc_flags_[module][port] = preproc_flag;
}
/* Set the side for a pin of a port port */
void ModuleManager::set_port_side(const ModuleId& module,
const ModulePortId& port,
const e_side& pin_side) {
/* Must find something, otherwise drop an error */
VTR_ASSERT(valid_module_port_id(module, port));
port_sides_[module][port] = pin_side;
}
/* Add a child module to a parent module */
void ModuleManager::add_child_module(const ModuleId& parent_module,
const ModuleId& child_module,

View File

@ -9,6 +9,7 @@
#include "module_manager_fwd.h"
#include "openfpga_port.h"
#include "physical_types.h"
#include "vtr_geometry.h"
#include "vtr_vector.h"
@ -273,6 +274,10 @@ class ModuleManager {
/* Find the type of a port */
ModuleManager::e_module_port_type port_type(const ModuleId& module,
const ModulePortId& port) const;
/* Get the physical side of a port. Note that not every pin has a valid side.
* An invalid value NUM_SIDES will be returned when the pin does not has a
* specific physical location */
e_side port_side(const ModuleId& module, const ModulePortId& port) const;
/* Find if a port is a wire connection */
bool port_is_wire(const ModuleId& module, const ModulePortId& port) const;
/* Find if a port is mappable to an I/O from users' implementations */
@ -369,6 +374,11 @@ class ModuleManager {
/* Set the preprocessing flag for a port */
void set_port_preproc_flag(const ModuleId& module, const ModulePortId& port,
const std::string& preproc_flag);
/* Set side to a given pin of a module port. Note that the pin id must be a
* valid one. Otherwise, abort and error out. The valid pin range can be get
* from module_port().pins() */
void set_port_side(const ModuleId& module, const ModulePortId& port,
const e_side& pin_side);
/** @brief Add a child module to a parent module.
* By default, it considers the child module as an I/O child, and update the
* children list of I/O modules inside It not needed, just turn it off. Then
@ -626,6 +636,8 @@ class ModuleManager {
ports_; /* List of ports for each Module */
vtr::vector<ModuleId, vtr::vector<ModulePortId, enum e_module_port_type>>
port_types_; /* Type of ports */
vtr::vector<ModuleId, vtr::vector<ModulePortId, e_side>>
port_sides_; /* Type of ports */
vtr::vector<ModuleId, vtr::vector<ModulePortId, bool>>
port_is_mappable_io_; /* If the port is mappable to an I/O for user's
implementations */

View File

@ -0,0 +1,192 @@
/***************************************************************************************
* Output internal structure of module graph to XML format
***************************************************************************************/
/* Headers from system goes first */
#include <algorithm>
#include <chrono>
#include <ctime>
#include <regex>
#include <string>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "command_exit_codes.h"
#include "openfpga_digest.h"
#include "openfpga_side_manager.h"
/* Headers from arch openfpga library */
#include "fabric_pin_physical_location_xml_constants.h"
#include "write_xml_fabric_pin_physical_location.h"
#include "write_xml_utils.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This function write header information to a pin location file
*******************************************************************/
static void write_xml_fabric_pin_physical_location_file_head(
std::fstream& fp, const bool& include_time_stamp) {
valid_file_stream(fp);
fp << "<!--" << std::endl;
fp << "\t- Fabric Pin Physical Location" << std::endl;
fp << "\t- Author: Xifan TANG" << std::endl;
fp << "\t- Organization: RapidFlex" << std::endl;
if (include_time_stamp) {
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
fp << "\t- Date: " << std::ctime(&end_time);
}
fp << "-->" << std::endl;
fp << std::endl;
}
/********************************************************************
* This function write header information to a pin location file
*******************************************************************/
static int write_xml_fabric_module_pin_phy_loc(
std::fstream& fp, const ModuleManager& module_manager,
const ModuleId& curr_module, const bool& show_invalid_side,
const bool& verbose) {
valid_file_stream(fp);
/* If show invalid side is off, we should check if there is any valid side. If
* there are not any, skip this module */
bool skip_curr_module = true;
for (ModulePortId curr_port_id : module_manager.module_ports(curr_module)) {
SideManager side_mgr(module_manager.port_side(curr_module, curr_port_id));
if (side_mgr.validate()) {
skip_curr_module = false;
break;
}
}
if (!show_invalid_side && skip_curr_module) {
VTR_LOGV(verbose, "Skip module '%s' as it contains no valid sides\n",
module_manager.module_name(curr_module).c_str());
return CMD_EXEC_SUCCESS;
}
/* Print a head */
write_tab_to_file(fp, 1);
fp << "<" << XML_MODULE_NODE_NAME;
write_xml_attribute(fp, XML_MODULE_ATTRIBUTE_NAME,
module_manager.module_name(curr_module).c_str());
fp << ">"
<< "\n";
size_t cnt = 0;
for (ModulePortId curr_port_id : module_manager.module_ports(curr_module)) {
BasicPort curr_port = module_manager.module_port(curr_module, curr_port_id);
SideManager side_mgr(module_manager.port_side(curr_module, curr_port_id));
if (!side_mgr.validate() && !show_invalid_side) {
continue;
}
for (int curr_pin_id : curr_port.pins()) {
BasicPort curr_pin(curr_port.get_name(), curr_pin_id, curr_pin_id);
std::string curr_port_str = generate_xml_port_name(curr_pin);
write_tab_to_file(fp, 2);
fp << "<" << XML_MODULE_PINLOC_NODE_NAME;
write_xml_attribute(fp, XML_MODULE_PINLOC_ATTRIBUTE_PIN,
curr_port_str.c_str());
write_xml_attribute(fp, XML_MODULE_PINLOC_ATTRIBUTE_SIDE,
side_mgr.c_str());
fp << "/>";
fp << std::endl;
}
cnt++;
}
VTR_LOGV(verbose, "Output %lu ports with physical sides for module '%s'\n",
cnt, module_manager.module_name(curr_module).c_str());
/* Print a tail */
write_tab_to_file(fp, 1);
fp << "</" << XML_MODULE_NODE_NAME;
fp << ">"
<< "\n";
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* Top-level function
*******************************************************************/
int write_xml_fabric_pin_physical_location(const char* fname,
const std::string& module_name,
const ModuleManager& module_manager,
const bool& show_invalid_side,
const bool& include_time_stamp,
const bool& verbose) {
vtr::ScopedStartFinishTimer timer("Write fabric pin physical location");
/* 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_xml_fabric_pin_physical_location_file_head(fp, include_time_stamp);
/* Write the root node */
fp << "<" << XML_PINLOC_ROOT_NAME;
fp << ">"
<< "\n";
/* If module name is not specified, walk through all the modules and write
* physical pin location when any is specified */
short cnt = 0;
/* Use regular expression to capture the module whose name matches the pattern
*/
for (ModuleId curr_module : module_manager.modules()) {
std::string curr_module_name = module_manager.module_name(curr_module);
std::string pattern = module_name;
std::regex star_replace("\\*");
std::regex questionmark_replace("\\?");
std::string wildcard_pattern =
std::regex_replace(std::regex_replace(pattern, star_replace, ".*"),
questionmark_replace, ".");
std::regex wildcard_regex(wildcard_pattern);
if (!std::regex_match(curr_module_name, wildcard_regex)) {
continue;
}
VTR_LOGV(verbose, "Outputted pin physical location of module '%s'.\n",
curr_module_name.c_str());
/* Write the pin physical location for this module */
int err_code = write_xml_fabric_module_pin_phy_loc(
fp, module_manager, curr_module, show_invalid_side, verbose);
if (err_code != CMD_EXEC_SUCCESS) {
return CMD_EXEC_FATAL_ERROR;
}
cnt++;
}
/* Finish writing the root node */
fp << "</" << XML_PINLOC_ROOT_NAME << ">"
<< "\n";
/* Close the file stream */
fp.close();
/* If there is no match, error out! */
if (cnt == 0) {
VTR_LOG_ERROR(
"Invalid regular expression for module name '%s' which does not match "
"any in current fabric!\n",
module_name.c_str());
return CMD_EXEC_FATAL_ERROR;
}
VTR_LOGV(verbose, "Outputted %lu modules with pin physical location.\n", cnt);
return CMD_EXEC_SUCCESS;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,27 @@
#ifndef WRITE_XML_FABRIC_PIN_PHYSICAL_LOCATION_H
#define WRITE_XML_FABRIC_PIN_PHYSICAL_LOCATION_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "module_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
int write_xml_fabric_pin_physical_location(const char* fname,
const std::string& module_name,
const ModuleManager& module_manager,
const bool& show_invalid_side,
const bool& include_time_stamp,
const bool& verbose);
} /* end namespace openfpga */
#endif

View File

@ -30,6 +30,7 @@
#ifndef FABRIC_BITSTREAM_H
#define FABRIC_BITSTREAM_H
#include <cstdint>
#include <unordered_map>
#include <unordered_set>
#include <vector>

View File

@ -317,8 +317,9 @@ static void print_pnr_sdc_constrain_cb_mux_timing(
/* Find the module port corresponding to the fan-in rr_nodes of the output
* rr_node */
std::vector<ModulePinInfo> module_input_ports =
find_connection_block_module_input_ports(
module_manager, cb_module, rr_graph, rr_gsb, cb_type, input_rr_nodes);
find_connection_block_module_input_ports(module_manager, cb_module, grids,
device_annotation, rr_graph,
rr_gsb, cb_type, input_rr_nodes);
/* Find timing constraints for each path (edge) */
std::map<ModulePinInfo, float> switch_delays;

View File

@ -61,6 +61,11 @@ constexpr const char* FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME =
constexpr const char* FORMAL_RANDOM_TOP_TESTBENCH_POSTFIX =
"_top_formal_verification_random_tb";
constexpr const char* VERILOG_FSDB_PREPROC_FLAG =
"DUMP_FSDB"; // the flag to enable fsdb waveform output during compilation
constexpr const char* VERILOG_VCD_PREPROC_FLAG =
"DUMP_VCD"; // the flag to enable vcd waveform output during compilation
#define VERILOG_DEFAULT_SIGNAL_INIT_VALUE 0
#endif

View File

@ -490,6 +490,12 @@ int print_verilog_preconfig_top_module(
module_manager, top_module, false);
}
/* Add waveform output command, support both fsdb and vcd */
if (true == options.dump_waveform()) {
print_verilog_testbench_dump_waveform(
fp, circuit_name, std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME));
}
/* Testbench ends*/
print_verilog_module_end(
fp,

View File

@ -31,6 +31,7 @@ VerilogTestbenchOption::VerilogTestbenchOption() {
time_stamp_ = true;
use_relative_path_ = false;
simulator_type_ = e_simulator_type::IVERILOG;
dump_waveform_ = false;
verbose_output_ = false;
SIMULATOR_TYPE_STRING_ = {{"iverilog", "vcs"}};
@ -87,6 +88,8 @@ bool VerilogTestbenchOption::include_signal_init() const {
return include_signal_init_;
}
bool VerilogTestbenchOption::dump_waveform() const { return dump_waveform_; }
bool VerilogTestbenchOption::no_self_checking() const {
return reference_benchmark_file_path_.empty();
}
@ -206,6 +209,10 @@ void VerilogTestbenchOption::set_include_signal_init(const bool& enabled) {
include_signal_init_ = enabled;
}
void VerilogTestbenchOption::set_dump_waveform(const bool& enabled) {
dump_waveform_ = enabled;
}
void VerilogTestbenchOption::set_default_net_type(
const std::string& default_net_type) {
/* Decode from net type string */;

View File

@ -59,6 +59,7 @@ class VerilogTestbenchOption {
std::string simulation_ini_path() const;
bool explicit_port_mapping() const;
bool include_signal_init() const;
bool dump_waveform() const;
bool no_self_checking() const;
e_verilog_default_net_type default_net_type() const;
e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type() const;
@ -98,6 +99,7 @@ class VerilogTestbenchOption {
void set_print_simulation_ini(const std::string& simulation_ini_path);
void set_explicit_port_mapping(const bool& enabled);
void set_include_signal_init(const bool& enabled);
void set_dump_waveform(const bool& enabled);
void set_default_net_type(const std::string& default_net_type);
void set_time_unit(const float& time_unit);
void set_embedded_bitstream_hdl_type(
@ -132,6 +134,7 @@ class VerilogTestbenchOption {
std::string simulation_ini_path_;
bool explicit_port_mapping_;
bool include_signal_init_;
bool dump_waveform_;
e_verilog_default_net_type default_net_type_;
e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type_;
e_simulator_type simulator_type_;

View File

@ -1344,4 +1344,34 @@ void print_verilog_testbench_signal_initialization(
}
}
/********************************************************************
* Print waveform output commands: support both VCD and FSDB
*******************************************************************/
void print_verilog_testbench_dump_waveform(std::fstream& fp,
const std::string& circuit_name,
const std::string& uut_name) {
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_comment(
fp, std::string("------ Use " + std::string(VERILOG_FSDB_PREPROC_FLAG) +
" to enable FSDB waveform output -----"));
print_verilog_preprocessing_flag(fp, std::string(VERILOG_FSDB_PREPROC_FLAG));
fp << "initial begin\n";
fp << "\t$fsdbDumpfile(\"" << circuit_name << ".fsdb\");\n";
fp << "\t$fsdbDumpvars(0, \"" << uut_name << "\");\n";
fp << "end\n";
print_verilog_endif(fp);
print_verilog_comment(
fp, std::string("------ Use " + std::string(VERILOG_VCD_PREPROC_FLAG) +
" to enable VCD waveform output -----"));
print_verilog_preprocessing_flag(fp, std::string(VERILOG_VCD_PREPROC_FLAG));
fp << "initial begin\n";
fp << "\t$dumpfile(\"" << circuit_name << ".vcd\");\n";
fp << "\t$dumpvars(0, \"" << uut_name << "\");\n";
fp << "end\n";
print_verilog_endif(fp);
}
} /* end namespace openfpga */

View File

@ -135,6 +135,10 @@ void print_verilog_testbench_signal_initialization(
const CircuitLibrary& circuit_lib, const ModuleManager& module_manager,
const ModuleId& top_module, const bool& deposit_random_values);
void print_verilog_testbench_dump_waveform(std::fstream& fp,
const std::string& circuit_name,
const std::string& uut_name);
} /* end namespace openfpga */
#endif

View File

@ -138,8 +138,13 @@ static void build_physical_pb_lut_truth_tables(
size_t(lut_pb_id), output_pin->to_string().c_str());
VTR_LOGV(verbose, "Input nets:\n");
for (auto input_net : input_nets) {
VTR_LOGV(verbose, "\t%s\n",
atom_ctx.nlist.net_name(input_net).c_str());
if (AtomNetId::INVALID() == input_net) {
VTR_LOGV(verbose, "\tunconn\n");
} else {
VTR_ASSERT(AtomNetId::INVALID() != input_net);
VTR_LOGV(verbose, "\t%s\n",
atom_ctx.nlist.net_name(input_net).c_str());
}
}
VTR_LOGV(verbose, "Output nets:\n");
VTR_LOGV(verbose, "\t%s\n",
@ -236,6 +241,10 @@ void build_physical_lut_truth_tables(
for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
PhysicalPb& physical_pb = cluster_annotation.mutable_physical_pb(blk_id);
VTR_LOGV(
verbose,
"Build truth tables for physical LUTs under clustered block '%s'...\n",
cluster_ctx.clb_nlist.block_name(blk_id).c_str());
/* Find the LUT physical pb id */
for (const PhysicalPbId& primitive_pb : physical_pb.primitive_pbs()) {
CircuitModelId circuit_model = device_annotation.pb_type_circuit_model(

View File

@ -92,10 +92,9 @@ void save_lb_router_results_to_physical_pb(PhysicalPb& phy_pb,
const AtomNetId& atom_net = lb_router.net_atom_net_id(net);
/* Print info to help debug */
VTR_LOGV(verbose, "Save net '%s' to physical pb_graph_pin '%s.%s[%d]'\n",
VTR_LOGV(verbose, "Save net '%s' to physical pb_graph_pin '%s'\n",
atom_netlist.net_name(atom_net).c_str(),
pb_graph_pin->parent_node->pb_type->name,
pb_graph_pin->port->name, pb_graph_pin->pin_number);
pb_graph_pin->to_string().c_str());
if (AtomNetId::INVALID() ==
phy_pb.pb_graph_pin_atom_net(pb_id, pb_graph_pin)) {

View File

@ -304,6 +304,33 @@ static std::vector<int> find_pb_route_by_atom_net(
return pb_route_indices;
}
/***************************************************************************************
* This function will find the actual routing traces of the demanded net
* There is a specific search space applied when searching the routing traces:
* - ONLY applicable to the pb_pin of top-level pb_graph_node
***************************************************************************************/
static std::vector<int> find_pb_routes_by_atom_net_among_top_pb_pins(
const t_pb* pb, const AtomNetId& atom_net_id) {
std::vector<int> pb_route_indices;
std::vector<int> candidate_pool;
for (int pin = 0; pin < pb->pb_graph_node->total_pb_pins; ++pin) {
/* Bypass unused pins */
if ((0 == pb->pb_route.count(pin)) ||
(AtomNetId::INVALID() == pb->pb_route.at(pin).atom_net_id)) {
continue;
}
/* Get the driver pb pin id, it must be valid */
if (atom_net_id != pb->pb_route.at(pin).atom_net_id) {
continue;
}
if (pb->pb_route.at(pin).pb_graph_pin->parent_node->is_root()) {
candidate_pool.push_back(pin);
}
}
return candidate_pool;
}
/***************************************************************************************
* This function will find the actual routing traces of the demanded net
* There is a specific search space applied when searching the routing traces:
@ -584,7 +611,6 @@ static void add_lb_router_nets(
std::string(lb_type->pb_type->name), curr_pin))) {
/* Find the net mapped to this pin in clustering results*/
AtomNetId atom_net_id = pb_pin_mapped_nets[source_pb_pin];
std::vector<int> pb_route_indices =
find_pb_route_by_atom_net(pb, source_pb_pin, atom_net_id);
VTR_ASSERT(1 == pb_route_indices.size());
@ -640,9 +666,15 @@ static void add_lb_router_nets(
BasicPort curr_pin(std::string(source_pb_pin->port->name),
source_pb_pin->pin_number, source_pb_pin->pin_number);
/* Be very careful! There is only one routing trace for the net, it should
* never be ignored! */
if ((ignored_atom_nets[atom_net_id]) &&
(find_pb_routes_by_atom_net_among_top_pb_pins(pb, atom_net_id).size() >
1) &&
(options.is_pin_ignore_global_nets(std::string(lb_type->pb_type->name),
curr_pin))) {
VTR_LOGV(verbose, "Skip net '%s' as it is global and set to be ignored\n",
atom_ctx.nlist.net_name(atom_net_id).c_str());
continue;
}

View File

@ -197,7 +197,7 @@ static vtr::Point<size_t> find_inter_direct_destination_coordinate(
* Our search space will start from the next column
* and ends at the RIGHT side of fabric
*/
if (INTER_COLUMN == arch_direct.type(arch_direct_id)) {
if (e_direct_type::INTER_COLUMN == arch_direct.type(arch_direct_id)) {
if (POSITIVE_DIR == arch_direct.x_dir(arch_direct_id)) {
/* Our first search space will be in x-direction:
*
@ -262,7 +262,7 @@ static vtr::Point<size_t> find_inter_direct_destination_coordinate(
* Our search space will start from the next column
* and ends at the RIGHT side of fabric
*/
if (INTER_ROW == arch_direct.type(arch_direct_id)) {
if (e_direct_type::INTER_ROW == arch_direct.type(arch_direct_id)) {
if (POSITIVE_DIR == arch_direct.y_dir(arch_direct_id)) {
/* Our first search space will be in y-direction:
*
@ -326,10 +326,11 @@ static vtr::Point<size_t> find_inter_direct_destination_coordinate(
for (size_t ix : first_search_space) {
std::vector<vtr::Point<size_t>> next_col_row_coords;
for (size_t iy : second_search_space) {
if (INTER_COLUMN == arch_direct.type(arch_direct_id)) {
if (e_direct_type::INTER_COLUMN == arch_direct.type(arch_direct_id)) {
next_col_row_coords.push_back(vtr::Point<size_t>(ix, iy));
} else {
VTR_ASSERT(INTER_ROW == arch_direct.type(arch_direct_id));
VTR_ASSERT(e_direct_type::INTER_ROW ==
arch_direct.type(arch_direct_id));
/* For cross-row connection, our search space is flipped */
next_col_row_coords.push_back(vtr::Point<size_t>(iy, ix));
}
@ -549,8 +550,8 @@ static void build_inter_column_row_tile_direct(
/* Go through the direct connection list, see if we need intra-column/row
* connection here */
if ((INTER_COLUMN != arch_direct.type(arch_direct_id)) &&
(INTER_ROW != arch_direct.type(arch_direct_id))) {
if ((e_direct_type::INTER_COLUMN != arch_direct.type(arch_direct_id)) &&
(e_direct_type::INTER_ROW != arch_direct.type(arch_direct_id))) {
return;
}
/* For cross-column connection, we will search the first valid grid in each
@ -568,7 +569,7 @@ static void build_inter_column_row_tile_direct(
* +------+
*
*/
if (INTER_COLUMN == arch_direct.type(arch_direct_id)) {
if (e_direct_type::INTER_COLUMN == arch_direct.type(arch_direct_id)) {
for (size_t ix = 1; ix < device_ctx.grid.width() - 1; ++ix) {
std::vector<vtr::Point<size_t>> next_col_src_grid_coords;
/* For negative y- direction, we should start from y = ny */
@ -671,7 +672,7 @@ static void build_inter_column_row_tile_direct(
}
/* Reach here, it must be a cross-row connection */
VTR_ASSERT(INTER_ROW == arch_direct.type(arch_direct_id));
VTR_ASSERT(e_direct_type::INTER_ROW == arch_direct.type(arch_direct_id));
/* For cross-row connection, we will search the first valid grid in each
* column from x = 1 to x = nx
*
@ -804,9 +805,14 @@ TileDirect build_device_tile_direct(const DeviceContext& device_ctx,
exit(1);
}
/* Build from original VPR arch definition */
build_inner_column_row_tile_direct(tile_direct,
device_ctx.arch->Directs[idirect],
device_ctx, arch_direct_id, verbose);
if (e_direct_type::INNER_COLUMN_OR_ROW ==
arch_direct.type(arch_direct_id)) {
build_inner_column_row_tile_direct(tile_direct,
device_ctx.arch->Directs[idirect],
device_ctx, arch_direct_id, verbose);
/* Skip those direct connections which belong part of a connection block
*/
}
/* Build from OpenFPGA arch definition */
build_inter_column_row_tile_direct(
tile_direct, device_ctx.arch->Directs[idirect], device_ctx, arch_direct,

View File

@ -77,7 +77,7 @@ size_t find_mux_local_decoder_addr_size(const size_t& data_size) {
***************************************************************************************/
size_t find_memory_decoder_addr_size(const size_t& num_mems) {
return find_mux_local_decoder_addr_size(
find_memory_decoder_data_size(num_mems));
find_memory_decoder_data_size(num_mems, 0, false));
}
/***************************************************************************************
@ -86,8 +86,18 @@ size_t find_memory_decoder_addr_size(const size_t& num_mems) {
*lines and word lines, the number of data lines will be a square root of the
*number of memory cells.
***************************************************************************************/
size_t find_memory_decoder_data_size(const size_t& num_mems) {
return (size_t)std::ceil(std::sqrt((float)num_mems));
size_t find_memory_decoder_data_size(const size_t& num_mems,
const size_t& defined_num_wl,
const bool is_bl) {
if (defined_num_wl == 0) {
return (size_t)std::ceil(std::sqrt((float)num_mems));
} else {
if (is_bl) {
return find_memory_wl_decoder_data_size(num_mems, defined_num_wl);
} else {
return defined_num_wl;
}
}
}
/***************************************************************************************

View File

@ -15,7 +15,9 @@ size_t find_mux_local_decoder_addr_size(const size_t& data_size);
size_t find_memory_decoder_addr_size(const size_t& num_mems);
size_t find_memory_decoder_data_size(const size_t& num_mems);
size_t find_memory_decoder_data_size(const size_t& num_mems,
const size_t& defined_num_wl,
const bool is_bl);
size_t find_memory_wl_decoder_data_size(const size_t& num_mems,
const size_t& num_bls);

View File

@ -436,7 +436,8 @@ size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type,
* - QL Memory decoders: Apply square root as BL/WLs will be grouped
********************************************************************/
size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type,
const size_t& num_config_bits) {
const size_t& num_config_bits,
const size_t& defined_num_wl) {
size_t sram_port_size = num_config_bits;
switch (sram_orgz_type) {
@ -447,7 +448,8 @@ size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type,
sram_port_size = 1;
break;
case CONFIG_MEM_QL_MEMORY_BANK:
sram_port_size = find_memory_decoder_data_size(num_config_bits);
sram_port_size =
find_memory_decoder_data_size(num_config_bits, defined_num_wl, true);
break;
case CONFIG_MEM_MEMORY_BANK:
break;

View File

@ -42,7 +42,8 @@ size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type,
const size_t& num_config_bits);
size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type,
const size_t& num_config_bits);
const size_t& num_config_bits,
const size_t& defined_num_wl);
/**
* @brief Compute the number of configurable children to be skipped for a given

View File

@ -419,11 +419,16 @@ void add_sram_ports_to_module_manager(
void add_pb_sram_ports_to_module_manager(
ModuleManager& module_manager, const ModuleId& module_id,
const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model,
const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits) {
const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits,
const uint32_t defined_num_wl) {
if (defined_num_wl) {
// Only support defined_num_wl if the configuration mode is QL Memory Bank
VTR_ASSERT(sram_orgz_type == CONFIG_MEM_QL_MEMORY_BANK);
}
std::vector<std::string> sram_port_names =
generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type);
size_t sram_port_size =
generate_pb_sram_port_size(sram_orgz_type, num_config_bits);
generate_pb_sram_port_size(sram_orgz_type, num_config_bits, defined_num_wl);
/* Add ports to the module manager */
switch (sram_orgz_type) {

Some files were not shown because too many files have changed in this diff Show More