Merge remote-tracking branch 'lnis_origin/master' into ganesh_dev

This commit is contained in:
ganeshgore 2020-11-25 17:29:53 -07:00
commit fefba0db59
447 changed files with 17772 additions and 15033 deletions

107
.github/workflows/basic_reg_test.sh vendored Executable file
View File

@ -0,0 +1,107 @@
#!/bin/bash
set -e
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "Basic regression tests";
echo -e "Testing configuration chain of a K4N4 FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain_use_reset --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain_use_resetb --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain_use_set --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain_use_setb --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain_use_set_reset --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/multi_region_configuration_chain --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_configuration_chain --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_configuration_chain_use_set --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/smart_fast_configuration_chain --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/smart_fast_multi_region_configuration_chain --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/preconfig_testbench/configuration_chain --debug --show_thread_logs
echo -e "Testing fram-based configuration protocol of a K4N4 FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_frame --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/smart_fast_configuration_frame --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_configuration_frame --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_configuration_frame_use_set --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_frame_ccff --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_frame_scff --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_frame_use_reset --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_frame_use_resetb --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_frame_use_set --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_frame_use_setb --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_frame_use_set_reset --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/multi_region_configuration_frame --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/smart_fast_multi_region_configuration_frame --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/preconfig_testbench/configuration_frame --debug --show_thread_logs
echo -e "Testing memory bank configuration protocol of a K4N4 FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/memory_bank --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/memory_bank_use_reset --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/memory_bank_use_resetb --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/memory_bank_use_set --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/memory_bank_use_setb --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/memory_bank_use_set_reset --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/multi_region_memory_bank --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_memory_bank --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_memory_bank_use_set --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/smart_fast_memory_bank --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/smart_fast_multi_region_memory_bank --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/preconfig_testbench/memory_bank --debug --show_thread_logs
echo -e "Testing standalone (flatten memory) configuration protocol of a K4N4 FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/flatten_memory --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/preconfig_testbench/flatten_memory --debug --show_thread_logs
echo -e "Testing fixed device layout and routing channel width";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/fixed_device_support --debug --show_thread_logs
echo -e "Testing fabric Verilog generation only";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/generate_fabric --debug --show_thread_logs
echo -e "Testing Verilog testbench generation only";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/generate_testbench --debug --show_thread_logs
echo -e "Testing separated Verilog fabric netlists and testbench locations";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/custom_fabric_netlist_location --debug --show_thread_logs
echo -e "Testing user-defined simulation settings: clock frequency and number of cycles";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/fixed_simulation_settings --debug --show_thread_logs
echo -e "Testing Secured FPGA fabrics";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/fabric_key/generate_vanilla_key --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/fabric_key/generate_multi_region_vanilla_key --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/fabric_key/generate_random_key --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/fabric_key/load_external_key --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/fabric_key/load_external_key_cc_fpga --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/fabric_key/load_external_key_multi_region_cc_fpga --debug --show_thread_logs
echo -e "Testing K4 series FPGA";
echo -e "Testing K4N4 with facturable LUTs";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_frac_lut --debug --show_thread_logs
echo -e "Testing K4N4 with hard adders";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_adder --debug --show_thread_logs
echo -e "Testing K4N4 without local routing architecture";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_no_local_routing --debug --show_thread_logs
echo -e "Testing K4N4 with block RAM";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_bram --debug --show_thread_logs
echo -e "Testing K4N4 with multiple lengths of routing segments";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_L124 --debug --show_thread_logs
echo -e "Testing K4N4 with 32-bit fracturable multiplier";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_frac_mult --debug --show_thread_logs
echo -e "Testing K4N5 with pattern based local routing";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n5_pattern_local_routing --debug --show_thread_logs
echo -e "Testing different tile organizations";
echo -e "Testing tiles with pins only on top and left sides";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/tile_organization/top_left_custom_pins --debug --show_thread_logs
echo -e "Testing tiles with pins only on top and right sides";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/tile_organization/top_right_custom_pins --debug --show_thread_logs
echo -e "Testing tiles with pins only on bottom and right sides";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/tile_organization/bottom_right_custom_pins --debug --show_thread_logs
echo -e "Testing global port definition from tiles";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/global_tile_ports/global_tile_clock --debug --show_thread_logs

201
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,201 @@
name: linux_build
# Run CI on
# - each push
# - each pull request
# - scheduled weekly
on:
push:
pull_request:
schedule:
- cron: '0 0 * * 0 ' # weekly
# Environment variables
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
MAKEFLAGS: "-j8"
# Multiple job to tests
jobs:
# Test the compilation compatibility
linux_build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
# Branch on different OS and settings
strategy:
fail-fast: false
matrix:
config:
- {
name: "Build Compatibility: GCC-5 (Ubuntu 18.04)",
artifact: "OpenFPGA-ubuntu-18.04-gcc5-build.7z",
os: ubuntu-18.04,
cc: "gcc-5", cxx: "g++-5"
}
- {
name: "Build Compatibility: GCC-6 (Ubuntu 18.04)",
artifact: "OpenFPGA-ubuntu-18.04-gcc6-build.7z",
os: ubuntu-18.04,
cc: "gcc-6", cxx: "g++-6"
}
- {
name: "Build Compatibility: GCC-7 (Ubuntu 18.04)",
artifact: "OpenFPGA-ubuntu-18.04-gcc7-build.7z",
os: ubuntu-18.04,
cc: "gcc-7", cxx: "g++-7"
}
- {
name: "Build Compatibility: GCC-8 (Ubuntu 18.04)",
artifact: "OpenFPGA-ubuntu-18.04-gcc8-build.7z",
os: ubuntu-18.04,
cc: "gcc-8", cxx: "g++-8"
}
- {
name: "Build Compatibility: GCC-9 (Ubuntu 18.04)",
artifact: "OpenFPGA-ubuntu-18.04-gcc9-build.7z",
os: ubuntu-18.04,
cc: "gcc-9", cxx: "g++-9"
}
- {
name: "Build Compatibility: Clang-6 (Ubuntu 18.04)",
artifact: "OpenFPGA-ubuntu-18.04-clang6-build.7z",
os: ubuntu-18.04,
cc: "clang-6.0", cxx: "clang++-6.0"
}
- {
name: "Build Compatibility: Clang-8 (Ubuntu 18.04)",
artifact: "OpenFPGA-ubuntu-18.04-clang8-build.7z",
os: ubuntu-18.04,
cc: "clang-8", cxx: "clang++-8"
}
- {
name: "Basic Regression Tests: GCC-8 (Ubuntu 18.04)",
artifact: "OpenFPGA-basic-tests-ubuntu-18.04-gcc8-build.7z",
os: ubuntu-18.04,
cc: "gcc-8", cxx: "g++-8",
reg_script: "basic_reg_test.sh"
}
- {
name: "FPGA-Verilog Regression Tests: GCC-8 (Ubuntu 18.04)",
artifact: "OpenFPGA-fpga-verilog-tests-ubuntu-18.04-gcc8-build.7z",
os: ubuntu-18.04,
cc: "gcc-8", cxx: "g++-8",
reg_script: "fpga_verilog_reg_test.sh"
}
- {
name: "FPGA-Bitstream Regression Tests: GCC-8 (Ubuntu 18.04)",
artifact: "OpenFPGA-fpga-bitstream-tests-ubuntu-18.04-gcc8-build.7z",
os: ubuntu-18.04,
cc: "gcc-8", cxx: "g++-8",
reg_script: "fpga_bitstream_reg_test.sh"
}
- {
name: "FPGA-SDC Regression Tests: GCC-8 (Ubuntu 18.04)",
artifact: "OpenFPGA-fpga-sdc-tests-ubuntu-18.04-gcc8-build.7z",
os: ubuntu-18.04,
cc: "gcc-8", cxx: "g++-8",
reg_script: "fpga_sdc_reg_test.sh"
}
- {
name: "FPGA-SPICE Regression Tests: GCC-8 (Ubuntu 18.04)",
artifact: "OpenFPGA-fpga-spice-tests-ubuntu-18.04-gcc8-build.7z",
os: ubuntu-18.04,
cc: "gcc-8", cxx: "g++-8",
reg_script: "fpga_spice_reg_test.sh"
}
# Define the steps to run the build job
steps:
- name: Checkout OpenFPGA repo
uses: actions/checkout@v2
- name: Install dependency
run: source ./.github/workflows/install_dependency.sh
- name: Checkout CMake version
run: cmake --version
- name: Checkout iVerilog version
run: |
iverilog -V
vvp -V
- name: Prepare ccache timestamp
id: ccache_cache_timestamp
shell: cmake -P {0}
run: |
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
message("::set-output name=timestamp::${current_date}")
- name: Create CMake build environment
# Some projects don't allow in-source building, so create a separate build directory
# We'll use this as our working directory for all subsequent commands
run: cmake -E make_directory ${{runner.workspace}}/build
- name: ccache cache files
uses: actions/cache@v2
with:
path: ${{runner.workspace}}/.ccache
key: ${{ matrix.config.name }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }}
restore-keys: |
${{ matrix.config.name }}-ccache-
# Set up the paths for ccache and control the size under 400MB
- name: Configure ccache
shell: cmake -P {0}
run: |
file(TO_CMAKE_PATH ${{runner.workspace}} ccache_basedir)
set(ENV{CCACHE_BASEDIR} "${ccache_basedir}")
set(ENV{CCACHE_DIR} "${ccache_basedir}/.ccache")
set(ENV{CCACHE_COMPRESS} "true")
set(ENV{CCACHE_COMPRESSLEVEL} "6")
set(ENV{CCACHE_MAXSIZE} "400M")
execute_process(COMMAND ccache -p)
execute_process(COMMAND ccache -z)
- name: Configure CMake
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash
working-directory: ${{runner.workspace}}/build
# Note the current convention is to use the -S and -B options here to specify source
# and build directories, but this is only available with CMake 3.13 and higher.
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
run: |
export CC=${{ matrix.config.cc }}
export CXX=${{ matrix.config.cxx }}
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash
# Execute the build. You can specify a specific target with "--target <NAME>"
run: |
cmake --build . --config $BUILD_TYPE
# Check the cache size and see if it is over the limit
- name: Check ccache size
shell: cmake -P {0}
run: |
execute_process(COMMAND ccache -s)
- name: ${{matrix.config.name}}
if: contains(matrix.config.name, 'Regression Test')
shell: bash
# Execute the test.
run: source ./.github/workflows/${{matrix.config.reg_script}}

21
.github/workflows/fpga_bitstream_reg_test.sh vendored Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash
set -e
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "FPGA-Bitstream regression tests";
echo -e "Testing bitstream generation for an auto-sized device";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_bitstream/generate_bitstream/device_auto --debug --show_thread_logs
echo -e "Testing bitstream generation for an 48x48 FPGA device";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_bitstream/generate_bitstream/device_48x48 --debug --show_thread_logs
echo -e "Testing bitstream generation for an 96x96 FPGA device";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_bitstream/generate_bitstream/device_96x96 --debug --show_thread_logs
echo -e "Testing loading architecture bitstream from an external file";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_bitstream/load_external_architecture_bitstream --debug --show_thread_logs

11
.github/workflows/fpga_sdc_reg_test.sh vendored Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
set -e
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "FPGA-SDC regression tests";
echo -e "Testing SDC generation with time units";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_sdc/sdc_time_unit --debug --show_thread_logs

11
.github/workflows/fpga_spice_reg_test.sh vendored Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
set -e
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "FPGA-SPICE regression tests";
echo -e "Testing FPGA-SPICE with netlist generation";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_spice/generate_spice --debug --show_thread_logs

115
.github/workflows/fpga_verilog_reg_test.sh vendored Executable file
View File

@ -0,0 +1,115 @@
#!/bin/bash
set -e
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "FPGA-Verilog Feature Tests";
echo -e "Testing Verilog generation for LUTs: a single mode LUT6 FPGA using micro benchmarks";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/lut_design/single_mode --debug --show_thread_logs
echo -e "Testing Verilog generation for LUTs: simple fracturable LUT4 ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/lut_design/frac_lut4 --debug --show_thread_logs
echo -e "Testing Verilog generation for LUTs: simple fracturable LUT4 using AND gate to switch modes";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/lut_design/frac_lut4_and_switch --debug --show_thread_logs
echo -e "Testing Verilog generation for LUTs: simple fracturable LUT6 ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/lut_design/frac_lut6 --debug --show_thread_logs
echo -e "Testing Verilog generation for LUTs: LUT6 with intermediate buffers";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/lut_design/intermediate_buffer --debug --show_thread_logs
echo -e "Testing Verilog generation with VPR's untileable routing architecture ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/untileable --debug --show_thread_logs
echo -e "Testing Verilog generation with hard adder chain in CLBs ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/hard_adder --debug --show_thread_logs
echo -e "Testing Verilog generation with 16k block RAMs ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/bram/dpram16k --debug --show_thread_logs
echo -e "Testing Verilog generation with 16k block RAMs spanning two columns ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/bram/wide_dpram16k --debug --show_thread_logs
echo -e "Testing Verilog generation with different I/O capacities on each side of an FPGA ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/io/multi_io_capacity --debug --show_thread_logs
echo -e "Testing Verilog generation with I/Os only on left and right sides of an FPGA ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/io/reduced_io --debug --show_thread_logs
echo -e "Testing Verilog generation with embedded I/Os for an FPGA ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/io/embedded_io --debug --show_thread_logs
echo -e "Testing Verilog generation with SoC I/Os for an FPGA ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/io/soc_io --debug --show_thread_logs
echo -e "Testing Verilog generation with adder chain across an FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_chain/adder_chain --debug --show_thread_logs
echo -e "Testing Verilog generation with shift register chain across an FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_chain/register_chain --debug --show_thread_logs
echo -e "Testing Verilog generation with scan chain across an FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_chain/scan_chain --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers implemented by tree structure";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/tree_structure --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers implemented by standard cell MUX2";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/stdcell_mux2 --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers implemented by local encoders";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/local_encoder --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers without buffers";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/debuf_mux --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers with input buffers only";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/inbuf_only_mux --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers with output buffers only";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/outbuf_only_mux --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers with constant gnd input";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/const_input_gnd --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers without constant inputs";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/no_const_input --debug --show_thread_logs
echo -e "Testing Verilog generation with behavioral description";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/behavioral_verilog --debug --show_thread_logs
echo -e "Testing implicit Verilog generation";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/implicit_verilog --debug --show_thread_logs
echo -e "Testing Verilog generation with flatten routing modules";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/flatten_routing --debug --show_thread_logs
echo -e "Testing Verilog generation with duplicated grid output pins";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/duplicated_grid_pin --debug --show_thread_logs
echo -e "Testing Verilog generation with spy output pads";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/spypad --debug --show_thread_logs
echo -e "Testing Power-gating designs";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/power_gated_design/power_gated_inverter --show_thread_logs --debug
echo -e "Testing Depopulated crossbar in local routing";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/depopulate_crossbar --debug --show_thread_logs
echo -e "Testing Fully connected output crossbar in local routing";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fully_connected_output_crossbar --debug --show_thread_logs
echo -e "Testing through channels in tileable routing";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/thru_channel/thru_narrow_tile --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/thru_channel/thru_wide_tile --debug --show_thread_logs
# Verify MCNC big20 benchmark suite with ModelSim
# Please make sure you have ModelSim installed in the environment
# Otherwise, it will fail
#python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mcnc_big20 --debug --show_thread_logs --maxthreads 20
#python3 openfpga_flow/scripts/run_modelsim.py mcnc_big20 --run_sim

48
.github/workflows/install_dependency.sh vendored Normal file
View File

@ -0,0 +1,48 @@
# Install all the dependency for OpenFPGA in Ubuntu-18.04
sudo apt-get update
sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install bash
sudo apt-get install bison
sudo apt-get install build-essential
sudo apt-get install cmake
sudo apt-get install ccache
sudo apt-get install ctags
sudo apt-get install curl
sudo apt-get install doxygen
sudo apt-get install flex
sudo apt-get install fontconfig
sudo apt-get install gdb
sudo apt-get install git
sudo apt-get install gperf
sudo apt-get install iverilog
sudo apt-get install libcairo2-dev
sudo apt-get install libevent-dev
sudo apt-get install libfontconfig1-dev
sudo apt-get install liblist-moreutils-perl
sudo apt-get install libncurses5-dev
sudo apt-get install libx11-dev
sudo apt-get install libxft-dev
sudo apt-get install libxml++2.6-dev
sudo apt-get install perl
sudo apt-get install python
sudo apt-get install python-lxml
sudo apt-get install texinfo
sudo apt-get install time
sudo apt-get install valgrind
sudo apt-get install zip
sudo apt-get install qt5-default
sudo apt-get install clang-format-7
# Add all the supported compilers
sudo apt-get install g++-5
sudo apt-get install gcc-5
sudo apt-get install g++-6
sudo apt-get install gcc-6
sudo apt-get install g++-7
sudo apt-get install gcc-7
sudo apt-get install g++-8
sudo apt-get install gcc-8
sudo apt-get install g++-9
sudo apt-get install gcc-9
sudo apt-get install clang-6.0
sudo apt-get install clang-8

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "OpenSTA"]
path = OpenSTA
url = https://github.com/abk-openroad/OpenSTA

20
.readthedocs.yml Normal file
View File

@ -0,0 +1,20 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required configuration file version
version: 2
# Build documentation in the docs/ directory with Sphinx
sphinx:
builder: dirhtml
configuration: docs/source/conf.py
# Optionally build your docs in additional formats such as PDF and ePub
formats: all
# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.7
install:
- requirements: docs/requirements.txt

View File

@ -5,51 +5,6 @@ set -e
start_section "OpenFPGA.TaskTun" "${GREEN}..Running_Regression..${NC}"
cd ${TRAVIS_BUILD_DIR}
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "Basic regression tests";
echo -e "Testing configuration chain of a K4N4 FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_configuration_chain --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/preconfig_testbench/configuration_chain --debug --show_thread_logs
echo -e "Testing fram-based configuration protocol of a K4N4 FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_frame --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_configuration_frame --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/preconfig_testbench/configuration_frame --debug --show_thread_logs
echo -e "Testing memory bank configuration protocol of a K4N4 FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/memory_bank --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/fast_memory_bank --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/preconfig_testbench/memory_bank --debug --show_thread_logs
echo -e "Testing standalone (flatten memory) configuration protocol of a K4N4 FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/flatten_memory --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/preconfig_testbench/flatten_memory --debug --show_thread_logs
echo -e "Testing fabric Verilog generation only";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/generate_fabric --debug --show_thread_logs
echo -e "Testing Verilog testbench generation only";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/generate_testbench --debug --show_thread_logs
echo -e "Testing user-defined simulation settings: clock frequency and number of cycles";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/fixed_simulation_settings --debug --show_thread_logs
echo -e "Testing K4 series FPGA";
echo -e "Testing K4N4 with facturable LUTs";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_frac_lut --debug --show_thread_logs
echo -e "Testing K4N4 with hard adders";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_adder --debug --show_thread_logs
echo -e "Testing K4N4 without local routing architecture";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_no_local_routing --debug --show_thread_logs
echo -e "Testing K4N4 with block RAM";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_bram --debug --show_thread_logs
echo -e "Testing K4N4 with multiple lengths of routing segments";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_L124 --debug --show_thread_logs
echo -e "Testing K4N4 with 32-bit fracturable multiplier";
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/k4_series/k4n4_frac_mult --debug --show_thread_logs
source .github/workflows/basic_reg_test.sh
end_section "OpenFPGA.TaskTun"

View File

@ -5,22 +5,6 @@ set -e
start_section "OpenFPGA.TaskTun" "${GREEN}..Running_Regression..${NC}"
cd ${TRAVIS_BUILD_DIR}
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "FPGA-Bitstream regression tests";
echo -e "Testing bitstream generation for an auto-sized device";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_bitstream/generate_bitstream/device_auto --debug --show_thread_logs
echo -e "Testing bitstream generation for an 48x48 FPGA device";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_bitstream/generate_bitstream/device_48x48 --debug --show_thread_logs
echo -e "Testing bitstream generation for an 96x96 FPGA device";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_bitstream/generate_bitstream/device_96x96 --debug --show_thread_logs
echo -e "Testing loading architecture bitstream from an external file";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_bitstream/load_external_architecture_bitstream --debug --show_thread_logs
source .github/workflows/fpga_bitstream_reg_test.sh
end_section "OpenFPGA.TaskTun"

View File

@ -5,12 +5,6 @@ set -e
start_section "OpenFPGA.TaskTun" "${GREEN}..Running_Regression..${NC}"
cd ${TRAVIS_BUILD_DIR}
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "FPGA-SDC regression tests";
echo -e "Testing SDC generation with time units";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_sdc/sdc_time_unit --debug --show_thread_logs
source .github/workflows/fpga_sdc_reg_test.sh
end_section "OpenFPGA.TaskTun"

View File

@ -5,12 +5,6 @@ set -e
start_section "OpenFPGA.TaskTun" "${GREEN}..Running_Regression..${NC}"
cd ${TRAVIS_BUILD_DIR}
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "FPGA-SPICE regression tests";
echo -e "Testing FPGA-SPICE with netlist generation";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_spice/generate_spice --debug --show_thread_logs
source .github/workflows/fpga_spice_reg_test.sh
end_section "OpenFPGA.TaskTun"

View File

@ -5,105 +5,6 @@ set -e
start_section "OpenFPGA.TaskTun" "${GREEN}..Running_Regression..${NC}"
cd ${TRAVIS_BUILD_DIR}
###############################################
# OpenFPGA Shell with VPR8
##############################################
echo -e "FPGA-Verilog Feature Tests";
echo -e "Testing Verilog generation for LUTs: a single mode LUT6 FPGA using micro benchmarks";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/lut_design/single_mode --debug --show_thread_logs
echo -e "Testing Verilog generation for LUTs: simple fracturable LUT4 ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/lut_design/frac_lut4 --debug --show_thread_logs
echo -e "Testing Verilog generation for LUTs: simple fracturable LUT6 ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/lut_design/frac_lut6 --debug --show_thread_logs
echo -e "Testing Verilog generation for LUTs: LUT6 with intermediate buffers";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/lut_design/intermediate_buffer --debug --show_thread_logs
echo -e "Testing Verilog generation with VPR's untileable routing architecture ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/untileable --debug --show_thread_logs
echo -e "Testing Verilog generation with hard adder chain in CLBs ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/hard_adder --debug --show_thread_logs
echo -e "Testing Verilog generation with 16k block RAMs ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/bram/dpram16k --debug --show_thread_logs
echo -e "Testing Verilog generation with 16k block RAMs spanning two columns ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/bram/wide_dpram16k --debug --show_thread_logs
echo -e "Testing Verilog generation with different I/O capacities on each side of an FPGA ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/io/multi_io_capacity --debug --show_thread_logs
echo -e "Testing Verilog generation with I/Os only on left and right sides of an FPGA ";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/io/reduced_io --debug --show_thread_logs
echo -e "Testing Verilog generation with adder chain across an FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_chain/adder_chain --debug --show_thread_logs
echo -e "Testing Verilog generation with shift register chain across an FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_chain/register_chain --debug --show_thread_logs
echo -e "Testing Verilog generation with scan chain across an FPGA";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_chain/scan_chain --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers implemented by tree structure";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/tree_structure --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers implemented by standard cell MUX2";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/stdcell_mux2 --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers implemented by local encoders";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/local_encoder --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers without buffers";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/debuf_mux --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers with input buffers only";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/inbuf_only_mux --debug --show_thread_logs
echo -e "Testing Verilog generation with routing multiplexers with output buffers only";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mux_design/outbuf_only_mux --debug --show_thread_logs
echo -e "Testing Verilog generation with behavioral description";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/behavioral_verilog --debug --show_thread_logs
echo -e "Testing implicit Verilog generation";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/implicit_verilog --debug --show_thread_logs
echo -e "Testing Verilog generation with flatten routing modules";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/flatten_routing --debug --show_thread_logs
echo -e "Testing Verilog generation with duplicated grid output pins";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/duplicated_grid_pin --debug --show_thread_logs
echo -e "Testing Verilog generation with spy output pads";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/spypad --debug --show_thread_logs
echo -e "Testing Secured FPGA fabrics";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_key/generate_vanilla_key --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_key/generate_random_key --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fabric_key/load_external_key --debug --show_thread_logs
echo -e "Testing Power-gating designs";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/power_gated_design/power_gated_inverter --show_thread_logs --debug
echo -e "Testing Depopulated crossbar in local routing";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/depopulate_crossbar --debug --show_thread_logs
echo -e "Testing Fully connected output crossbar in local routing";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/fully_connected_output_crossbar --debug --show_thread_logs
echo -e "Testing through channels in tileable routing";
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/thru_channel/thru_narrow_tile --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/thru_channel/thru_wide_tile --debug --show_thread_logs
# Verify MCNC big20 benchmark suite with ModelSim
# Please make sure you have ModelSim installed in the environment
# Otherwise, it will fail
#python3 openfpga_flow/scripts/run_fpga_task.py fpga_verilog/mcnc_big20 --debug --show_thread_logs --maxthreads 20
#python3 openfpga_flow/scripts/run_modelsim.py mcnc_big20 --run_sim
source .github/workflows/fpga_verilog_reg_test.sh
end_section "OpenFPGA.TaskTun"

View File

@ -1,14 +1,24 @@
# Getting Started with OpenFPGA <img src="./docs/source/figures/OpenFPGA_logo.png" width="200" align="right">
# Getting Started with OpenFPGA <img src="./docs/source/overview/figures/OpenFPGA_logo.png" width="200" align="right">
![Github Actions Status](https://github.com/LNIS-Projects/OpenFPGA/workflows/OpenFPGA%20Tests/badge.svg)
[![Build Status](https://travis-ci.com/LNIS-Projects/OpenFPGA.svg?branch=master)](https://travis-ci.com/LNIS-Projects/OpenFPGA)
[![Documentation Status](https://readthedocs.org/projects/openfpga/badge/?version=master)](https://openfpga.readthedocs.io/en/master/?badge=master)
## Introduction
The OpenFPGA framework is the **first open-source FPGA IP generator** supporting highly-customizable homogeneous FPGA architectures. OpenFPGA provides a full set of 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.
The award-winning OpenFPGA framework is the **first open-source FPGA IP generator** supporting highly-customizable homogeneous FPGA architectures. OpenFPGA provides a full set of 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.
A quick overview of OpenFPGA tools can be found [**here**](https://openfpga.readthedocs.io/en/master/tutorials/tools.html).
We also recommend potential users to checkout the summary of [**technical capabilities**](https://openfpga.readthedocs.io/en/master/overview/tech_highlights.html) before compiling.
## Compilation
Dependencies and help using docker can be found [**here**](./docs/source/tutorials/compile.rst).
Before start, we strongly recommend you to read the required dependencies at [**compilation guidelines**](https://openfpga.readthedocs.io/en/master/tutorials/compile.html).
It also includes detailed information about docker image.
---
**Compilation Steps:**
```bash
# Clone the repository and go inside it
git clone https://github.com/LNIS-Projects/OpenFPGA.git && cd OpenFPGA
@ -16,9 +26,11 @@ mkdir build && cd build # Create a folder named build in the OpenPFGA
cmake .. # Create a Makefile in this folder using cmake
make # Compile the tool and its dependencies
```
*cmake3.12 is recommended to compile OpenFPGA with GUI*
---
**Quick Compilation Verification**
To quickly verify the tool is well compiled, user can run the following command from OpenFPGA root repository.
```bash
python3 openfpga_flow/scripts/run_fpga_task.py compilation_verification --debug --show_thread_logs
@ -26,8 +38,10 @@ python3 openfpga_flow/scripts/run_fpga_task.py compilation_verification --debug
*Python3 and iVerilog v10.1+ are required. GUI will pop-up if enabled during compilation.*
---
**Supported Operating Systems**
We currently target OpenFPGA for:
1. Ubuntu 18.04
2. Red Hat 7.5
@ -35,7 +49,9 @@ We currently target OpenFPGA for:
*The tool was tested with these operating systems. It might work with earlier versions and other distributions.*
## Documentation
OpenFPGA's [full documentation](https://openfpga.readthedocs.io/en/master/) includes tutorials, descriptions of the design flow, and tool options.
## Tutorials
You can find some tutorials in the [**./tutorials**](./docs/source/tutorials/) folder. This will help you get more familiar with the tool and use OpenFPGA under different configurations.

View File

@ -7,9 +7,10 @@ Welcome to OpenFPGA's documentation!
====================================
.. toctree::
:caption: Motivation
:maxdepth: 2
:caption: Overview
motivation
overview/index
.. toctree::
:maxdepth: 2

View File

@ -49,6 +49,74 @@ Similar to the Switch Boxes and Connection Blocks, the channel wire segments in
- ``circuit_model_name="<string>"`` should match a circuit model whose type is ``chan_wire`` defined in :ref:`circuit_library`.
Physical Tile Annotation
~~~~~~~~~~~~~~~~~~~~~~~~
Original VPR architecture description contains ``<tile>`` XML nodes to define physical tile pins.
OpenFPGA allows users to define pin/port of physical tiles as global ports.
Here is an example:
.. code-block:: xml
<tile_annotations>
<global_port name="<string>" tile_port="<string>" is_clock="<bool>" is_reset="<bool>" is_set="<bool>"/>
</tile_annotations>
- ``name="<string>"`` is the port name to appear in the top-level FPGA fabric.
- ``tile_port="<string>"`` is the port name of a physical tile, e.g., ``tile_port="clb.clk"``.
.. note:: The port of physical tile must be a valid port of the physical definition in VPR architecture!
.. note:: The linked port of physical tile must meet the following requirements:
- If the ``global_port`` is set as clock through ``is_clock="true"``, the port of the physical tile must also be a clock port.
- If not a clock, the port of the physical tile must be defined as non-clock global
- The port of the physical tile should have zero connectivity (``Fc=0``) in VPR architecture
- ``is_clock="<bool>"`` define if the global port is a clock port at the top-level FPGA fabric. An operating clock port will be driven by proper signals in auto-generated testbenches.
- ``is_reset="<bool>"`` define if the global port is a reset port at the top-level FPGA fabric. An operating reset port will be driven by proper signals in testbenches.
- ``is_set="<bool>"`` define if the global port is a set port at the top-level FPGA fabric. An operating set port will be driven by proper signals in testbenches.
.. note:: A port can only be defined as ``clock`` or ``set`` or ``reset``.
.. note:: All the global port from a physical tile port is only used in operating phase. Any ports for programmable use are not allowed!
A more illustrative example:
:numref:`fig_global_tile_ports` illustrates the difference between the global ports defined through ``circuit_model`` and ``tile_annotation``.
.. _fig_global_tile_ports:
.. figure:: ./figures/global_tile_ports.png
:scale: 100%
:alt: Difference between global port definition through circuit model and tile annotation
Difference between global port definition through circuit model and tile annotation
When a global port, e.g., ``clk``, is defined in ``circuit_model`` using the following code:
.. code-block:: xml
<circuit_model>
<port name="clk" is_global="true" is_clock="true"/>
</circuit_model>
Dedicated feedthrough wires will be created across all the modules from top-level to primitive.
When a global port, e.g., ``clk``, is defined in ``tile_annotation`` using the following code:
.. code-block:: xml
<tile_annotations>
<global_port name="clk" tile_port="clb.clk" is_clock="true"/>
</tile_annotations>
Clock port ``clk`` of each ``clb`` tile will be connected to a common clock port of the top module, while local clock network is customizable through VPR's architecture description language. For instance, the local clock network can be a programmable clock network.
Primitive Blocks inside Multi-mode Configurable Logic Blocks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -143,7 +143,8 @@ A circuit model may consist of a number of ports. The port list is mandatory in
.. option:: <port type="<string>" prefix="<string>" lib_name="<string>" size="<int>"
default_val="<int>" circuit_model_name="<string>" mode_select="<bool>"
is_global="<bool>" is_set="<bool>" is_reset="<bool>" is_config_enable="<bool>"/>
is_global="<bool>" is_set="<bool>" is_reset="<bool>"
is_config_enable="<bool>" is_io="<bool>" is_data_io="<bool>"/>
Define the attributes for a port of a circuit model.
@ -169,10 +170,14 @@ A circuit model may consist of a number of ports. The port list is mandatory in
.. note:: ``circuit_model_name`` is only valid when the type of this port is ``sram``.
- ``io="true|false"`` Specify if this port should be treated as an I/O port of an FPGA fabric. When this is enabled, this port of each circuit model instanciated in FPGA will be added as an I/O of an FPGA.
- ``is_io="true|false"`` Specify if this port should be treated as an I/O port of an FPGA fabric. When this is enabled, this port of each circuit model instanciated in FPGA will be added as an I/O of an FPGA.
.. note:: global ``output`` ports must be ``io`` ports
- ``is_data_io="true|false"`` Specify if this port should be treated as a mappable FPGA I/O port for users' implementation. When this is enabled, I/Os of user's implementation, e.g., ``.input`` and ``.output`` in ``.blif`` netlist, can be mapped to the port through VPR.
.. note:: Any I/O model must have at least 1 port that is defined as data I/O!
- ``mode_select="true|false"`` Specify if this port controls the mode switching in a configurable logic block. This is due to that a configurable logic block can operate in different modes, which is controlled by SRAM bits.
.. note:: ``mode_select`` is only valid when the type of this port is ``sram``.

View File

@ -30,6 +30,8 @@ Template
- ``f_per_stage="<float>"`` Define the ratio of driving strength between the levels of a tapered inverter/buffer. Default value is 4.
.. _circuit_model_inverter_1x_example:
Inverter 1x Example
```````````````````
@ -59,6 +61,8 @@ This example shows:
- Size of 1 for the output strength
- The tapered parameter is not declared and is ``false`` by default
.. _circuit_model_power_gated_inverter_example:
Power-gated Inverter 1x example
```````````````````````````````
@ -74,7 +78,9 @@ The XML code describing an inverter which can be power-gated by the control sign
<port type="output" prefix="out" size="1" lib_name="Z"/>
</circuit_model>
.. note:: For power-gated inverters: all the control signals must be set as ``config_enable`` so that the testbench generation will generate testing waveforms. If the power-gated inverters are auto-generated , all the ``config_enable`` signals must be ``global`` signals as well. If the pwoer-gated inverters come from user-defined netlists, restrictions on ``global`` signals are free.
.. note:: For power-gated inverters: all the control signals must be set as ``config_enable`` so that the testbench generation will generate testing waveforms. If the power-gated inverters are auto-generated, all the ``config_enable`` signals must be ``global`` signals as well. If the power-gated inverters come from user-defined netlists, restrictions on ``global`` signals are free.
.. _circuit_model_buffer_2x_example:
Buffer 2x example
`````````````````
@ -104,6 +110,26 @@ This example shows:
- Size of 2 for the output strength
- The tapered parameter is not declared and is ``false`` by default
.. _circuit_model_power_gated_buffer_example:
Power-gated Buffer 4x example
`````````````````````````````
The XML code describing a buffer which can be power-gated by the control signals ``EN`` and ``ENB`` :
.. code-block:: xml
<circuit_model type="inv_buf" name="buf_4x" prefix="buf_4x">
<design_technology type="cmos" topology="buffer" size="4" power_gated="true"/>
<port type="input" prefix="in" size="1" lib_name="I"/>
<port type="input" prefix="EN" size="1" lib_name="EN" is_global="true" default_val="0" is_config_enable="true"/>
<port type="input" prefix="ENB" size="1" lib_name="ENB" is_global="true" default_val="1" is_config_enable="true"/>
<port type="output" prefix="out" size="1" lib_name="Z"/>
</circuit_model>
.. note:: For power-gated buffers: all the control signals must be set as ``config_enable`` so that the testbench generation will generate testing waveforms. If the power-gated buffers are auto-generated, all the ``config_enable`` signals must be ``global`` signals as well. If the power-gated buffers come from user-defined netlists, restrictions on ``global`` signals are free.
.. _circuit_model_tapered_inv_16x_example:
Tapered inverter 16x example
````````````````````````````
@ -123,7 +149,7 @@ The XML code describing this inverter is:
.. code-block:: xml
<circuit_model type="inv_buf" name="tapdrive4" prefix="tapdrive4">
<design_technology type="cmos" topology=inverter" size="1" num_level="3" f_per_stage="4"/>
<design_technology type="cmos" topology="inverter" size="1" num_level="3" f_per_stage="4"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
</circuit_model>
@ -133,7 +159,30 @@ This example shows:
- The topology chosen as inverter
- Size of 1 for the first stage output strength
- The number of stage is set to 3 by
- f_per_stage is set to 4. Then 2nd stage output strength is 4* the 1st stage output strength (so 4*1 = 4) and the 3rd stage output strength is 4* the 2nd stage output strength (so 4*4 = 16).
- f_per_stage is set to 4. As a result, 2nd stage output strength is 4x, and the 3rd stage output strength is 16x.
.. _circuit_model_tapered_buffer_64x_example:
Tapered buffer 64x example
``````````````````````````
The XML code describing a 4-stage buffer is:
.. code-block:: xml
<circuit_model type="inv_buf" name="tapbuf_16x" prefix="tapbuf_16x">
<design_technology type="cmos" topology="buffer" size="1" num_level="4" f_per_stage="4"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
</circuit_model>
This example shows:
- The topology chosen as buffer
- Size of 1 for the first stage output strength
- The number of stage is set to 4 by
- f_per_stage is set to 2. As a result, 2nd stage output strength is 4*, the 3rd stage output strength is 16*, and the 4th stage output strength is 64x.
Pass-gate Logic
~~~~~~~~~~~~~~~
@ -151,7 +200,15 @@ Template
<port type="output" prefix="<string>" size="<int>"/>
</circuit_model>
.. note:: Please do not add input and output buffers to pass-gate logic.
.. note:: The port sequence really matters! And all the input ports must have an input size of 1!
- The first input must be the datapath input, e.g., ``in``.
- The second input must be the select input, e.g., ``sel``.
- The third input (if applicable) must be the inverted select input, e.g., ``selb``.
.. warning:: Please do **NOT** add input and output buffers to pass-gate logic.
.. option:: <design_technology type="cmos" topology="<string>" nmos_size="<float>" pmos_size="<float>"/>
@ -163,6 +220,8 @@ Template
.. note:: ``nmos_size`` and ``pmos_size`` are required for FPGA-SPICE
.. _circuit_model_tgate_example:
Transmission-gate Example
`````````````````````````
@ -192,6 +251,8 @@ This example shows:
- A ``transmission_gate`` built with a *n*-type transistor in the size of 1 and a *p*-type transistor in the size of 2.
- 3 inputs considered, 1 for datapath signal and 2 to turn on/off the transistors gates
.. _circuit_model_pass_transistor_example:
Pass-transistor Example
```````````````````````
@ -240,6 +301,8 @@ Template
.. note:: The information of input and output buffer should be clearly specified according to the customized Verilog/SPICE netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
.. _circuit_model_sram_blwl_example:
SRAM with BL/WL
```````````````
.. _fig_sram_blwl:
@ -268,6 +331,8 @@ The following XML codes describes the SRAM cell shown in :numref:`fig_sram_blwl`
.. note:: When the ``memory_bank`` type of configuration procotol is specified, SRAM modules should have a BL and a WL.
.. _circuit_model_config_latch_example:
Configurable Latch
``````````````````
@ -319,8 +384,43 @@ Template
- ``topology="AND|OR|MUX2"`` Specify the logic functionality of a gate. As for standard cells, the size of each port is limited to 1. Currently, only 2-input and single-output logic gates are supported.
2-input OR Gate Example
```````````````````````
.. note:: The port sequence really matters for MUX2 logic gates!
- The first two inputs must be the datapath inputs, e.g., ``in0`` and ``in1``.
- The third input must be the select input, e.g., ``sel``.
.. _circuit_model_and2_example:
2-input AND Gate
````````````````
.. code-block:: xml
<circuit_model type="gate" name="AND2" prefix="AND2" is_default="true">
<design_technology type="cmos" topology="AND"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="a" size="1"/>
<port type="input" prefix="b" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="a b" out_port="out">
10e-12 8e-12
</delay_matrix>
<delay_matrix type="fall" in_port="a b" out_port="out">
10e-12 7e-12
</delay_matrix>
</circuit_model>
This example shows:
- A 2-input AND gate without any input and output buffers
- Propagation delay from input ``a`` to ``out`` is 10ps in rising edge and and 8ps in falling edge
- Propagation delay from input ``b`` to ``out`` is 10ps in rising edge and 7ps in falling edge
.. _circuit_model_or2_example:
2-input OR Gate
```````````````
.. code-block:: xml
@ -344,8 +444,10 @@ This example shows:
- Propagation delay from input ``a`` to ``out`` is 10ps in rising edge and and 8ps in falling edge
- Propagation delay from input ``b`` to ``out`` is 10ps in rising edge and 7ps in falling edge
MUX2 Gate Example
```````````````````````
.. _circuit_model_mux2_gate_example:
MUX2 Gate
`````````
.. code-block:: xml
@ -409,7 +511,9 @@ Template
.. note:: When multiplexers are not provided by users, the size of ports do not have to be consistent with actual numbers in the architecture.
One-level Mux Example
.. _circuit_model_mux_1level_example:
One-level Multiplexer
`````````````````````
:numref:`fig_mux1` illustrates an example of multiplexer modelling, which consists of input/output buffers and a transmission-gate-based tree structure.
@ -443,8 +547,10 @@ This example shows:
- The multiplexer will be built by transmission gate using the circuit model ``tgate``
- The multiplexer will have 4 inputs and 4 SRAMs to control which datapath to propagate
Tree-like Multiplexer Example
`````````````````````````````
.. _circuit_model_mux_tree_example:
Tree-like Multiplexer
`````````````````````
:numref:`fig_mux` illustrates an example of multiplexer modelling, which consists of input/output buffers and a transmission-gate-based tree structure.
@ -477,8 +583,10 @@ This example shows:
- The multiplexer will be built by transmission gate using the circuit model ``tgate``
- The multiplexer will have 4 inputs and 3 SRAMs to control which datapath to propagate
Standard Cell Multiplexer Example
`````````````````````````````````
.. _circuit_model_mux_stdcell_example:
Standard Cell Multiplexer
`````````````````````````
.. code-block:: xml
<circuit_model type="mux" name="mux_stdcell" prefix="mux_stdcell">
@ -497,6 +605,74 @@ This example shows:
- All the outputs will be buffered using the circuit model ``tapbuf4``
- The multiplexer will have 4 inputs and 3 SRAMs to control which datapath to propagate
.. _circuit_model_mux_multilevel_example:
Multi-level Multiplexer
```````````````````````
.. code-block:: xml
<circuit_model type="mux" name="mux_2level" prefix="mux_stdcell">
<design_technology type="cmos" structure="multi_level" num_level="2"/>
<input_buffer exist="on" circuit_model_name="inv1x"/>
<output_buffer exist="on" circuit_model_name="tapdrive4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="16"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="8"/>
</circuit_model>
This example shows:
- A two-level 16-input CMOS multiplexer built by the transmission gate ``TGATE``
- All the inputs will be buffered using the circuit model ``inv1x``
- All the outputs will be buffered using the circuit model ``tapbuf4``
- The multiplexer will have 16 inputs and 8 SRAMs to control which datapath to propagate
.. _circuit_model_mux_local_encoder_example:
Multiplexer with Local Encoder
``````````````````````````````
.. code-block:: xml
<circuit_model type="mux" name="mux_2level" prefix="mux_stdcell">
<design_technology type="cmos" structure="multi_level" num_level="2" local_encoder="true"/>
<input_buffer exist="on" circuit_model_name="inv1x"/>
<output_buffer exist="on" circuit_model_name="tapdrive4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="16"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="4"/>
</circuit_model>
This example shows:
- A two-level 16-input CMOS multiplexer built by the transmission gate ``TGATE``
- All the inputs will be buffered using the circuit model ``inv1x``
- All the outputs will be buffered using the circuit model ``tapbuf4``
- The multiplexer will have 16 inputs and 4 SRAMs to control which datapath to propagate
- Two local encoders are generated between the SRAMs and multiplexing structure to reduce the number of configurable memories required.
.. _circuit_model_mux_const_input_example:
Multiplexer with Constant Input
```````````````````````````````
.. code-block:: xml
<circuit_model type="mux" name="mux_2level" prefix="mux_stdcell">
<design_technology type="cmos" structure="multi_level" num_level="2" add_const_input="true" const_input_val="1"/>
<input_buffer exist="on" circuit_model_name="inv1x"/>
<output_buffer exist="on" circuit_model_name="tapdrive4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="14"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="8"/>
</circuit_model>
This example shows:
- A two-level 16-input CMOS multiplexer built by the transmission gate ``TGATE``
- All the inputs will be buffered using the circuit model ``inv1x``
- All the outputs will be buffered using the circuit model ``tapbuf4``
- The multiplexer will have 15 inputs and 8 SRAMs to control which datapath to propagate
- An constant input toggled at logic '1' is added in addition to the 14 regular inputs
Look-Up Tables
~~~~~~~~~~~~~~
@ -576,8 +752,10 @@ Template
.. note:: The size of a mode-selection SRAM port should be consistent to the number of '1s' or '0s' in the ``tri_state_map``.
Single-Output LUT Example
`````````````````````````
.. _circuit_model_single_output_lut_example:
Single-Output LUT
`````````````````
:numref:`fig_lut` illustrates an example of LUT modeling, which consists of input/output buffers and a transmission-gate-based tree structure.
@ -609,8 +787,10 @@ This example shows:
- The multiplexer inside LUT will be built with transmission gate using circuuit model ``inv1x``
- There are no internal buffered inserted to any intermediate stage of a LUT
Fracturable LUT Example
`````````````````````````
.. _circuit_model_frac_lut_example:
Fracturable LUT
```````````````
.. code-block:: xml
@ -666,14 +846,16 @@ Template
- ``type="ccff|ff"`` Specify the type of a flip-flop. ``ff`` is a regular flip-flop while ``ccff`` denotes a configuration-chain flip-flop
.. note:: A flip-flop should have three types of ports, ``input``, ``output`` and ``clock``.
.. note:: A flip-flop should at least have three types of ports, ``input``, ``output`` and ``clock``.
.. note:: If the user provides a customized Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist.
.. note:: In a valid FPGA architecture, users should provide at least either a ``ccff`` or ``sram`` circuit model, so that the configurations can loaded to core logic.
Flip-Flop example
`````````````````
.. _circuit_model_dff_example:
D-type Flip-Flop
````````````````
:numref:`fig_ff` illustrates an example of regular flip-flop.
@ -702,8 +884,10 @@ This example shows:
- The flip-flop has ``set`` and ``reset`` functionalities
- The flip-flop port names defined differently in standard cell library and VPR architecture. The ``lib_name`` capture the port name defined in standard cells, while ``prefix`` capture the port name defined in ``pb_type`` of VPR architecture file
Configuration-chain Flip-flop Example
`````````````````````````````````````
.. _circuit_model_ccff_example:
Configuration-chain Flip-flop
`````````````````````````````
:numref:`fig_ccff` illustrates an example of scan-chain flop-flop used to build a configuration chain.
@ -721,7 +905,8 @@ The code describing this FF is:
<circuit_model type="ccff" name="ccff" prefix="ccff" verilog_netlist="ccff.v" spice_netlist="ccff.sp">
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="2"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="Qb" size="1"/>
<port type="clock" prefix="CK" size="1" is_global="true"/>
</circuit_model>
@ -756,8 +941,10 @@ Template
.. note:: The information of input and output buffer should be clearly specified according to the customized Verilog/SPICE netlist! The existence of input/output buffers will influence the decision in creating SPICE testbenches, which may leads to larger errors in power analysis.
1-bit Full Adder Example
````````````````````````
.. _circuit_model_full_adder_example:
Full Adder
``````````
.. code-block:: xml
@ -857,10 +1044,12 @@ Template
.. note:: The information of input and output buffer should be clearly specified according to the customized netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
I/O Pad Example
```````````````
.. _circuit_model_gpio_example:
:numref:`fig_iopad` depicts an I/O pad.
General Purpose I/O
```````````````````
:numref:`fig_iopad` depicts a general purpose I/O pad.
.. _fig_iopad:
@ -870,7 +1059,7 @@ I/O Pad Example
An example of an IO-Pad
The code describing this IO-Pad is:
The code describing this I/O-Pad is:
.. code-block:: xml
@ -879,7 +1068,7 @@ The code describing this IO-Pad is:
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="inout" prefix="pad" size="1"/>
<port type="inout" prefix="pad" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="sram" prefix="en" size="1" mode_select="true" circuit_model_name="ccff" default_val="1"/>
<port type="input" prefix="outpad" size="1"/>
<port type="output" prefix="inpad" size="1"/>

View File

@ -41,6 +41,13 @@ Template
- ``memory_bank`` requires a circuit model type of ``sram``
- ``standalone`` requires a circuit model type of ``sram``
.. option:: num_regions="<int>"
Specify the number of configuration regions to be used across the fabrics. By default, it will be only 1 configuration region. Each configuration region contains independent configuration protocols, but the whole fabric should employ the same type of configuration protocols. For example, an FPGA fabric consists of 4 configuration regions, each of which includes a configuration chain. The more configuration chain to be used, the fast configuration runtime will be, but at the cost of more I/Os in the FPGA fabrics. The organization of each configurable region can be customized through the fabric key (see details in :ref:`fabric_key`).
.. warning:: Currently, multiple configuration regions is not applicable to ``standalone`` configuration protocol.
Configuration Chain Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following XML code describes a scan-chain circuitry to configure the core logic of FPGA, as illustrated in :numref:`fig_ccff_fpga`.
@ -49,7 +56,7 @@ It will use the circuit model defined in :numref:`fig_ccff`.
.. code-block:: xml
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="ccff"/>
<organization type="scan_chain" circuit_model_name="ccff" num_regions="<int>"/>
</configuration_protocol>
.. _fig_ccff_fpga:
@ -60,6 +67,14 @@ It will use the circuit model defined in :numref:`fig_ccff`.
Example of a configuration chain to program core logic of a FPGA
.. figure:: figures/multi_region_config_chains.png
:scale: 100%
:alt: map to buried treasure
Examples of single- and multiple- region configuration chains
Frame-based Example
~~~~~~~~~~~~~~~~~~~
The following XML code describes frame-based memory banks to configure the core logic of FPGA.
@ -102,10 +117,13 @@ When the decoder of sub block, e.g., the LUT, is enabled, each memory cells can
.. warning:: Please do NOT add inverted Bit-Line and Word-Line inputs. It is not supported yet!
When multiple configuration region is applied, the configuration frames will be grouped into different configuration regions. Each region has a separated data input bus and dedicated address decoders. As such, the configuration frame groups can be programmed in parallel.
Memory bank Example
~~~~~~~~~~~~~~~~~~~
The following XML code describes a memory-bank circuitry to configure the core logic of FPGA, as illustrated in :numref:`fig_sram`.
The following XML code describes a memory-bank circuitry to configure the core logic of FPGA, as illustrated in :numref:`fig_memory_bank`.
It will use the circuit model defined in :numref:`fig_sram_blwl`.
Users can customized the number of memory banks to be used across the fabrics. By default, it will be only 1 memory bank. :numref:`fig_memory_bank` shows an example where 4 memory banks are defined. The more memory bank to be used, the fast configuration runtime will be, but at the cost of more I/Os in the FPGA fabrics. The organization of each configurable region can be customized through the fabric key (see details in :ref:`fabric_key`).
.. code-block:: xml
@ -113,13 +131,13 @@ It will use the circuit model defined in :numref:`fig_sram_blwl`.
<organization type="memory_bank" circuit_model_name="sram_blwl"/>
</configuration_protocol>
.. _fig_sram:
.. _fig_memory_bank:
.. figure:: figures/sram.png
:scale: 60%
.. figure:: figures/memory_bank.png
:scale: 30%
:alt: map to buried treasure
Example of a memory organization using memory decoders
Example of (a) a memory organization using memory decoders; (b) single memory bank across the fabric; and (c) multiple memory banks across the fabric.
.. note:: Memory-bank decoders does require a memory cell to have

View File

@ -1,3 +1,5 @@
.. _fabric_key:
Fabric Key
~~~~~~~~~~
@ -6,6 +8,12 @@ With this key, OpenFPGA can generate correct bitstreams for the FPGA.
Using a wrong key, OpenFPGA may error out or generate wrong bitstreams.
The fabric key support allows users to build secured/classified FPGA chips even with an open-source tool.
.. figure:: figures/fabric_key_motivation.png
:scale: 60%
:alt: map to buried treasure
The use of fabric key to secure the FPGA chip design
.. note:: Users are the only owner of the key. OpenFPGA will not store or replicate the key.
Key Generation
@ -19,7 +27,56 @@ A fabric key can be achieved in the following ways:
File Format
```````````
A fabric key follows an XML format. As shown in the following XML code, the key file includes the organization of configurable memory blocks in the top-level FPGA fabric:
A fabric key follows an XML format. As shown in the following XML code, the key file includes the organization of configurable blocks in the top-level FPGA fabric.
Configurable Region
^^^^^^^^^^^^^^^^^^^
The top-level FPGA fabric can consist of several configurable regions, where a region may contain one or multiple configurable blocks. Each configurable region can be configured independently and in parrallel.
.. option:: <region id="<int>"/>
- ``id`` indicates the unique id of a configurable region in the fabric.
.. warning:: The id must start from zero!
.. note:: The number of regions defined in the fabric key must be consistent with the number of regions defined in the configuration protocol of architecture description. (See details in :ref:`config_protocol`).
The following example shows how to define multiple configuration regions in the fabric key.
.. code-block:: xml
<fabric_key>
<region id="0">
<key id="0" name="grid_io_bottom" value="0" alias="grid_io_bottom_1__0_"/>
<key id="1" name="grid_io_right" value="0" alias="grid_io_right_2__1_"/>
<key id="2" name="sb_1__1_" value="0" alias="sb_1__1_"/>
</region>
<region id="1">
<key id="3" name="cbx_1__1_" value="0" alias="cbx_1__1_"/>
<key id="4" name="grid_io_top" value="0" alias="grid_io_top_1__2_"/>
<key id="5" name="sb_0__1_" value="0" alias="sb_0__1_"/>
</region>
<region id="2">
<key id="6" name="sb_0__0_" value="0" alias="sb_0__0_"/>
<key id="7" name="cby_0__1_" value="0" alias="cby_0__1_"/>
<key id="8" name="grid_io_left" value="0" alias="grid_io_left_0__1_"/>
</region>
<region id="3">
<key id="9" name="sb_1__0_" value="0" alias="sb_1__0_"/>
<key id="10" name="cbx_1__0_" value="0" alias="cbx_1__0_"/>
<key id="11" name="cby_1__1_" value="0" alias="cby_1__1_"/>
<key id="12" name="grid_clb" value="0" alias="grid_clb_1__1_"/>
</region>
</fabric_key>
Configurable Block
^^^^^^^^^^^^^^^^^^^
Each configurable block is defined as a key. There are two ways to define a key, either with alias or with name and value.
.. option:: <key id="<int>" alias="<string>" name="<string>" value="<int>"/>
- ``id`` indicates the sequence of the configurable memory block in the top-level FPGA fabric.
@ -29,86 +86,92 @@ A fabric key follows an XML format. As shown in the following XML code, the key
- ``alias`` indicates the instance name of the configurable memory block in the top-level FPGA fabric. If a valid alias is specified, the ``name`` and ``value`` are not required.
.. note:: For fast loading of fabric key, strongly recommend to use pairs ``name`` and ``alias`` or ``name`` and ``value`` in the fabric key file. Using only ``alias`` may cause long parsing time for fabric key.
.. warning:: For fast loading of fabric key, strongly recommend to use pairs ``name`` and ``alias`` or ``name`` and ``value`` in the fabric key file. Using only ``alias`` may cause long parsing time for fabric key.
The following is an example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA.
This key contains only ``alias`` which is easy to craft.
.. code-block:: xml
<fabric_key>
<key id="0" alias="sb_2__2_"/>
<key id="1" alias="grid_clb_2_2"/>
<key id="2" alias="sb_0__1_"/>
<key id="3" alias="cby_0__1_"/>
<key id="4" alias="grid_clb_2_1"/>
<key id="5" alias="grid_io_left_0_1"/>
<key id="6" alias="sb_1__0_"/>
<key id="7" alias="sb_1__1_"/>
<key id="8" alias="cbx_2__1_"/>
<key id="9" alias="cby_1__2_"/>
<key id="10" alias="grid_io_right_3_2"/>
<key id="11" alias="cbx_2__0_"/>
<key id="12" alias="cby_1__1_"/>
<key id="13" alias="grid_io_right_3_1"/>
<key id="14" alias="grid_io_bottom_1_0"/>
<key id="15" alias="cby_2__1_"/>
<key id="16" alias="sb_2__1_"/>
<key id="17" alias="cbx_1__0_"/>
<key id="18" alias="grid_clb_1_2"/>
<key id="19" alias="cbx_1__2_"/>
<key id="20" alias="cbx_2__2_"/>
<key id="21" alias="sb_2__0_"/>
<key id="22" alias="sb_1__2_"/>
<key id="23" alias="cby_0__2_"/>
<key id="24" alias="sb_0__0_"/>
<key id="25" alias="grid_clb_1_1"/>
<key id="26" alias="cby_2__2_"/>
<key id="27" alias="grid_io_top_2_3"/>
<key id="28" alias="sb_0__2_"/>
<key id="29" alias="grid_io_bottom_2_0"/>
<key id="30" alias="cbx_1__1_"/>
<key id="31" alias="grid_io_top_1_3"/>
<key id="32" alias="grid_io_left_0_2"/>
</fabric_key>
<fabric_key>
<region id="0">
<key id="0" alias="sb_2__2_"/>
<key id="1" alias="grid_clb_2_2"/>
<key id="2" alias="sb_0__1_"/>
<key id="3" alias="cby_0__1_"/>
<key id="4" alias="grid_clb_2_1"/>
<key id="5" alias="grid_io_left_0_1"/>
<key id="6" alias="sb_1__0_"/>
<key id="7" alias="sb_1__1_"/>
<key id="8" alias="cbx_2__1_"/>
<key id="9" alias="cby_1__2_"/>
<key id="10" alias="grid_io_right_3_2"/>
<key id="11" alias="cbx_2__0_"/>
<key id="12" alias="cby_1__1_"/>
<key id="13" alias="grid_io_right_3_1"/>
<key id="14" alias="grid_io_bottom_1_0"/>
<key id="15" alias="cby_2__1_"/>
<key id="16" alias="sb_2__1_"/>
<key id="17" alias="cbx_1__0_"/>
<key id="18" alias="grid_clb_1_2"/>
<key id="19" alias="cbx_1__2_"/>
<key id="20" alias="cbx_2__2_"/>
<key id="21" alias="sb_2__0_"/>
<key id="22" alias="sb_1__2_"/>
<key id="23" alias="cby_0__2_"/>
<key id="24" alias="sb_0__0_"/>
<key id="25" alias="grid_clb_1_1"/>
<key id="26" alias="cby_2__2_"/>
<key id="27" alias="grid_io_top_2_3"/>
<key id="28" alias="sb_0__2_"/>
<key id="29" alias="grid_io_bottom_2_0"/>
<key id="30" alias="cbx_1__1_"/>
<key id="31" alias="grid_io_top_1_3"/>
<key id="32" alias="grid_io_left_0_2"/>
</region>
</fabric_key>
The following shows another example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA.
This key contains only ``name`` and ``value`` which is fast to parse.
.. code-block:: xml
<fabric_key>
<key id="0" name="sb_2__2_" value="0"/>
<key id="1" name="grid_clb" value="3"/>
<key id="2" name="sb_0__1_" value="0"/>
<key id="3" name="cby_0__1_" value="0"/>
<key id="4" name="grid_clb" value="2"/>
<key id="5" name="grid_io_left" value="0"/>
<key id="6" name="sb_1__0_" value="0"/>
<key id="7" name="sb_1__1_" value="0"/>
<key id="8" name="cbx_1__1_" value="1"/>
<key id="9" name="cby_1__1_" value="1"/>
<key id="10" name="grid_io_right" value="1"/>
<key id="11" name="cbx_1__0_" value="1"/>
<key id="12" name="cby_1__1_" value="0"/>
<key id="13" name="grid_io_right" value="0"/>
<key id="14" name="grid_io_bottom" value="0"/>
<key id="15" name="cby_2__1_" value="0"/>
<key id="16" name="sb_2__1_" value="0"/>
<key id="17" name="cbx_1__0_" value="0"/>
<key id="18" name="grid_clb" value="1"/>
<key id="19" name="cbx_1__2_" value="0"/>
<key id="20" name="cbx_1__2_" value="1"/>
<key id="21" name="sb_2__0_" value="0"/>
<key id="22" name="sb_1__2_" value="0"/>
<key id="23" name="cby_0__1_" value="1"/>
<key id="24" name="sb_0__0_" value="0"/>
<key id="25" name="grid_clb" value="0"/>
<key id="26" name="cby_2__1_" value="1"/>
<key id="27" name="grid_io_top" value="1"/>
<key id="28" name="sb_0__2_" value="0"/>
<key id="29" name="grid_io_bottom" value="1"/>
<key id="30" name="cbx_1__1_" value="0"/>
<key id="31" name="grid_io_top" value="0"/>
<key id="32" name="grid_io_left" value="1"/>
</fabric_key>
<fabric_key>
<region id="0">
<key id="0" name="sb_2__2_" value="0"/>
<key id="1" name="grid_clb" value="3"/>
<key id="2" name="sb_0__1_" value="0"/>
<key id="3" name="cby_0__1_" value="0"/>
<key id="4" name="grid_clb" value="2"/>
<key id="5" name="grid_io_left" value="0"/>
<key id="6" name="sb_1__0_" value="0"/>
<key id="7" name="sb_1__1_" value="0"/>
<key id="8" name="cbx_1__1_" value="1"/>
<key id="9" name="cby_1__1_" value="1"/>
<key id="10" name="grid_io_right" value="1"/>
<key id="11" name="cbx_1__0_" value="1"/>
<key id="12" name="cby_1__1_" value="0"/>
<key id="13" name="grid_io_right" value="0"/>
<key id="14" name="grid_io_bottom" value="0"/>
<key id="15" name="cby_2__1_" value="0"/>
<key id="16" name="sb_2__1_" value="0"/>
<key id="17" name="cbx_1__0_" value="0"/>
<key id="18" name="grid_clb" value="1"/>
<key id="19" name="cbx_1__2_" value="0"/>
<key id="20" name="cbx_1__2_" value="1"/>
<key id="21" name="sb_2__0_" value="0"/>
<key id="22" name="sb_1__2_" value="0"/>
<key id="23" name="cby_0__1_" value="1"/>
<key id="24" name="sb_0__0_" value="0"/>
<key id="25" name="grid_clb" value="0"/>
<key id="26" name="cby_2__1_" value="1"/>
<key id="27" name="grid_io_top" value="1"/>
<key id="28" name="sb_0__2_" value="0"/>
<key id="29" name="grid_io_bottom" value="1"/>
<key id="30" name="cbx_1__1_" value="0"/>
<key id="31" name="grid_io_top" value="0"/>
<key id="32" name="grid_io_left" value="1"/>
</region>
</fabric_key>

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

View File

@ -47,6 +47,8 @@ The information depends on the type of configuration procotol.
.. option:: frame_based
Multiple lines will be included, each of which is organized as <address><space><bit>.
Note that the address may include don't care bit which is denoted as ``x``.
OpenFPGA automatically convert don't care bit to logic ``0`` when generating testbenches.
For example
.. code-block:: xml
@ -97,10 +99,12 @@ Other information may depend on the type of configuration procotol.
- ``frame``: frame address information
.. note:: Frame address may include don't care bit which is denoted as ``x``.
A quick example:
.. code-block:: xml
<bit id="0" value="1" path="fpga_top.grid_clb_1__2_.logical_tile_clb_mode_clb__0.mem_fle_9_in_5.mem_out[0]"/>
<frame address="0000000000000000"/>
<frame address="0001000x00000x01"/>
</bit>

View File

@ -48,18 +48,6 @@ Top-level Netlists
.. note:: We strongly recommend users to turn on this flag as it can help simulators to converge quickly.
- ```define ENABLE_SIGNAL_INITIALIZATION`` When enabled, all the outputs of primitive Verilog modules will be initialized with a random value. This flag is added when ``--include_signal_init`` option is enabled when calling the ``write_fabric_verilog`` command.
.. note:: We strongly recommend users to turn on this flag as it can help simulators to converge quickly.
- ```define ICARUS_SIMULATOR`` When enabled, Verilog netlists are generated to be compatible with the syntax required by `icarus iVerilog simulator`__. This flag is added when ``--support_icarus_simulator`` option is enabled when calling the ``write_fabric_verilog`` command.
.. warning:: Please disable this flag if you are not using icarus iVerilog simulator.
__ iverilog_website_
.. _iverilog_website: http://iverilog.icarus.com/
Logic Blocks
~~~~~~~~~~~~
This sub-directory contains all the Verilog modules modeling configurable logic blocks, heterogeneous blocks as well as I/O blocks.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 299 KiB

View File

@ -5,6 +5,16 @@ Testbench
In this part, we will introduce the hierarchy, dependency and functionality of each Verilog testbench, which are generated to verify a FPGA fabric implemented with an application.
+-----------------+---------+----------------+---------------+
| Testbench Type | Runtime | Test Vector | Test Coverage |
+=================+=========+================+===============+
| Full | Long | Random Stimuli | Full fabric |
+-----------------+---------+----------------+---------------+
| Formal-oriented | Short | Random Stimuli | Programmable |
| | | | fabric only |
| | | Formal Method | |
+-----------------+---------+----------------+---------------+
OpenFPGA can auto-generate two types of Verilog testbenches to validate the correctness of the fabric: full and formal-oriented.
Both testbenches share the same organization, as depicted in :numref:`fig_verilog_testbench_organization` (a).
To enable self-testing, the FPGA and user's RTL design (simulate using an HDL simulator) are driven by the same input stimuli, and any mismatch on their outputs will raise an error flag.
@ -70,6 +80,22 @@ Inside the directory, the Verilog testbenches are organized as illustrated in :n
.. note:: To run full testbenches, both flags ``ENABLE_FORMAL_VERIFICATION`` and ``ENABLE_FORMAL_SIMULATION`` must be disabled!
- ```define ENABLE_SIGNAL_INITIALIZATION`` When enabled, all the outputs of primitive Verilog modules will be initialized with a random value. This flag is added when ``--include_signal_init`` option is enabled when calling the ``write_verilog_testbench`` command.
.. note:: We strongly recommend users to turn on this flag as it can help simulators to converge quickly.
.. 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.
- ```define ICARUS_SIMULATOR`` When enabled, Verilog netlists are generated to be compatible with the syntax required by `icarus iVerilog simulator`__. This flag is added when ``--support_icarus_simulator`` option is enabled when calling the ``write_verilog_testbench`` command.
.. warning:: Please disable this flag if you are not using icarus iVerilog simulator.
__ iverilog_website_
.. _iverilog_website: http://iverilog.icarus.com/
.. option:: <bench_name>_autocheck_top_tb.v
This is the netlist for full testbench.
@ -88,7 +114,7 @@ Inside the directory, the Verilog testbenches are organized as illustrated in :n
.. _fig_preconfig_module:
.. figure:: ./figures/preconfig_module.png
:scale: 100%
:scale: 25%
Internal structure of a pre-configured FPGA module

View File

@ -11,8 +11,6 @@ To launch OpenFPGA shell, users can choose two modes.
Launch OpenFPGA in interactive mode where users type-in command by command and get runtime results
.. warning:: Currently OpenFPGA does not support continued lines and comments
.. option:: --file or -f
Launch OpenFPGA in script mode where users write commands in scripts and FPGA will execute them

View File

@ -29,10 +29,14 @@ write_verilog_testbench
- ``--file`` or ``-f`` The output directory for all the testbench netlists. We suggest the use of same output directory as fabric Verilog netlists
- ``--fabric_netlist_file_path`` Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names.
- ``--reference_benchmark_file_path`` Must specify the reference benchmark Verilog file if you want to output any testbenches
- ``--fast_configuration`` Enable fast configuration phase for the top-level testbench in order to reduce runtime of simulations. It is applicable to configuration chain, memory bank and frame-based configuration protocols. For configuration chain, when enabled, the zeros at the head of the bitstream will be skipped. For memory bank and frame-based, when enabled, all the zero configuration bits will be skipped. So ensure that your memory cells can be correctly reset to zero with a reset signal.
.. note:: If both reset and set ports are defined in the circuit modeling for programming, OpenFPGA will pick the one that will bring largest benefit in speeding up configuration.
- ``--print_top_testbench`` Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
- ``--print_formal_verification_top_netlist`` Generate a top-level module which can be used in formal verification

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 171 KiB

View File

Before

Width:  |  Height:  |  Size: 273 KiB

After

Width:  |  Height:  |  Size: 273 KiB

View File

@ -0,0 +1,9 @@
.. _overview:
Overview
.. toctree::
:maxdepth: 2
motivation
tech_highlights

View File

@ -27,12 +27,43 @@ The rest of this section will focus on detailed motivation on each of them, as d
Design flows in different purposes using OpenFPGA
Fully Customizable Architecture
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OpenFPGA supports VPR's architecture description language, which allows
users to define versatile programmable fabrics down to point-to-point
interconnection.
OpenFPGA leverage VPR's architecture description by introducing an XML-based
architecture annotation, enabling fully customizable FPGA fabric down to
circuit elements.
As illustrated in :ref:`fig_openfpga_arch_lang_coverage`, OpenFPGA's
architecture annotation covers a complete FPGA fabric, including both the
programmable fabric and the configuration peripheral.
.. _fig_openfpga_arch_lang_coverage:
.. figure:: ./figures/openfpga_arch_lang_coverage.png
:scale: 15%
:alt: OpenFPGA architecture description language enabling fully customizable FPGA architecture and circuit-level implementation
OpenFPGA architecture description language enabling fully customizable FPGA architecture and circuit-level implementation
The technical details can be found in our TVLSI'19 paper :cite:`XTang_TVLSI_2019` and FPL'19 paper :cite:`XTang_FPL_2019`.
FPGA-Verilog
~~~~~~~~~~~~
Driven by the strong need in data processing applications, Field Programmable Gate Arrays (FPGAs) are playing an ever-increasing role as programmable accelerators in modern
computing systems. To fully unlock processing capabilities for domain-specific applications, FPGA architectures have to be tailored for seamless cooperation with other computing resources. However, prototyping and bringing to production a customized FPGA is a costly and complex endeavor even for industrial vendors. OpenFPGA, an opensource framework, aims to rapid prototype of customizable FPGA architectures through a semi-custom design approach. We propose an XML-to-Prototype design flow, where the Verilog netlists of a full FPGA fabric can be autogenerated using an extension of the XML language from the VTR framework and then fed into a back-end flow to generate production-ready layouts.
FPGA-Verilog is designed to output flexible and standard Verilog netlists, enabling various backend choices, as illustrated in :ref:`fig_fpga_verilog_motivation`.
.. _fig_fpga_verilog_motivation:
.. figure:: ./figures/fpga_verilog_motivation.png
:scale: 25%
:alt: Flexible netlist format support by FPGA-Verilog to enable various backend choices
FPGA-Verilog enabling flexible backend flows
The technical details can be found in our TVLSI'19 paper :cite:`XTang_TVLSI_2019` and FPL'19 paper :cite:`XTang_FPL_2019`.
@ -41,7 +72,18 @@ FPGA-SDC
Design constraints are indepensible in modern ASIC design flows to guarantee the performance level.
OpenFPGA includes a rich SDC generator in the OpenFPGA framework to deal with both PnR constraints and sign-off timing analysis.
Our flow automatically generates two sets of SDC files. The first set of SDC is designed for the P&R flow, where all the combinational loops are broken to enable wellcontrolled timing-driven P&R. In addition, there are SDC files devoted to constrain pin-to-pin timing for all the resources in FPGAs, in order to obtain nicely constrained and homogeneous delays across the fabric. The second set of SDC is designed for the timing analysis of a benchmark at the post P&R stage.
Our flow automatically generates two sets of SDC files.
- The first set of SDC is designed for the P&R flow, where all the combinational loops are broken to enable wellcontrolled timing-driven P&R. In addition, there are SDC files devoted to constrain pin-to-pin timing for all the resources in FPGAs, in order to obtain nicely constrained and homogeneous delays across the fabric. OpenFPGA allows users to define timing constraints in the architecture description and outputs timing constraints in standard format, enabling fully timing constrained backend flow (see :ref:`fig_fpga_sdc_motivation`).
- The second set of SDC is designed for the timing analysis of a benchmark at the post P&R stage.
.. _fig_fpga_sdc_motivation:
.. figure:: ./figures/fpga_sdc_motivation.png
:scale: 25%
:alt: FPGA-SDC enabling iterative timing constrained backend flow
FPGA-SDC enabling iterative timing constrained backend flow
The technical details can be found in our FPL'19 paper :cite:`XTang_FPL_2019`.

View File

@ -0,0 +1,98 @@
Technical Highlights
--------------------
The follow lists of technical features are created to help users spot their needs in customizing FPGA fabrics.(**as of October 2020**)
Supported Circuit Designs
~~~~~~~~~~~~~~~~~~~~~~~~~
+---------------+-----------------+--------------+-----------------------------------------------------+
| Circuit Types | Auto-generation | User-Defined | Design Topologies |
+===============+=================+==============+=====================================================+
| Inverter | Yes | Yes | - :ref:`circuit_model_power_gated_inverter_example` |
| | | | - :ref:`circuit_model_inverter_1x_example` |
| | | | - :ref:`circuit_model_tapered_inv_16x_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| Buffer | Yes | Yes | - :ref:`circuit_model_buffer_2x_example` |
| | | | - :ref:`circuit_model_power_gated_buffer_example` |
| | | | - :ref:`circuit_model_tapered_buffer_64x_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| AND gate | Yes | Yes | - :ref:`circuit_model_and2_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| OR gate | Yes | Yes | - :ref:`circuit_model_or2_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| MUX2 gate | Yes | Yes | - :ref:`circuit_model_mux2_gate_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| Pass gate | Yes | Yes | - :ref:`circuit_model_tgate_example` |
| | | | - :ref:`circuit_model_pass_transistor_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| Look-Up Table | Yes | Yes | - **Any size** |
| | | | - :ref:`circuit_model_single_output_lut_example` |
| | | | - :ref:`circuit_model_frac_lut_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| Routing | Yes | No | - **Any size** |
| Multiplexer | | | - :ref:`circuit_model_mux_multilevel_example` |
| | | | - :ref:`circuit_model_mux_1level_example` |
| | | | - :ref:`circuit_model_mux_tree_example` |
| | | | - :ref:`circuit_model_mux_stdcell_example` |
| | | | - :ref:`circuit_model_mux_local_encoder_example` |
| | | | - :ref:`circuit_model_mux_const_input_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| Configurable | No | Yes | - :ref:`circuit_model_config_latch_example` |
| Memory | | | - :ref:`circuit_model_sram_blwl_example` |
| | | | - :ref:`circuit_model_dff_example` |
| | | | - :ref:`circuit_model_ccff_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| Block RAM | No | Yes | - **Any size** |
| | | | - Single-port |
| | | | - Dual-port |
| | | | - Fracturable |
+---------------+-----------------+--------------+-----------------------------------------------------+
| Arithmetic | No | Yes | - **Any size** |
| Units | | | - Multiplier |
| | | | - :ref:`circuit_model_full_adder_example` |
+---------------+-----------------+--------------+-----------------------------------------------------+
| I/O | No | Yes | - :ref:`circuit_model_gpio_example` |
| | | | - Bi-directional buffer |
| | | | - AIB |
+---------------+-----------------+--------------+-----------------------------------------------------+
* The user defined netlist could come from a standard cell
Supported FPGA Architectures
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We support most FPGA architectures that VPR can support!
The following are most commonly seen architectural features:
+------------------------+----------------------------------------------+
| Block Type | Architecture features |
+========================+==============================================+
| Programmable Block | - Single-mode Configurable Logic Block (CLB) |
| | - Multi-mode Configurable Logic Block (CLB) |
| | - Single-mode heterogeneous blocks |
| | - Multi-mode heterogeneous blocks |
| | - Flexible local routing architecture |
+------------------------+----------------------------------------------+
| Routing Block | - Tileable routing architecture |
| | - Flexible connectivity |
| | - Flexible Switch Block Patterns |
+------------------------+----------------------------------------------+
| | - Chain-based organization |
| | - Frame-based organization |
| :ref:`config_protocol` | - Memory bank organization |
| | - Flatten organization |
+------------------------+----------------------------------------------+
Supported Verilog Modeling
~~~~~~~~~~~~~~~~~~~~~~~~~~
OpenFPGA supports the following Verilog features in auto-generated netlists for circuit designs
- Synthesizable Behavioral Verilog
- Structural Verilog
- Implicit/Explicit port mapping

View File

@ -23,6 +23,8 @@ In general, please follow the steps to compile
.. note:: recommand to use ``make -j`` to accelerate the compilation
.. note:: VPR's GUI requires gtk-3, and can be enabled with ``cmake .. -DVPR_USE_EZGL=on``
**Quick Compilation Verification**
To quickly verify the tool is well compiled, user can run the following command from OpenFPGA root repository

View File

@ -18,9 +18,9 @@ We will simply execute the following openfpga task-run by
.. code-block:: shell
python3 openfpga_flow/scripts/run_fpga_task.py openfpga_shell/full_testbench/configuration_chain
python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/full_testbench/configuration_chain
Detailed settings, such as architecture XML files and RTL designs, can be found at ``${OPENFPGA_PATH}/openfpga_flow/tasks/openfpga_shell/full_testbench/configuration_chain/config/task.conf``.
Detailed settings, such as architecture XML files and RTL designs, can be found at ``${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/config/task.conf``.
.. note:: ``${OPENFPGA_PATH}`` is the root directory of OpenFPGA
@ -28,7 +28,7 @@ After this task-run, you can find all the generated netlists and testbenches at
.. code-block:: shell
${OPENFPGA_PATH}/openfpga_flow/tasks/openfpga_shell/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/
${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/
.. note:: See :ref:`fabric_netlists` and :ref:`fpga_verilog_testbench` for the netlist details.
@ -43,7 +43,7 @@ The simulation results are logged in
.. code-block:: shell
${OPENFPGA_PATH}/openfpga_flow/tasks/openfpga_shell/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/vvp_sim_output.txt
${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/vvp_sim_output.txt
If the verification passed, you should be able to see ``Simulation Succeed`` in the log file.
@ -53,7 +53,7 @@ To visualize the waveforms, you can use the `GTKWave
.. code-block:: shell
gtkwave ${OPENFPGA_PATH}/openfpga_flow/tasks/openfpga_shell/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/and2_formal.vcd &
gtkwave ${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/and2_formal.vcd &
Manual Method
^^^^^^^^^^^^^
@ -62,7 +62,7 @@ If you want to run iVerilog simulation manually, you can follow these steps:
.. code-block:: shell
cd ${OPENFPGA_PATH}/openfpga_flow/tasks/openfpga_shell/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH
cd ${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH
source iverilog_output.txt
@ -75,7 +75,7 @@ If you want to apply full visibility to the signals, you need to change the foll
.. code-block:: shell
${OPENFPGA_PATH}/openfpga_flow/tasks/openfpga_shell/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/and2_autocheck_top_tb.v
${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/and2_autocheck_top_tb.v
from
@ -94,19 +94,21 @@ Run Modelsim Simulation
~~~~~~~~~~~~~~~~~~~~~~~
Alternatively, you can run Modelsim simulations through openfpga_flow scripts or manually.
.. note:: Before starting, please ensure that Mentor Modelsim has been correctly installed on your local environment.
Through OpenFPGA Scripts
^^^^^^^^^^^^^^^^^^^^^^^^
You can simply call the python script in the following line:
.. code-block:: shell
python3 openfpga_flow/scripts/run_modelsim.py openfpga_shell/full_testbench/configuration_chain --run_sim
python3 openfpga_flow/scripts/run_modelsim.py basic_tests/full_testbench/configuration_chain --run_sim
The script will automatically create a Modelsim project at
.. code-block:: shell
${OPENFPGA_PATH}/openfpga_flow/tasks/openfpga_shell/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/MSIM2/
${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/MSIM2/
and run the simulation.
@ -131,7 +133,7 @@ Create a folder ``MSIM`` under
.. code-block:: shell
${OPENFPGA_PATH}/openfpga_flow/tasks/openfpga_shell/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/
${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/
Under the ``MSIM`` folder, create symbolic links to ``SRC`` folder and reference benchmarks by
@ -149,7 +151,7 @@ Add the following file to your project:
.. code-block:: shell
${OPENFPGA_PATH}/openfpga_flow/tasks/openfpga_shell/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/and2_include_netlists.v
${OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/full_testbench/configuration_chain/latest/k4_N4_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH/SRC/and2_include_netlists.v
Compile the netlists, create a simulation configuration and specify ``and2_autocheck_top_tb`` at the top unit.

View File

@ -1,18 +0,0 @@
.. _eda_flow:
Supported EDA flows in OpenFPGA
-------------------------------
As illustrated in :numref:`fig_eda_flow`, FPGA-SPICE creates a modified VTR flow. All the input files for VPR do not need modifications except the architecture description XML. As simulation-based power analysis requires the transistor-level netlists, we extend the architecture description language to support transistor-level modeling (See details in "Tools Guide>Extended Architecture Description Language"). FPGA-SPICE, embedded in VPR, outputs the SPICE netlists and testbenches according to placement and routing results when enabled by command-line options. (See each "FPGA-*Branch*" about command-line options available) Besides automatically generating all the SPICE netlists, FPGA-SPICE supports user-defined SPICE netlists for modules. We believe the support on user-defined SPICE netlists allows FPGA-SPICE to be general enough to support novel circuit designs and even technologies. (See "FPGA-SPICE... > Create Customized SPICE Modules" for guidelines in customizing your FPGA-SPICE compatible SPICE netlists.) With the dumped SPICE netlists and testbenches, a SPICE simulator, i.e., HSPICE, can be called to conduct a power analysis. FPGA-SPICE automatically generates a shell script, which brings convenience for users to run all the simulations (See "FPGA-SPICE... > Run SPICE simulation").
.. _fig_eda_flow:
.. figure:: ./figures/eda_flow.png
:scale: 50%
:alt: map to buried treasure
Detailed EDA flows based on FPGA-SPICE/Verilog/Bitstream in the purpose of (a) architecture of the output of FPGA-SPICE (b) functionality verification; (c) prototyping and area analysis and (d) power analysis. *TBD: change for Yosys*
FPGA-Verilog is the part of the flow in charge of the Verilog and the semi-custom design flow. In our case, we use Cadence Innovus. The goal is to get the full-FPGA layout to complete the analysis provided by FPGA-SPICE. By having the layout, we can get an area analysis on the one hand and have new information concerning the power analysis. For instance, having the layout allows the user to have new information on the circuit such as the parasitics.
FPGA-Bitstream is the part of the flow in charge of the functional verification of the produced FPGA. Testbenches are generated by FPGA-Verilog and are combined with the full FPGA fabric in Modelsim. A bitstream is generated at the same time as the testbenches. This bitstream configures the FPGA with the functionality given by the user to VPR at the beginning of the flow. First, we configure the FPGA with the bitstream, and then waveforms are sent onto the I/O pads to check the functionality.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 KiB

View File

@ -6,7 +6,7 @@
compile
eda_flow
tools
design_flow/index

View File

@ -0,0 +1,49 @@
.. _openfpga_tools:
Supported Tools
---------------
Internal Tools
^^^^^^^^^^^^^^
To enable various design purposes, OpenFPGA integrates several tools to i.e., FPGA-Verilog, FPGA-SDC and FPGA-bitstream (highlighted green in :ref:`fig_openfpga_tools`, with other popular open-source EDA tools, i.e., VPR and Yosys.
.. _fig_openfpga_tools:
.. figure:: figures/openfpga_tools.png
:scale: 25%
:alt: map to buried treasure
OpenFPGA tool suites and design flows
Third-Party Tools
^^^^^^^^^^^^^^^^^
OpenFPGA accepts and outputs in standard file formats, and therefore can
interface a wide range of commercial and open-source tools.
+--------------+-------------------------+---------------------+
| Usage | Tools | Version Requirement |
+==============+=========================+=====================+
| Backend | Synopsys IC Compiler II | v2019.03 or later |
| | | |
| | Cadence Innovus | v19.1 or later |
+--------------+-------------------------+---------------------+
| Timing | Synopsys PrimeTime | v2019.03 or later |
| Analyzer | | |
| | Cadence Tempus | v19.15 or later |
+--------------+-------------------------+---------------------+
| Verification | Synopsys VCS | v2019.06 or later |
| | | |
| | Synopsys Formality | v2019.03 or later |
| | | |
| | Mentor ModelSim | v10.6 or later |
| | | |
| | Mentor QuestaSim | v2019.3 or later |
| | | |
| | Cadence NCSim | v15.2 or later |
| | | |
| | Icarus iVerilog | v10.1 or later |
+--------------+-------------------------+---------------------+
* The version requirements is based on our local tests. Older versions may work.

View File

@ -299,10 +299,11 @@ size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib,
1, 1, true);
/* Check if we have output */
/* Check if we have 1 or 2 outputs */
size_t num_output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true).size();
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
CIRCUIT_MODEL_PORT_OUTPUT,
2, 1, false);
num_output_ports, 1, false);
return num_err;
}
@ -562,6 +563,81 @@ int check_power_gated_circuit_models(const CircuitLibrary& circuit_lib) {
return num_err;
}
/************************************************************************
* Check io has been defined and has input and output ports
* - We must have global I/O port, either its type is inout, input or output
* - For each IOPAD, we must have at least an input an output
***********************************************************************/
static
size_t check_io_circuit_model(const CircuitLibrary& circuit_lib) {
size_t num_err = 0;
/* Each I/O cell must have
* - One of the following ports
* - At least 1 ASIC-to-FPGA (A2F) port that is defined as global data I/O
* - At least 1 FPGA-to-ASIC (F2A) port that is defined as global data I/O!
* - At least 1 regular port that is non-global which is connected to global routing architecture
*/
for (const auto& io_model : circuit_lib.models_by_type(CIRCUIT_MODEL_IOPAD)) {
bool has_data_io = false;
bool has_data_input_only_io = false;
bool has_data_output_only_io = false;
bool has_internal_connection = false;
for (const auto& port : circuit_lib.model_ports(io_model)) {
if ( (true == circuit_lib.port_is_io(port))
&& (true == circuit_lib.port_is_data_io(port))
&& (CIRCUIT_MODEL_PORT_INOUT == circuit_lib.port_type(port))
&& (true == circuit_lib.port_is_global(port))) {
has_data_io = true;
continue; /* Go to next */
}
if ( (true == circuit_lib.port_is_io(port))
&& (true == circuit_lib.port_is_data_io(port))
&& (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port))
&& (true == circuit_lib.port_is_global(port))) {
has_data_input_only_io = true;
continue; /* Go to next */
}
if ( (true == circuit_lib.port_is_io(port))
&& (true == circuit_lib.port_is_data_io(port))
&& (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port))
&& (true == circuit_lib.port_is_global(port))) {
has_data_output_only_io = true;
continue; /* Go to next */
}
if ( (false == circuit_lib.port_is_io(port)
&& (false == circuit_lib.port_is_global(port)))
&& (CIRCUIT_MODEL_PORT_SRAM != circuit_lib.port_type(port))) {
has_internal_connection = true;
continue; /* Go to next */
}
}
/* Error out when
* - there is no data io, data input-only io and data output-only io
*/
if ( (false == has_data_io)
&& (false == has_data_input_only_io)
&& (false == has_data_output_only_io)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"I/O circuit model '%s' does not have any data I/O port defined!\n",
circuit_lib.model_name(io_model).c_str());
num_err++;
}
if (false == has_internal_connection) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"I/O circuit model '%s' does not have any port connected to FPGA core!\n",
circuit_lib.model_name(io_model).c_str());
num_err++;
}
}
return num_err;
}
/************************************************************************
* Check points to make sure we have a valid circuit library
* Detailed checkpoints:
@ -575,6 +651,10 @@ int check_power_gated_circuit_models(const CircuitLibrary& circuit_lib) {
* 8. FF must have at least a clock, an input and an output ports
* 9. LUT must have at least an input, an output and a SRAM ports
* 10. We must have default circuit models for these types: MUX, channel wires and wires
*
* Note:
* - NO modification on the circuit library is allowed!
* The circuit library should be read-only!!!
***********************************************************************/
bool check_circuit_library(const CircuitLibrary& circuit_lib) {
size_t num_err = 0;
@ -595,20 +675,11 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) {
num_err += check_circuit_library_ports(circuit_lib);
/* 3. Check io has been defined and has input and output ports
* [a] We must have an IOPAD!
* [b] For each IOPAD, we must have at least an input, an output, an INOUT and an SRAM port
* [a] We must have global I/O port, either its type is inout, input or output
* [b] For each IOPAD, we must have at least an input an output
*/
num_err += check_circuit_model_required(circuit_lib, CIRCUIT_MODEL_IOPAD);
std::vector<enum e_circuit_model_port_type> iopad_port_types_required;
iopad_port_types_required.push_back(CIRCUIT_MODEL_PORT_INPUT);
iopad_port_types_required.push_back(CIRCUIT_MODEL_PORT_OUTPUT);
iopad_port_types_required.push_back(CIRCUIT_MODEL_PORT_INOUT);
/* Some I/Os may not have SRAM port, such as AIB interface
* iopad_port_types_required.push_back(CIRCUIT_MODEL_PORT_SRAM);
*/
num_err += check_circuit_model_port_required(circuit_lib, CIRCUIT_MODEL_IOPAD, iopad_port_types_required);
num_err += check_io_circuit_model(circuit_lib);
/* 4. Check mux has been defined and has input and output ports
* [a] We must have a MUX!

View File

@ -907,6 +907,13 @@ bool CircuitLibrary::port_is_io(const CircuitPortId& circuit_port_id) const {
return port_is_io_[circuit_port_id];
}
/* Return a flag if the port is used in mode-selection purpuse of a circuit model */
bool CircuitLibrary::port_is_data_io(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
return port_is_data_io_[circuit_port_id];
}
/* Return a flag if the port is used in mode-selection purpuse of a circuit model */
bool CircuitLibrary::port_is_mode_select(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
@ -942,6 +949,7 @@ bool CircuitLibrary::port_is_config_enable(const CircuitPortId& circuit_port_id)
return port_is_config_enable_[circuit_port_id];
}
/* Return a flag if the port is used during programming a FPGA in a circuit model */
bool CircuitLibrary::port_is_prog(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
@ -1369,6 +1377,7 @@ CircuitPortId CircuitLibrary::add_model_port(const CircuitModelId& model_id,
port_inv_prefix_.emplace_back();
port_default_values_.push_back(-1);
port_is_io_.push_back(false);
port_is_data_io_.push_back(false);
port_is_mode_select_.push_back(false);
port_is_global_.push_back(false);
port_is_reset_.push_back(false);
@ -1448,6 +1457,15 @@ void CircuitLibrary::set_port_is_io(const CircuitPortId& circuit_port_id,
return;
}
/* Set the is_mode_select for a port of a circuit model */
void CircuitLibrary::set_port_is_data_io(const CircuitPortId& circuit_port_id,
const bool& is_data_io) {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
port_is_data_io_[circuit_port_id] = is_data_io;
return;
}
/* Set the is_mode_select for a port of a circuit model */
void CircuitLibrary::set_port_is_mode_select(const CircuitPortId& circuit_port_id,
const bool& is_mode_select) {

View File

@ -79,27 +79,29 @@
* 2. pass_gate_logic_model_id_: specify the id of circuit model for the pass gate logic
*
* ------ Port information ------
* 1. port_ids_: unique id of ports belonging to a circuit model
* 1. port_model_ids_: unique id of the parent circuit model for the port
* 2. port_types_: types of ports belonging to a circuit model
* 3. port_sizes_: width of ports belonging to a circuit model
* 4. port_prefix_: prefix of a port when instance of a circuit model
* 5. port_lib_names_: port name in the standard cell library, only used when explicit_port_mapping is enabled
* 6. port_inv_prefix_: the prefix to be added for the inverted port. This is mainly used by SRAM ports, which have an coupled inverterd port
* 7. port_is_mode_select: specify if this port is used to select operating modes of the circuit model
* 8. port_is_global: specify if this port is a global signal shared by other circuit model
* 9. port_is_reset: specify if this port is a reset signal which needs special pulse widths in testbenches
* 10. port_is_set: specify if this port is a set signal which needs special pulse widths in testbenches
* 11. port_is_config_enable: specify if this port is a config_enable signal which needs special pulse widths in testbenches
* 12. port_is_prog: specify if this port is for FPGA programming use which needs special pulse widths in testbenches
* 13. port_tri_state_model_name: the name of circuit model linked to tri-state the port
* 14. port_tri_state_model_ids_: the Id of circuit model linked to tri-state the port
* 15. port_inv_model_names_: the name of inverter circuit model linked to the port
* 16. port_inv_model_ids_: the Id of inverter circuit model linked to the port
* 17. port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map applied to each pin of this port
* 18. port_lut_frac_level_: only applicable to outputs of LUTs, indicate which level of outputs inside LUT multiplexing structure will be used
* 19. port_lut_output_mask_: only applicable to outputs of LUTs, indicate which output at an internal level of LUT multiplexing structure will be used
* 20. port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will be organized, either memory decoders or scan-chains
* - port_ids_: unique id of ports belonging to a circuit model
* - port_model_ids_: unique id of the parent circuit model for the port
* - port_types_: types of ports belonging to a circuit model
* - port_sizes_: width of ports belonging to a circuit model
* - port_prefix_: prefix of a port when instance of a circuit model
* - port_lib_names_: port name in the standard cell library, only used when explicit_port_mapping is enabled
* - port_inv_prefix_: the prefix to be added for the inverted port. This is mainly used by SRAM ports, which have an coupled inverterd port
* - port_is_mode_select: specify if this port is used to select operating modes of the circuit model
* - port_is_io: specify if this port is an io port
* - port_is_data_io: specify if this port is an io port that can be mapped to a signal from netlist
* - port_is_global: specify if this port is a global signal shared by other circuit model
* - port_is_reset: specify if this port is a reset signal which needs special pulse widths in testbenches
* - port_is_set: specify if this port is a set signal which needs special pulse widths in testbenches
* - port_is_config_enable: specify if this port is a config_enable signal which needs special pulse widths in testbenches
* - port_is_prog: specify if this port is for FPGA programming use which needs special pulse widths in testbenches
* - port_tri_state_model_name: the name of circuit model linked to tri-state the port
* - port_tri_state_model_ids_: the Id of circuit model linked to tri-state the port
* - port_inv_model_names_: the name of inverter circuit model linked to the port
* - port_inv_model_ids_: the Id of inverter circuit model linked to the port
* - port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map applied to each pin of this port
* - port_lut_frac_level_: only applicable to outputs of LUTs, indicate which level of outputs inside LUT multiplexing structure will be used
* - port_lut_output_mask_: only applicable to outputs of LUTs, indicate which output at an internal level of LUT multiplexing structure will be used
* - port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will be organized, either memory decoders or scan-chains
*
* ------ Delay information ------
* 1. delay_types_: type of pin-to-pin delay, either rising_edge of falling_edge
@ -279,6 +281,7 @@ class CircuitLibrary {
std::string port_inv_prefix(const CircuitPortId& circuit_port_id) const;
size_t port_default_value(const CircuitPortId& circuit_port_id) const;
bool port_is_io(const CircuitPortId& circuit_port_id) const;
bool port_is_data_io(const CircuitPortId& circuit_port_id) const;
bool port_is_mode_select(const CircuitPortId& circuit_port_id) const;
bool port_is_global(const CircuitPortId& circuit_port_id) const;
bool port_is_reset(const CircuitPortId& circuit_port_id) const;
@ -354,6 +357,8 @@ class CircuitLibrary {
const size_t& default_val);
void set_port_is_io(const CircuitPortId& circuit_port_id,
const bool& is_io);
void set_port_is_data_io(const CircuitPortId& circuit_port_id,
const bool& is_data_io);
void set_port_is_mode_select(const CircuitPortId& circuit_port_id,
const bool& is_mode_select);
void set_port_is_global(const CircuitPortId& circuit_port_id,
@ -545,6 +550,7 @@ class CircuitLibrary {
vtr::vector<CircuitPortId, std::string> port_inv_prefix_;
vtr::vector<CircuitPortId, size_t> port_default_values_;
vtr::vector<CircuitPortId, bool> port_is_io_;
vtr::vector<CircuitPortId, bool> port_is_data_io_;
vtr::vector<CircuitPortId, bool> port_is_mode_select_;
vtr::vector<CircuitPortId, bool> port_is_global_;
vtr::vector<CircuitPortId, bool> port_is_reset_;

View File

@ -28,6 +28,10 @@ CircuitModelId ConfigProtocol::memory_model() const {
return memory_model_;
}
int ConfigProtocol::num_regions() const {
return num_regions_;
}
/************************************************************************
* Public Mutators
***********************************************************************/
@ -42,3 +46,7 @@ void ConfigProtocol::set_memory_model_name(const std::string& memory_model_name)
void ConfigProtocol::set_memory_model(const CircuitModelId& memory_model) {
memory_model_ = memory_model;
}
void ConfigProtocol::set_num_regions(const int& num_regions) {
num_regions_ = num_regions;
}

View File

@ -15,10 +15,12 @@ class ConfigProtocol {
e_config_protocol_type type() const;
std::string memory_model_name() const;
CircuitModelId memory_model() const;
int num_regions() const;
public: /* Public Mutators */
void set_type(const e_config_protocol_type& type);
void set_memory_model_name(const std::string& memory_model_name);
void set_memory_model(const CircuitModelId& memory_model);
void set_num_regions(const int& num_regions);
private: /* Internal data */
/* The type of configuration protocol.
* In other words, it is about how to organize and access each configurable memory
@ -28,6 +30,9 @@ class ConfigProtocol {
/* The circuit model of configuration memory to be used in the protocol */
std::string memory_model_name_;
CircuitModelId memory_model_;
/* Number of configurable regions */
int num_regions_;
};
#endif

View File

@ -9,6 +9,7 @@
#include "simulation_setting.h"
#include "config_protocol.h"
#include "arch_direct.h"
#include "tile_annotation.h"
#include "pb_type_annotation.h"
/* namespace openfpga begins */
@ -51,6 +52,11 @@ struct Arch {
*/
ArchDirect arch_direct;
/* Physical tile annotations:
* Global port definition for tile ports
*/
TileAnnotation tile_annotations;
/* Pb type annotations
* Bind from operating to physical
* Bind from physical to circuit model

View File

@ -26,52 +26,10 @@
*******************************************************************/
static
e_circuit_model_type string_to_circuit_model_type(const std::string& type_string) {
if (std::string("chan_wire") == type_string) {
return CIRCUIT_MODEL_CHAN_WIRE;
}
if (std::string("wire") == type_string) {
return CIRCUIT_MODEL_WIRE;
}
if (std::string("mux") == type_string) {
return CIRCUIT_MODEL_MUX;
}
if (std::string("lut") == type_string) {
return CIRCUIT_MODEL_LUT;
}
if (std::string("ff") == type_string) {
return CIRCUIT_MODEL_FF;
}
if (std::string("sram") == type_string) {
return CIRCUIT_MODEL_SRAM;
}
if (std::string("hard_logic") == type_string) {
return CIRCUIT_MODEL_HARDLOGIC;
}
if (std::string("ccff") == type_string) {
return CIRCUIT_MODEL_CCFF;
}
if (std::string("iopad") == type_string) {
return CIRCUIT_MODEL_IOPAD;
}
if (std::string("inv_buf") == type_string) {
return CIRCUIT_MODEL_INVBUF;
}
if (std::string("pass_gate") == type_string) {
return CIRCUIT_MODEL_PASSGATE;
}
if (std::string("gate") == type_string) {
return CIRCUIT_MODEL_GATE;
for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_TYPES; ++itype) {
if (std::string(CIRCUIT_MODEL_TYPE_STRING[itype]) == type_string) {
return static_cast<e_circuit_model_type>(itype);
}
}
/* Reach here, we have an invalid value, error out */
@ -83,12 +41,10 @@ e_circuit_model_type string_to_circuit_model_type(const std::string& type_string
*******************************************************************/
static
e_circuit_model_design_tech string_to_design_tech_type(const std::string& type_string) {
if (std::string("cmos") == type_string) {
return CIRCUIT_MODEL_DESIGN_CMOS;
}
if (std::string("rram") == type_string) {
return CIRCUIT_MODEL_DESIGN_RRAM;
for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES; ++itype) {
if (std::string(CIRCUIT_MODEL_DESIGN_TECH_TYPE_STRING[itype]) == type_string) {
return static_cast<e_circuit_model_design_tech>(itype);
}
}
return NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES;
@ -99,12 +55,10 @@ e_circuit_model_design_tech string_to_design_tech_type(const std::string& type_s
*******************************************************************/
static
e_circuit_model_buffer_type string_to_buffer_type(const std::string& type_string) {
if (std::string("inverter") == type_string) {
return CIRCUIT_MODEL_BUF_INV;
}
if (std::string("buffer") == type_string) {
return CIRCUIT_MODEL_BUF_BUF;
for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_BUF_TYPES; ++itype) {
if (std::string(CIRCUIT_MODEL_BUFFER_TYPE_STRING[itype]) == type_string) {
return static_cast<e_circuit_model_buffer_type>(itype);
}
}
return NUM_CIRCUIT_MODEL_BUF_TYPES;
@ -115,12 +69,10 @@ e_circuit_model_buffer_type string_to_buffer_type(const std::string& type_string
*******************************************************************/
static
e_circuit_model_pass_gate_logic_type string_to_passgate_type(const std::string& type_string) {
if (std::string("transmission_gate") == type_string) {
return CIRCUIT_MODEL_PASS_GATE_TRANSMISSION;
}
if (std::string("pass_transistor") == type_string) {
return CIRCUIT_MODEL_PASS_GATE_TRANSISTOR;
for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_PASS_GATE_TYPES; ++itype) {
if (std::string(CIRCUIT_MODEL_PASSGATE_TYPE_STRING[itype]) == type_string) {
return static_cast<e_circuit_model_pass_gate_logic_type>(itype);
}
}
return NUM_CIRCUIT_MODEL_PASS_GATE_TYPES;
@ -131,16 +83,10 @@ e_circuit_model_pass_gate_logic_type string_to_passgate_type(const std::string&
*******************************************************************/
static
e_circuit_model_structure string_to_mux_structure_type(const std::string& type_string) {
if (std::string("tree") == type_string) {
return CIRCUIT_MODEL_STRUCTURE_TREE;
}
if (std::string("one_level") == type_string) {
return CIRCUIT_MODEL_STRUCTURE_ONELEVEL;
}
if (std::string("multi_level") == type_string) {
return CIRCUIT_MODEL_STRUCTURE_MULTILEVEL;
for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_STRUCTURE_TYPES; ++itype) {
if (std::string(CIRCUIT_MODEL_STRUCTURE_TYPE_STRING[itype]) == type_string) {
return static_cast<e_circuit_model_structure>(itype);
}
}
return NUM_CIRCUIT_MODEL_STRUCTURE_TYPES;
@ -151,16 +97,10 @@ e_circuit_model_structure string_to_mux_structure_type(const std::string& type_s
*******************************************************************/
static
e_circuit_model_gate_type string_to_gate_type(const std::string& type_string) {
if (std::string("AND") == type_string) {
return CIRCUIT_MODEL_GATE_AND;
}
if (std::string("OR") == type_string) {
return CIRCUIT_MODEL_GATE_OR;
}
if (std::string("MUX2") == type_string) {
return CIRCUIT_MODEL_GATE_MUX2;
for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_GATE_TYPES; ++itype) {
if (std::string(CIRCUIT_MODEL_GATE_TYPE_STRING[itype]) == type_string) {
return static_cast<e_circuit_model_gate_type>(itype);
}
}
return NUM_CIRCUIT_MODEL_GATE_TYPES;
@ -171,40 +111,10 @@ e_circuit_model_gate_type string_to_gate_type(const std::string& type_string) {
*******************************************************************/
static
e_circuit_model_port_type string_to_circuit_model_port_type(const std::string& type_string) {
if (std::string("input") == type_string) {
return CIRCUIT_MODEL_PORT_INPUT;
}
if (std::string("output") == type_string) {
return CIRCUIT_MODEL_PORT_OUTPUT;
}
if (std::string("clock") == type_string) {
return CIRCUIT_MODEL_PORT_CLOCK;
}
if (std::string("sram") == type_string) {
return CIRCUIT_MODEL_PORT_SRAM;
}
if (std::string("bl") == type_string) {
return CIRCUIT_MODEL_PORT_BL;
}
if (std::string("wl") == type_string) {
return CIRCUIT_MODEL_PORT_WL;
}
if (std::string("blb") == type_string) {
return CIRCUIT_MODEL_PORT_BLB;
}
if (std::string("wlb") == type_string) {
return CIRCUIT_MODEL_PORT_WLB;
}
if (std::string("inout") == type_string) {
return CIRCUIT_MODEL_PORT_INOUT;
for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_PORT_TYPES; ++itype) {
if (std::string(CIRCUIT_MODEL_PORT_TYPE_STRING[itype]) == type_string) {
return static_cast<e_circuit_model_port_type>(itype);
}
}
return NUM_CIRCUIT_MODEL_PORT_TYPES;
@ -215,12 +125,10 @@ e_circuit_model_port_type string_to_circuit_model_port_type(const std::string& t
*******************************************************************/
static
e_wire_model_type string_to_wire_model_type(const std::string& type_string) {
if (std::string("pi") == type_string) {
return WIRE_MODEL_PI;
}
if (std::string("t") == type_string) {
return WIRE_MODEL_T;
for (size_t itype = 0; itype < NUM_WIRE_MODEL_TYPES; ++itype) {
if (std::string(WIRE_MODEL_TYPE_STRING[itype]) == type_string) {
return static_cast<e_wire_model_type>(itype);
}
}
return NUM_WIRE_MODEL_TYPES;
@ -231,12 +139,10 @@ e_wire_model_type string_to_wire_model_type(const std::string& type_string) {
*******************************************************************/
static
e_circuit_model_delay_type string_to_circuit_model_delay_type(const std::string& type_string) {
if (std::string("rise") == type_string) {
return CIRCUIT_MODEL_DELAY_RISE;
}
if (std::string("fall") == type_string) {
return CIRCUIT_MODEL_DELAY_FALL;
for (size_t itype = 0; itype < NUM_CIRCUIT_MODEL_DELAY_TYPES; ++itype) {
if (std::string(CIRCUIT_MODEL_DELAY_TYPE_STRING[itype]) == type_string) {
return static_cast<e_circuit_model_delay_type>(itype);
}
}
return NUM_CIRCUIT_MODEL_DELAY_TYPES;
@ -512,6 +418,13 @@ void read_xml_circuit_port(pugi::xml_node& xml_port,
*/
circuit_lib.set_port_is_io(port, get_attribute(xml_port, "is_io", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
/* Identify if the port is a data io, ONLY applicable to I/O port
* By default, it will NOT be a data io port
*/
if (true == circuit_lib.port_is_io(port)) {
circuit_lib.set_port_is_data_io(port, get_attribute(xml_port, "is_data_io", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
}
/* Identify if the port is for mode selection, this is only applicable to SRAM ports.
* By default, it will NOT be a mode selection port
*/

View File

@ -23,20 +23,11 @@
*******************************************************************/
static
e_config_protocol_type string_to_config_protocol_type(const std::string& type_string) {
if (std::string("standalone") == type_string) {
return CONFIG_MEM_STANDALONE;
}
if (std::string("scan_chain") == type_string) {
return CONFIG_MEM_SCAN_CHAIN;
}
if (std::string("memory_bank") == type_string) {
return CONFIG_MEM_MEMORY_BANK;
}
if (std::string("frame_based") == type_string) {
return CONFIG_MEM_FRAME_BASED;
for (size_t itype = 0; itype < NUM_CONFIG_PROTOCOL_TYPES; ++itype) {
if (std::string(CONFIG_PROTOCOL_TYPE_STRING[itype]) == type_string) {
return static_cast<e_config_protocol_type>(itype);
}
}
return NUM_CONFIG_PROTOCOL_TYPES;
@ -62,8 +53,18 @@ void read_xml_config_organization(pugi::xml_node& xml_config_orgz,
config_protocol.set_type(config_orgz_type);
/* Find the circuit model used by the configuration protocol */
config_protocol.set_memory_model_name(get_attribute(xml_config_orgz, "circuit_model_name", loc_data).as_string());
/* Parse the number of configurable regions
* At least 1 region should be defined, otherwise error out
*/
config_protocol.set_num_regions(get_attribute(xml_config_orgz, "num_regions", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1));
if (1 > config_protocol.num_regions()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_config_orgz),
"Invalid 'num_region=%d' definition. At least 1 region should be defined!\n",
config_protocol.num_regions());
}
}
/********************************************************************

View File

@ -21,6 +21,7 @@
#include "read_xml_simulation_setting.h"
#include "read_xml_config_protocol.h"
#include "read_xml_routing_circuit.h"
#include "read_xml_tile_annotation.h"
#include "read_xml_pb_type_annotation.h"
#include "read_xml_openfpga_arch.h"
#include "openfpga_arch_linker.h"
@ -103,6 +104,9 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) {
openfpga_arch.arch_direct = read_xml_direct_circuit(xml_openfpga_arch, loc_data,
openfpga_arch.circuit_lib);
/* Parse the pb_type annotation */
openfpga_arch.tile_annotations = read_xml_tile_annotations(xml_openfpga_arch, loc_data);
/* Parse the pb_type annotation */
openfpga_arch.pb_type_annotations = read_xml_pb_type_annotations(xml_openfpga_arch, loc_data);

View File

@ -23,12 +23,10 @@
*******************************************************************/
static
e_sim_accuracy_type string_to_sim_accuracy_type(const std::string& type_string) {
if (std::string("frac") == type_string) {
return SIM_ACCURACY_FRAC;
}
if (std::string("abs") == type_string) {
return SIM_ACCURACY_ABS;
for (size_t itype = 0; itype < NUM_SIM_ACCURACY_TYPES; ++itype) {
if (std::string(SIM_ACCURACY_TYPE_STRING[itype]) == type_string) {
return static_cast<e_sim_accuracy_type>(itype);
}
}
return NUM_SIM_ACCURACY_TYPES;

View File

@ -23,12 +23,10 @@
*******************************************************************/
static
e_tech_lib_model_type string_to_device_model_type(const std::string& type_string) {
if (std::string("transistor") == type_string) {
return TECH_LIB_MODEL_TRANSISTOR;
}
if (std::string("rram") == type_string) {
return TECH_LIB_MODEL_RRAM;
for (size_t itype = 0; itype < NUM_TECH_LIB_MODEL_TYPES; ++itype) {
if (std::string(TECH_LIB_MODEL_TYPE_STRING[itype]) == type_string) {
return static_cast<e_tech_lib_model_type>(itype);
}
}
return NUM_TECH_LIB_MODEL_TYPES;
@ -39,12 +37,10 @@ e_tech_lib_model_type string_to_device_model_type(const std::string& type_string
*******************************************************************/
static
e_tech_lib_type string_to_tech_lib_type(const std::string& type_string) {
if (std::string("industry") == type_string) {
return TECH_LIB_INDUSTRY;
}
if (std::string("academia") == type_string) {
return TECH_LIB_ACADEMIA;
for (size_t itype = 0; itype < NUM_TECH_LIB_TYPES; ++itype) {
if (std::string(TECH_LIB_TYPE_STRING[itype]) == type_string) {
return static_cast<e_tech_lib_type>(itype);
}
}
return NUM_TECH_LIB_TYPES;

View File

@ -0,0 +1,107 @@
/********************************************************************
* This file includes the top-level function of this library
* which reads an XML modeling OpenFPGA architecture to the associated
* data structures
*******************************************************************/
#include <string>
/* Headers from pugi XML library */
#include "pugixml.hpp"
#include "pugixml_util.hpp"
/* Headers from vtr util library */
#include "vtr_assert.h"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
/* Headers from libopenfpgautil */
#include "openfpga_tokenizer.h"
#include "openfpga_port_parser.h"
#include "read_xml_tile_annotation.h"
/********************************************************************
* Parse XML description for an interconnection annotation
* under a <global_port> XML node
*******************************************************************/
static
void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile,
const pugiutil::loc_data& loc_data,
openfpga::TileAnnotation& tile_annotation) {
/* We have two mandatory XML attributes
* 1. name of the port
* 2. name of the tile and ports in the format of <tile_name>.<tile_port_name>
*/
const std::string& name_attr = get_attribute(xml_tile, "name", loc_data).as_string();
const std::string& tile_port_name_attr = get_attribute(xml_tile, "tile_port", loc_data).as_string();
/* Extract the tile name */
openfpga::StringToken tokenizer(tile_port_name_attr);
std::vector<std::string> tile_port_tokens = tokenizer.split('.');
if (2 != tile_port_tokens.size()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
"Invalid tile_port attribute '%s'! Valid format is <tile_name>.<port_name>\n",
tile_port_name_attr.c_str());
}
/* Extract the tile port information */
openfpga::PortParser tile_port_parser(tile_port_tokens[1]);
TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr, tile_port_tokens[0], tile_port_parser.port());
/* Report any duplicated port names */
if (TileGlobalPortId::INVALID() == tile_global_port_id) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
"Invalid port name '%s' which is defined more than once in the global port list!\n",
name_attr.c_str());
}
/* Get is_clock attributes */
tile_annotation.set_global_port_is_clock(tile_global_port_id, get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
/* Get is_set attributes */
tile_annotation.set_global_port_is_set(tile_global_port_id, get_attribute(xml_tile, "is_set", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
/* Get is_reset attributes */
tile_annotation.set_global_port_is_reset(tile_global_port_id, get_attribute(xml_tile, "is_reset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
/* Get default_value attributes */
tile_annotation.set_global_port_default_value(tile_global_port_id, get_attribute(xml_tile, "default_value", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0));
/* Ensure valid port attributes */
if (false == tile_annotation.valid_global_port_attributes(tile_global_port_id)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile),
"Invalid port attributes for '%s'! A port can only be clock or set or reset.\n",
name_attr.c_str());
}
}
/********************************************************************
* Top function to parse XML description about tile annotation
*******************************************************************/
openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data) {
openfpga::TileAnnotation tile_annotations;
/* Parse configuration protocol root node */
pugi::xml_node xml_annotations = get_single_child(Node, "tile_annotations", loc_data, pugiutil::ReqOpt::OPTIONAL);
/* Not found, we can return */
if (!xml_annotations) {
return tile_annotations;
}
/* Iterate over the children under this node,
* each child should be named after <pb_type>
*/
for (pugi::xml_node xml_tile_global_port : xml_annotations.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_tile_global_port.name() != std::string("global_port")) {
bad_tag(xml_tile_global_port, loc_data, xml_annotations, {"global_port"});
}
read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data, tile_annotations);
}
return tile_annotations;
}

View File

@ -0,0 +1,17 @@
#ifndef READ_XML_TILE_ANNOTATION_H
#define READ_XML_TILE_ANNOTATION_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "pugixml_util.hpp"
#include "pugixml.hpp"
#include "tile_annotation.h"
/********************************************************************
* Function declaration
*******************************************************************/
openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data);
#endif

View File

@ -0,0 +1,144 @@
/************************************************************************
* Member functions for class TileAnnotation
***********************************************************************/
#include "vtr_assert.h"
#include "tile_annotation.h"
/* namespace openfpga begins */
namespace openfpga {
/************************************************************************
* Constructors
***********************************************************************/
TileAnnotation::TileAnnotation() {
return;
}
/************************************************************************
* Public Accessors : aggregates
***********************************************************************/
TileAnnotation::global_port_range TileAnnotation::global_ports() const {
return vtr::make_range(global_port_ids_.begin(), global_port_ids_.end());
}
/************************************************************************
* Public Accessors
***********************************************************************/
std::string TileAnnotation::global_port_name(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_names_[global_port_id];
}
std::string TileAnnotation::global_port_tile_name(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_tile_names_[global_port_id];
}
BasicPort TileAnnotation::global_port_tile_port(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_tile_ports_[global_port_id];
}
bool TileAnnotation::global_port_is_clock(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_clock_[global_port_id];
}
bool TileAnnotation::global_port_is_set(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_set_[global_port_id];
}
bool TileAnnotation::global_port_is_reset(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_is_reset_[global_port_id];
}
size_t TileAnnotation::global_port_default_value(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
return global_port_default_values_[global_port_id];
}
/************************************************************************
* Public Mutators
***********************************************************************/
TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name,
const std::string& tile_name,
const BasicPort& tile_port) {
/* Ensure that the name is unique */
std::map<std::string, TileGlobalPortId>::iterator it = global_port_name2ids_.find(port_name);
if (it != global_port_name2ids_.end()) {
return TileGlobalPortId::INVALID();
}
/* This is a legal name. we can create a new id */
TileGlobalPortId port_id = TileGlobalPortId(global_port_ids_.size());
global_port_ids_.push_back(port_id);
global_port_names_.push_back(port_name);
global_port_tile_names_.push_back(tile_name);
global_port_tile_ports_.push_back(tile_port);
global_port_is_clock_.push_back(false);
global_port_is_set_.push_back(false);
global_port_is_reset_.push_back(false);
global_port_default_values_.push_back(0);
/* Register in the name-to-id map */
global_port_name2ids_[port_name] = port_id;
return port_id;
}
void TileAnnotation::set_global_port_is_clock(const TileGlobalPortId& global_port_id,
const bool& is_clock) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_clock_[global_port_id] = is_clock;
}
void TileAnnotation::set_global_port_is_set(const TileGlobalPortId& global_port_id,
const bool& is_set) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_set_[global_port_id] = is_set;
}
void TileAnnotation::set_global_port_is_reset(const TileGlobalPortId& global_port_id,
const bool& is_reset) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_is_reset_[global_port_id] = is_reset;
}
void TileAnnotation::set_global_port_default_value(const TileGlobalPortId& global_port_id,
const size_t& default_value) {
VTR_ASSERT(valid_global_port_id(global_port_id));
global_port_default_values_[global_port_id] = default_value;
}
/************************************************************************
* Internal invalidators/validators
***********************************************************************/
/* Validators */
bool TileAnnotation::valid_global_port_id(const TileGlobalPortId& global_port_id) const {
return ( size_t(global_port_id) < global_port_ids_.size() ) && ( global_port_id == global_port_ids_[global_port_id] );
}
bool TileAnnotation::valid_global_port_attributes(const TileGlobalPortId& global_port_id) const {
VTR_ASSERT(valid_global_port_id(global_port_id));
int attribute_counter = 0;
if (true == global_port_is_clock_[global_port_id]) {
attribute_counter++;
}
if (true == global_port_is_reset_[global_port_id]) {
attribute_counter++;
}
if (true == global_port_is_set_[global_port_id]) {
attribute_counter++;
}
return ((0 == attribute_counter) || (1 == attribute_counter));
}
} /* namespace openfpga ends */

View File

@ -0,0 +1,86 @@
#ifndef TILE_ANNOTATION_H
#define TILE_ANNOTATION_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <vector>
#include <map>
#include <array>
#include "vtr_vector.h"
#include "openfpga_port.h"
#include "tile_annotation_fwd.h"
/* namespace openfpga begins */
namespace openfpga {
/********************************************************************
* This file include the declaration of data structures
* to store physical tile annotation, including
* 1. global port definition where a tile port can be treated as a
* global port of the FPGA fabric
*
* Note:
* 1. Keep this data structure as general as possible. It is supposed
* to contain the raw data from architecture XML! If you want to link
* to other data structures, please create another one in other header files
*******************************************************************/
class TileAnnotation {
public: /* Types */
typedef vtr::vector<TileGlobalPortId, TileGlobalPortId>::const_iterator global_port_iterator;
/* Create range */
typedef vtr::Range<global_port_iterator> global_port_range;
public: /* Constructor */
TileAnnotation();
public: /* Public accessors: aggregators */
global_port_range global_ports() const;
public: /* Public accessors */
std::string global_port_name(const TileGlobalPortId& global_port_id) const;
std::string global_port_tile_name(const TileGlobalPortId& global_port_id) const;
BasicPort global_port_tile_port(const TileGlobalPortId& global_port_id) const;
bool global_port_is_clock(const TileGlobalPortId& global_port_id) const;
bool global_port_is_set(const TileGlobalPortId& global_port_id) const;
bool global_port_is_reset(const TileGlobalPortId& global_port_id) const;
size_t global_port_default_value(const TileGlobalPortId& global_port_id) const;
public: /* Public mutators */
/* By default, we do not set it as a clock.
* Users should set it through the set_global_port_is_clock() function
*/
TileGlobalPortId create_global_port(const std::string& port_name,
const std::string& tile_name,
const BasicPort& tile_port);
void set_global_port_is_clock(const TileGlobalPortId& global_port_id,
const bool& is_clock);
void set_global_port_is_set(const TileGlobalPortId& global_port_id,
const bool& is_set);
void set_global_port_is_reset(const TileGlobalPortId& global_port_id,
const bool& is_reset);
void set_global_port_default_value(const TileGlobalPortId& global_port_id,
const size_t& default_value);
public: /* Public validator */
bool valid_global_port_id(const TileGlobalPortId& global_port_id) const;
/* Validate attributes of a given global port
* - A port can only be defined as clock or set or reset
*/
bool valid_global_port_attributes(const TileGlobalPortId& global_port_id) const;
private: /* Internal data */
/* Global port information for tiles */
vtr::vector<TileGlobalPortId, TileGlobalPortId> global_port_ids_;
vtr::vector<TileGlobalPortId, std::string> global_port_names_;
vtr::vector<TileGlobalPortId, std::string> global_port_tile_names_;
vtr::vector<TileGlobalPortId, BasicPort> global_port_tile_ports_;
vtr::vector<TileGlobalPortId, bool> global_port_is_clock_;
vtr::vector<TileGlobalPortId, bool> global_port_is_reset_;
vtr::vector<TileGlobalPortId, bool> global_port_is_set_;
vtr::vector<TileGlobalPortId, size_t> global_port_default_values_;
/* A fast lookup for port names */
std::map<std::string, TileGlobalPortId> global_port_name2ids_;
};
} /* namespace openfpga ends */
#endif

View File

@ -0,0 +1,22 @@
/************************************************************************
* A header file for TileAnnotation class, including critical data declaration
* Please include this file only for using any TileAnnotation data structure
* Refer to tile_annotation.h for more details
***********************************************************************/
/************************************************************************
* Create strong id for tile global ports to avoid illegal type casting
***********************************************************************/
#ifndef TILE_ANNOTATION_FWD_H
#define TILE_ANNOTATION_FWD_H
#include "vtr_strong_id.h"
struct tile_global_port_id_tag;
typedef vtr::StrongId<tile_global_port_id_tag> TileGlobalPortId;
/* Short declaration of class */
class TileAnnotation;
#endif

View File

@ -186,6 +186,15 @@ void write_xml_circuit_port(std::fstream& fp,
}
}
/* I/O port attributes */
if (true == circuit_lib.port_is_io(port)) {
write_xml_attribute(fp, "is_io", "true");
}
if (true == circuit_lib.port_is_data_io(port)) {
write_xml_attribute(fp, "is_data_io", "true");
}
/* Global, reset, set port attributes */
if (true == circuit_lib.port_is_global(port)) {
write_xml_attribute(fp, "is_global", "true");

View File

@ -16,6 +16,7 @@
#include "write_xml_simulation_setting.h"
#include "write_xml_config_protocol.h"
#include "write_xml_routing_circuit.h"
#include "write_xml_tile_annotation.h"
#include "write_xml_pb_type_annotation.h"
#include "write_xml_openfpga_arch.h"
@ -59,7 +60,10 @@ void write_xml_openfpga_arch(const char* fname,
write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.arch_direct);
/* Write the pb_type annotations */
openfpga::write_xml_pb_type_annotations(fp, fname, openfpga_arch. pb_type_annotations);
openfpga::write_xml_tile_annotations(fp, fname, openfpga_arch.tile_annotations);
/* Write the pb_type annotations */
openfpga::write_xml_pb_type_annotations(fp, fname, openfpga_arch.pb_type_annotations);
fp << "</openfpga_architecture>" << "\n";

View File

@ -66,6 +66,7 @@ std::string generate_physical_pb_type_hierarchy_name(const PbTypeAnnotation& pb_
}
/********************************************************************
* FIXME: Use a common function to output ports
* Generate the full hierarchy name for a operating pb_type
*******************************************************************/
static

View File

@ -0,0 +1,94 @@
/********************************************************************
* This file includes functions that outputs tile annotations to XML format
*******************************************************************/
/* Headers from system goes first */
#include <string>
#include <algorithm>
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "openfpga_digest.h"
/* Headers from readarchopenfpga library */
#include "write_xml_utils.h"
#include "write_xml_tile_annotation.h"
/* namespace openfpga begins */
namespace openfpga {
/********************************************************************
* FIXME: Use a common function to output ports
* Generate the full hierarchy name for a operating pb_type
*******************************************************************/
static
std::string generate_tile_port_name(const BasicPort& pb_port) {
std::string port_name;
/* Output format: <port_name>[<LSB>:<MSB>] */
port_name += pb_port.get_name();
port_name += std::string("[");
port_name += std::to_string(pb_port.get_lsb());
port_name += std::string(":");
port_name += std::to_string(pb_port.get_msb());
port_name += std::string("]");
return port_name;
}
/********************************************************************
* A writer to output a device variation in a technology library to XML format
*******************************************************************/
static
void write_xml_tile_annotation_global_port(std::fstream& fp,
const char* fname,
const openfpga::TileAnnotation& tile_annotation,
const TileGlobalPortId& global_port_id) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
fp << "\t\t" << "<global_port ";
write_xml_attribute(fp, "name", tile_annotation.global_port_name(global_port_id).c_str());
std::string tile_port_attr = tile_annotation.global_port_tile_name(global_port_id)
+ "."
+ generate_tile_port_name(tile_annotation.global_port_tile_port(global_port_id));
write_xml_attribute(fp, "tile_port", tile_port_attr.c_str());
write_xml_attribute(fp, "is_clock", tile_annotation.global_port_is_clock(global_port_id));
write_xml_attribute(fp, "is_set", tile_annotation.global_port_is_set(global_port_id));
write_xml_attribute(fp, "is_reset", tile_annotation.global_port_is_reset(global_port_id));
write_xml_attribute(fp, "default_value", tile_annotation.global_port_default_value(global_port_id));
fp << "/>" << "\n";
}
/********************************************************************
* A writer to output tile annotations to XML format
*******************************************************************/
void write_xml_tile_annotations(std::fstream& fp,
const char* fname,
const TileAnnotation& tile_annotation) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the root node for pb_type annotations,
* we apply a tab becuase pb_type annotations is just a subnode
* under the root node <openfpga_arch>
*/
fp << "\t" << "<tile_annotations>" << "\n";
/* Write device model one by one */
for (const TileGlobalPortId& global_port_id : tile_annotation.global_ports()) {
write_xml_tile_annotation_global_port(fp, fname, tile_annotation, global_port_id);
}
/* Write the root node for pb_type annotations */
fp << "\t" << "</tile_annotations>" << "\n";
}
} /* namespace openfpga ends */

View File

@ -0,0 +1,22 @@
#ifndef WRITE_XML_TILE_ANNOTATION_H
#define WRITE_XML_TILE_ANNOTATION_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <fstream>
#include "tile_annotation.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* namespace openfpga begins */
namespace openfpga {
void write_xml_tile_annotations(std::fstream& fp,
const char* fname,
const TileAnnotation& tile_annotation);
} /* namespace openfpga ends */
#endif

View File

@ -1,7 +1,9 @@
<fabric_key>
<key id="0" name="sb" value="0"/>
<key id="2" name="cb" value="10"/>
<key id="1" name="sb" value="7"/>
<key id="3" name="clb" value="53"/>
<key id="4" name="bram" value="32"/>
<region id="0">
<key id="0" name="sb" value="0"/>
<key id="2" name="cb" value="10"/>
<key id="1" name="sb" value="7"/>
<key id="3" name="clb" value="53"/>
<key id="4" name="bram" value="32"/>
</region>
</fabric_key>

View File

@ -1,4 +1,7 @@
#include <algorithm>
#include "vtr_assert.h"
#include "vtr_log.h"
#include "fabric_key.h"
@ -20,24 +23,31 @@ FabricKey::fabric_key_range FabricKey::keys() const {
return vtr::make_range(key_ids_.begin(), key_ids_.end());
}
FabricKey::fabric_region_range FabricKey::regions() const {
return vtr::make_range(region_ids_.begin(), region_ids_.end());
}
/************************************************************************
* Public Accessors : Basic data query
***********************************************************************/
/* Access the name of a key */
std::vector<FabricKeyId> FabricKey::region_keys(const FabricRegionId& region_id) const {
/* validate the region_id */
VTR_ASSERT(valid_region_id(region_id));
return region_key_ids_[region_id];
}
std::string FabricKey::key_name(const FabricKeyId& key_id) const {
/* validate the key_id */
VTR_ASSERT(valid_key_id(key_id));
return key_names_[key_id];
}
/* Access the value of a key */
size_t FabricKey::key_value(const FabricKeyId& key_id) const {
/* validate the key_id */
VTR_ASSERT(valid_key_id(key_id));
return key_values_[key_id];
}
/* Access the alias of a key */
std::string FabricKey::key_alias(const FabricKeyId& key_id) const {
/* validate the key_id */
VTR_ASSERT(valid_key_id(key_id));
@ -51,20 +61,78 @@ bool FabricKey::empty() const {
/************************************************************************
* Public Mutators
***********************************************************************/
void FabricKey::reserve_regions(const size_t& num_regions) {
region_ids_.reserve(num_regions);
region_key_ids_.reserve(num_regions);
}
FabricRegionId FabricKey::create_region() {
/* Create a new id */
FabricRegionId region = FabricRegionId(region_ids_.size());
region_ids_.push_back(region);
region_key_ids_.emplace_back();
return region;
}
void FabricKey::reserve_region_keys(const FabricRegionId& region_id,
const size_t& num_keys) {
/* validate the region_id */
VTR_ASSERT(valid_region_id(region_id));
region_key_ids_[region_id].reserve(num_keys);
}
void FabricKey::add_key_to_region(const FabricRegionId& region_id,
const FabricKeyId& key_id) {
/* validate the key_id */
VTR_ASSERT(valid_key_id(key_id));
/* validate the region_id */
VTR_ASSERT(valid_region_id(region_id));
/* Check if the key is already in the region */
if (region_key_ids_[region_id].end() != std::find(region_key_ids_[region_id].begin(),
region_key_ids_[region_id].end(),
key_id)) {
VTR_LOG_WARN("Try to add a key '%s' which is already in the region '%lu'!\n",
key_name(key_id).c_str(),
size_t(region_id));
VTR_ASSERT(region_id == key_regions_[key_id]);
return; /* Nothing to do but leave a warning! */
}
/* Register the key in the region */
region_key_ids_[region_id].push_back(key_id);
/* If the key is already in another region, we will error out */
if ( (true == valid_region_id(key_regions_[key_id]))
&& (region_id != key_regions_[key_id])) {
VTR_LOG_ERROR("Try to add a key '%s' to region '%lu' but it is already in another region '%lu'!\n",
key_name(key_id).c_str(),
size_t(key_regions_[key_id]),
size_t(region_id));
exit(1);
}
key_regions_[key_id] = region_id;
}
void FabricKey::reserve_keys(const size_t& num_keys) {
key_ids_.reserve(num_keys);
key_names_.reserve(num_keys);
key_values_.reserve(num_keys);
key_regions_.reserve(num_keys);
key_alias_.reserve(num_keys);
}
/* Create a new key and add it to the library, return an id */
FabricKeyId FabricKey::create_key() {
/* Create a new id */
FabricKeyId key = FabricKeyId(key_ids_.size());
key_ids_.push_back(key);
key_names_.emplace_back();
key_values_.emplace_back();
key_regions_.emplace_back(FabricRegionId::INVALID());
key_alias_.emplace_back();
return key;
@ -98,6 +166,10 @@ void FabricKey::set_key_alias(const FabricKeyId& key_id,
* Internal invalidators/validators
***********************************************************************/
/* Validators */
bool FabricKey::valid_region_id(const FabricRegionId& region_id) const {
return ( size_t(region_id) < region_ids_.size() ) && ( region_id == region_ids_[region_id] );
}
bool FabricKey::valid_key_id(const FabricKeyId& key_id) const {
return ( size_t(key_id) < key_ids_.size() ) && ( key_id == key_ids_[key_id] );
}

View File

@ -15,41 +15,94 @@
/********************************************************************
* A data structure to describe a secure key for fabric organization
* A fabric may consist of multiple regions
* Each region contains a number of keys
*
* Note that:
* - each key can only be defined in one unique region
*
* Typical usage:
* --------------
* // Create an empty fabric key
* FabricKey fabric_key;
* // Create a region
* FabricRegionId region = fabric_key.create_region();
* // Add a key with name and value
* FabricKeyId key = fabic_key.create_key(key_name, key_value);
* FabricKeyId key = fabric_key.create_key(key_name, key_value);
* // Affilate a key to a region
* fabric_key.add_key_to_region(region, key);
*
*******************************************************************/
class FabricKey {
public: /* Types */
typedef vtr::vector<FabricKeyId, FabricKeyId>::const_iterator fabric_key_iterator;
typedef vtr::vector<FabricRegionId, FabricRegionId>::const_iterator fabric_region_iterator;
/* Create range */
typedef vtr::Range<fabric_region_iterator> fabric_region_range;
typedef vtr::Range<fabric_key_iterator> fabric_key_range;
public: /* Constructors */
FabricKey();
public: /* Accessors: aggregates */
fabric_key_range keys() const;
fabric_region_range regions() const;
public: /* Public Accessors: Basic data query */
/* Access all the keys of a region */
std::vector<FabricKeyId> region_keys(const FabricRegionId& region_id) const;
/* Access the name of a key */
std::string key_name(const FabricKeyId& key_id) const;
/* Access the value of a key */
size_t key_value(const FabricKeyId& key_id) const;
/* Access the alias of a key */
std::string key_alias(const FabricKeyId& key_id) const;
/* Check if there are any keys */
bool empty() const;
public: /* Public Mutators: model-related */
/* Reserve a number of regions to be memory efficent */
void reserve_regions(const size_t& num_regions);
/* Create a new region and add it to the library, return an id */
FabricRegionId create_region();
/* Reserve the memory space for keys under a region, to be memory efficient */
void reserve_region_keys(const FabricRegionId& region_id,
const size_t& num_keys);
/* Add a key to a region */
void add_key_to_region(const FabricRegionId& region_id,
const FabricKeyId& key_id);
/* Reserve a number of keys to be memory efficent */
void reserve_keys(const size_t& num_keys);
/* Create a new key and add it to the library, return an id */
FabricKeyId create_key();
/* Configure attributes of a key */
void set_key_name(const FabricKeyId& key_id,
const std::string& name);
void set_key_value(const FabricKeyId& key_id,
const size_t& value);
void set_key_alias(const FabricKeyId& key_id,
const std::string& alias);
public: /* Public invalidators/validators */
bool valid_region_id(const FabricRegionId& region_id) const;
bool valid_key_id(const FabricKeyId& key_id) const;
private: /* Internal data */
/* Unique ids for each region */
vtr::vector<FabricRegionId, FabricRegionId> region_ids_;
/* Key ids for each region */
vtr::vector<FabricRegionId, std::vector<FabricKeyId>> region_key_ids_;
/* Unique ids for each key */
vtr::vector<FabricKeyId, FabricKeyId> key_ids_;
@ -59,6 +112,9 @@ class FabricKey {
/* Values for each key */
vtr::vector<FabricKeyId, size_t> key_values_;
/* Region for each key */
vtr::vector<FabricKeyId, FabricRegionId> key_regions_;
/* Optional alias for each key, with which a key can also be represented */
vtr::vector<FabricKeyId, std::string> key_alias_;
};

View File

@ -12,8 +12,10 @@
#include "vtr_strong_id.h"
struct fabric_region_id_tag;
struct fabric_key_id_tag;
typedef vtr::StrongId<fabric_region_id_tag> FabricRegionId;
typedef vtr::StrongId<fabric_key_id_tag> FabricKeyId;
/* Short declaration of class */

View File

@ -23,17 +23,19 @@
* Parse XML codes of a <key> to an object of FabricKey
*******************************************************************/
static
void read_xml_component_key(pugi::xml_node& xml_component_key,
const pugiutil::loc_data& loc_data,
FabricKey& fabric_key) {
void read_xml_region_key(pugi::xml_node& xml_component_key,
const pugiutil::loc_data& loc_data,
FabricKey& fabric_key,
const FabricRegionId& fabric_region) {
/* Find the id of component key */
const size_t& id = get_attribute(xml_component_key, "id", loc_data).as_int();
if (false == fabric_key.valid_key_id(FabricKeyId(id))) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key),
"Invalid 'id' attribute '%d'\n",
id);
"Invalid 'id' attribute '%d' (in total %lu keys)!\n",
id,
fabric_key.keys().size());
}
VTR_ASSERT_SAFE(true == fabric_key.valid_key_id(FabricKeyId(id)));
@ -57,6 +59,41 @@ void read_xml_component_key(pugi::xml_node& xml_component_key,
fabric_key.set_key_name(FabricKeyId(id), name);
fabric_key.set_key_value(FabricKeyId(id), value);
fabric_key.add_key_to_region(fabric_region, FabricKeyId(id));
}
/********************************************************************
* Parse XML codes of a <key> to an object of FabricKey
*******************************************************************/
static
void read_xml_fabric_region(pugi::xml_node& xml_region,
const pugiutil::loc_data& loc_data,
FabricKey& fabric_key) {
/* Find the unique id for the region */
const FabricRegionId& region_id = FabricRegionId(get_attribute(xml_region, "id", loc_data).as_int());
if (false == fabric_key.valid_region_id(region_id)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region),
"Invalid region id '%lu' (in total %lu regions)!\n",
size_t(region_id),
fabric_key.regions().size());
}
VTR_ASSERT_SAFE(true == fabric_key.valid_region_id(region_id));
/* Reserve memory space for the keys in the region */
size_t num_keys = std::distance(xml_region.children().begin(), xml_region.children().end());
fabric_key.reserve_region_keys(region_id, num_keys);
for (pugi::xml_node xml_key : xml_region.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_key.name() != std::string("key")) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region),
"Unexpected child '%s' in region '%lu', Region XML node can only contain keys!\n",
xml_key.name(),
size_t(region_id));
}
/* Parse the key for this region */
read_xml_region_key(xml_key, loc_data, fabric_key, region_id);
}
}
/********************************************************************
@ -77,7 +114,24 @@ FabricKey read_xml_fabric_key(const char* key_fname) {
pugi::xml_node xml_root = get_single_child(doc, "fabric_key", loc_data);
size_t num_keys = std::distance(xml_root.children().begin(), xml_root.children().end());
size_t num_regions = std::distance(xml_root.children().begin(), xml_root.children().end());
/* Reserve memory space for the region */
fabric_key.reserve_regions(num_regions);
for (size_t iregion = 0; iregion < num_regions; ++iregion) {
fabric_key.create_region();
}
/* Reserve memory space for the keys */
size_t num_keys = 0;
for (pugi::xml_node xml_region : xml_root.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_region.name() != std::string("region")) {
bad_tag(xml_region, loc_data, xml_root, {"region"});
}
num_keys += std::distance(xml_region.children().begin(), xml_region.children().end());
}
fabric_key.reserve_keys(num_keys);
for (size_t ikey = 0; ikey < num_keys; ++ikey) {
fabric_key.create_key();
@ -86,12 +140,12 @@ FabricKey read_xml_fabric_key(const char* key_fname) {
/* Iterate over the children under this node,
* each child should be named after circuit_model
*/
for (pugi::xml_node xml_key : xml_root.children()) {
for (pugi::xml_node xml_region : xml_root.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_key.name() != std::string("key")) {
bad_tag(xml_key, loc_data, xml_root, {"key"});
if (xml_region.name() != std::string("region")) {
bad_tag(xml_region, loc_data, xml_root, {"region"});
}
read_xml_component_key(xml_key, loc_data, fabric_key);
read_xml_fabric_region(xml_region, loc_data, fabric_key);
}
} catch (pugiutil::XmlError& e) {
archfpga_throw(key_fname, e.line(),

View File

@ -9,6 +9,8 @@
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpga util library */
#include "openfpga_digest.h"
/* Headers from arch openfpga library */
@ -33,7 +35,8 @@ int write_xml_fabric_component_key(std::fstream& fp,
return 2;
}
fp << "\t" << "<key";
openfpga::write_tab_to_file(fp, 2);
fp << "<key";
if (false == fabric_key.valid_key_id(component_key)) {
return 1;
@ -79,12 +82,21 @@ int write_xml_fabric_key(const char* fname,
int err_code = 0;
/* Write component by component */
for (const FabricKeyId& key : fabric_key.keys()) {
err_code = write_xml_fabric_component_key(fp, fabric_key, key);
if (0 != err_code) {
return err_code;
/* Write region by region */
for (const FabricRegionId& region : fabric_key.regions()) {
openfpga::write_tab_to_file(fp, 1);
fp << "<region id=\"" << size_t(region) << "\"" << ">\n";
/* Write component by component */
for (const FabricKeyId& key : fabric_key.region_keys(region)) {
err_code = write_xml_fabric_component_key(fp, fabric_key, key);
if (0 != err_code) {
return err_code;
}
}
openfpga::write_tab_to_file(fp, 1);
fp << "</region>" << "\n";
}
/* Finish writing the root node */

View File

@ -128,4 +128,54 @@ size_t bintoi_charvec(const std::vector<char>& bin) {
return ret;
}
/********************************************************************
* Expand all the don't care bits in a string
* A don't care 'x' can be decoded to either '0' or '1'
* For example:
* input: 0x1x
* output: 0010
* 0100
* 0101
* 0011
*
* Return all the strings
********************************************************************/
std::vector<std::string> expand_dont_care_bin_str(const std::string& input_str) {
std::vector<std::string> ret;
/* If the input is don't care free, we can retrun */
bool has_dont_care = false;
for (const char& bit : input_str) {
if (DONT_CARE_CHAR == bit) {
has_dont_care = true;
break;
}
}
if (false == has_dont_care) {
ret.push_back(input_str);
return ret;
}
/* Recusively expand all the don't bits */
for (size_t i = 0; i < input_str.length(); ++i) {
if (DONT_CARE_CHAR == input_str[i]) {
std::string temp_input_str = input_str;
/* Flip to '0' and go recursively */
temp_input_str[i] = '0';
for (const std::string& expanded_str : expand_dont_care_bin_str(temp_input_str)) {
ret.push_back(expanded_str);
}
/* Flip to '1' and go recursively */
temp_input_str[i] = '1';
for (const std::string& expanded_str : expand_dont_care_bin_str(temp_input_str)) {
ret.push_back(expanded_str);
}
break;
}
}
return ret;
}
} /* end namespace openfpga */

View File

@ -6,6 +6,7 @@
*******************************************************************/
#include <stddef.h>
#include <vector>
#include <string>
/********************************************************************
* Function declaration
@ -13,6 +14,11 @@
/* namespace openfpga begins */
namespace openfpga {
/****************************************
* Constants
*/
constexpr char DONT_CARE_CHAR = 'x';
std::vector<size_t> ito1hot_vec(const size_t& in_int,
const size_t& bin_len);
@ -24,6 +30,8 @@ std::vector<char> itobin_charvec(const size_t& in_int,
size_t bintoi_charvec(const std::vector<char>& bin);
std::vector<std::string> expand_dont_care_bin_str(const std::string& input_str);
} /* namespace openfpga ends */
#endif

View File

@ -11,7 +11,10 @@ namespace openfpga {
/**************************************************
* Public Accessors
*************************************************/
size_t IoLocationMap::io_index(const size_t& x, const size_t& y, const size_t& z) const {
size_t IoLocationMap::io_index(const size_t& x,
const size_t& y,
const size_t& z,
const std::string& io_port_name) const {
if (x >= io_indices_.size()) {
return size_t(-1);
}
@ -24,10 +27,19 @@ size_t IoLocationMap::io_index(const size_t& x, const size_t& y, const size_t& z
return size_t(-1);
}
return io_indices_[x][y][z];
auto result = io_indices_[x][y][z].find(io_port_name);
if (result == io_indices_[x][y][z].end()) {
return size_t(-1);
}
return result->second;
}
void IoLocationMap::set_io_index(const size_t& x, const size_t& y, const size_t& z, const size_t& io_index) {
void IoLocationMap::set_io_index(const size_t& x,
const size_t& y,
const size_t& z,
const std::string& io_port_name,
const size_t& io_index) {
if (x >= io_indices_.size()) {
io_indices_.resize(x + 1);
}
@ -40,7 +52,7 @@ void IoLocationMap::set_io_index(const size_t& x, const size_t& y, const size_t&
io_indices_[x][y].resize(z + 1);
}
io_indices_[x][y][z] = io_index;
io_indices_[x][y][z][io_port_name] = io_index;
}
} /* end namespace openfpga */

View File

@ -6,6 +6,8 @@
*******************************************************************/
#include <stddef.h>
#include <vector>
#include <string>
#include <map>
/* Begin namespace openfpga */
namespace openfpga {
@ -15,24 +17,32 @@ namespace openfpga {
* in the FPGA fabric, i.e., the module graph, and logical location
* of the I/O in VPR coordinate system
*
* For example
* io[0] io[1] io[2]
* +-----------------+ +--------+
* | | | | |
* | I/O | I/O | | I/O |
* | [0][y] | [0][y] | | [1][y] |
* | [0] | [1] | | [0] |
* +-----------------+ +--------+
* For example:
*
* ioA[0] ioA[1] ioB[0] ioB[1] ioA[2]
* +-----------------+ +--------+--------+ +--------+
* | | | | | | | |
* | I/O | I/O | | I/O | I/O | | I/O |
* | [0][y] | [0][y] | | [1][y] | [1][y] | | [2][y] | ...
* | [0] | [1] | | [0] | [1] | | [0] |
* +-----------------+ +--------+--------+ +--------+
*
*******************************************************************/
class IoLocationMap {
public: /* Public aggregators */
size_t io_index(const size_t& x, const size_t& y, const size_t& z) const;
size_t io_index(const size_t& x,
const size_t& y,
const size_t& z,
const std::string& io_port_name) const;
public: /* Public mutators */
void set_io_index(const size_t& x, const size_t& y, const size_t& z, const size_t& io_index);
void set_io_index(const size_t& x,
const size_t& y,
const size_t& z,
const std::string& io_port_name,
const size_t& io_index);
private: /* Internal Data */
/* I/O index fast lookup by [x][y][z] location */
std::vector<std::vector<std::vector<size_t>>> io_indices_;
std::vector<std::vector<std::vector<std::map<std::string, size_t>>>> io_indices_;
};
} /* End namespace openfpga*/

View File

@ -16,6 +16,8 @@
#include "build_device_module.h"
#include "fabric_hierarchy_writer.h"
#include "fabric_key_writer.h"
#include "build_fabric_io_location_map.h"
#include "build_fabric_global_port_info.h"
#include "openfpga_build_fabric.h"
/* Include global variables of VPR */
@ -100,7 +102,6 @@ int build_fabric(OpenfpgaContext& openfpga_ctx,
VTR_LOG("\n");
curr_status = build_device_module_graph(openfpga_ctx.mutable_module_graph(),
openfpga_ctx.mutable_io_location_map(),
openfpga_ctx.mutable_decoder_lib(),
const_cast<const OpenfpgaContext&>(openfpga_ctx),
g_vpr_ctx.device(),
@ -116,13 +117,21 @@ int build_fabric(OpenfpgaContext& openfpga_ctx,
final_status = curr_status;
}
/* Build I/O location map */
openfpga_ctx.mutable_io_location_map() = build_fabric_io_location_map(openfpga_ctx.module_graph(),
g_vpr_ctx.device().grid);
/* Build fabric global port information */
openfpga_ctx.mutable_fabric_global_port_info() = build_fabric_global_port_info(openfpga_ctx.module_graph(),
openfpga_ctx.arch().tile_annotations,
openfpga_ctx.arch().circuit_lib);
/* Output fabric key if user requested */
if (true == cmd_context.option_enable(cmd, opt_write_fabric_key)) {
std::string fkey_fname = cmd_context.option_value(cmd, opt_write_fabric_key);
VTR_ASSERT(false == fkey_fname.empty());
curr_status = write_fabric_key_to_xml_file(openfpga_ctx.module_graph(),
fkey_fname,
openfpga_ctx.arch().config_protocol.type(),
cmd_context.option_enable(cmd, opt_verbose));
/* If there is any error, final status cannot be overwritten by a success flag */
if (CMD_EXEC_SUCCESS != curr_status) {

View File

@ -19,6 +19,7 @@
#include "fabric_bitstream.h"
#include "device_rr_gsb.h"
#include "io_location_map.h"
#include "fabric_global_port_info.h"
/********************************************************************
* This file includes the declaration of the date structure
@ -65,6 +66,7 @@ class OpenfpgaContext : public Context {
const openfpga::BitstreamManager& bitstream_manager() const { return bitstream_manager_; }
const openfpga::FabricBitstream& fabric_bitstream() const { return fabric_bitstream_; }
const openfpga::IoLocationMap& io_location_map() const { return io_location_map_; }
const openfpga::FabricGlobalPortInfo& fabric_global_port_info() const { return fabric_global_port_info_; }
const std::unordered_map<AtomNetId, t_net_power>& net_activity() const { return net_activity_; }
const openfpga::NetlistManager& verilog_netlists() const { return verilog_netlists_; }
const openfpga::NetlistManager& spice_netlists() const { return spice_netlists_; }
@ -85,6 +87,7 @@ class OpenfpgaContext : public Context {
openfpga::BitstreamManager& mutable_bitstream_manager() { return bitstream_manager_; }
openfpga::FabricBitstream& mutable_fabric_bitstream() { return fabric_bitstream_; }
openfpga::IoLocationMap& mutable_io_location_map() { return io_location_map_; }
openfpga::FabricGlobalPortInfo& mutable_fabric_global_port_info() { return fabric_global_port_info_; }
std::unordered_map<AtomNetId, t_net_power>& mutable_net_activity() { return net_activity_; }
openfpga::NetlistManager& mutable_verilog_netlists() { return verilog_netlists_; }
openfpga::NetlistManager& mutable_spice_netlists() { return spice_netlists_; }
@ -123,6 +126,7 @@ class OpenfpgaContext : public Context {
/* Fabric module graph */
openfpga::ModuleManager module_graph_;
openfpga::IoLocationMap io_location_map_;
openfpga::FabricGlobalPortInfo fabric_global_port_info_;
/* Bitstream database */
openfpga::BitstreamManager bitstream_manager_;

View File

@ -1445,4 +1445,14 @@ std::string generate_const_value_module_output_port_name(const size_t& const_val
return generate_const_value_module_name(const_val);
}
/*********************************************************************
* Generate the analysis SDC file name
* The format is
* <circuit_name>_<postfix>
********************************************************************/
std::string generate_analysis_sdc_file_name(const std::string& circuit_name,
const std::string& file_name_postfix) {
return circuit_name + "_" + file_name_postfix;
}
} /* end namespace openfpga */

View File

@ -264,6 +264,9 @@ std::string generate_const_value_module_name(const size_t& const_val);
std::string generate_const_value_module_output_port_name(const size_t& const_val);
std::string generate_analysis_sdc_file_name(const std::string& circuit_name,
const std::string& file_name_postfix);
} /* end namespace openfpga */
#endif

View File

@ -17,6 +17,7 @@
#include "openfpga_side_manager.h"
#include "pb_type_utils.h"
#include "openfpga_physical_tile_utils.h"
#include "openfpga_pb_pin_fixup.h"
/* Include global variables of VPR */
@ -25,28 +26,6 @@
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Give a given pin index, find the side where this pin is located
* on the physical tile
* Note:
* - Need to check if the pin_width_offset and pin_height_offset
* are properly set in VPR!!!
*******************************************************************/
static
std::vector<e_side> find_logic_tile_pin_side(t_physical_tile_type_ptr physical_tile,
const int& physical_pin) {
std::vector<e_side> pin_sides;
for (const e_side& side_cand : {TOP, RIGHT, BOTTOM, LEFT}) {
int pin_width_offset = physical_tile->pin_width_offset[physical_pin];
int pin_height_offset = physical_tile->pin_height_offset[physical_pin];
if (true == physical_tile->pinloc[pin_width_offset][pin_height_offset][side_cand][physical_pin]) {
pin_sides.push_back(side_cand);
}
}
return pin_sides;
}
/********************************************************************
* Fix up the pb pin mapping results for a given clustered block
* 1. For each input/output pin of a clustered pb,
@ -86,7 +65,7 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct
VTR_ASSERT(class_inf.type == RECEIVER);
rr_node_type = IPIN;
}
std::vector<e_side> pin_sides = find_logic_tile_pin_side(physical_tile, physical_pin);
std::vector<e_side> pin_sides = find_physical_tile_pin_side(physical_tile, physical_pin, border_side);
/* As some grid has height/width offset, we may not have the pin on any side */
if (0 == pin_sides.size()) {
continue;

View File

@ -12,10 +12,14 @@
#include "read_xml_openfpga_arch.h"
#include "check_circuit_library.h"
#include "circuit_library_utils.h"
#include "check_tile_annotation.h"
#include "write_xml_openfpga_arch.h"
#include "openfpga_read_arch.h"
/* Include global variables of VPR */
#include "globals.h"
/* begin namespace openfpga */
namespace openfpga {
@ -44,8 +48,9 @@ int read_arch(OpenfpgaContext& openfpga_context,
/* Check the architecture:
* 1. Circuit library
* 2. Technology library (TODO)
* 3. Simulation settings (TODO)
* 2. Tile annotation
* 3. Technology library (TODO)
* 4. Simulation settings (TODO)
*/
if (false == check_circuit_library(openfpga_context.arch().circuit_lib)) {
return CMD_EXEC_FATAL_ERROR;
@ -57,6 +62,12 @@ int read_arch(OpenfpgaContext& openfpga_context,
return CMD_EXEC_FATAL_ERROR;
}
if (false == check_tile_annotation(openfpga_context.arch().tile_annotations,
openfpga_context.arch().circuit_lib,
g_vpr_ctx.device().physical_tile_types)) {
return CMD_EXEC_FATAL_ERROR;
}
return CMD_EXEC_SUCCESS;
}

View File

@ -80,11 +80,6 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
options.set_generate_sdc_pnr(true);
}
/* Collect global ports from the circuit library:
* TODO: should we place this in the OpenFPGA context?
*/
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(openfpga_ctx.arch().circuit_lib);
/* Execute only when sdc is enabled */
if (true == options.generate_sdc_pnr()) {
print_pnr_sdc(options,
@ -96,7 +91,7 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
openfpga_ctx.module_graph(),
openfpga_ctx.mux_lib(),
openfpga_ctx.arch().circuit_lib,
global_ports,
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.flow_manager().compress_routing());
}
@ -193,17 +188,11 @@ int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx,
options.set_time_unit(string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit)));
}
/* Collect global ports from the circuit library:
* TODO: should we place this in the OpenFPGA context?
*/
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(openfpga_ctx.arch().circuit_lib);
if (true == options.generate_sdc_analysis()) {
print_analysis_sdc(options,
1./openfpga_ctx.simulation_setting().operating_clock_frequency(),
g_vpr_ctx,
openfpga_ctx,
global_ports,
openfpga_ctx.flow_manager().compress_routing());
}

View File

@ -26,8 +26,6 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
CommandOptionId opt_include_timing = cmd.option("include_timing");
CommandOptionId opt_include_signal_init = cmd.option("include_signal_init");
CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator");
CommandOptionId opt_print_user_defined_template = cmd.option("print_user_defined_template");
CommandOptionId opt_verbose = cmd.option("verbose");
@ -38,8 +36,6 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx,
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_include_timing(cmd_context.option_enable(cmd, opt_include_timing));
options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init));
options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator));
options.set_print_user_defined_template(cmd_context.option_enable(cmd, opt_print_user_defined_template));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
options.set_compress_routing(openfpga_ctx.flow_manager().compress_routing());
@ -65,6 +61,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path");
CommandOptionId opt_print_top_testbench = cmd.option("print_top_testbench");
CommandOptionId opt_fast_configuration = cmd.option("fast_configuration");
@ -72,6 +69,8 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_print_preconfig_top_testbench = cmd.option("print_preconfig_top_testbench");
CommandOptionId opt_print_simulation_ini = cmd.option("print_simulation_ini");
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
CommandOptionId opt_include_signal_init = cmd.option("include_signal_init");
CommandOptionId opt_support_icarus_simulator = cmd.option("support_icarus_simulator");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the FPGA-Verilog
@ -79,6 +78,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
*/
VerilogTestbenchOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_fabric_netlist_file_path(cmd_context.option_value(cmd, opt_fabric_netlist));
options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark));
options.set_print_formal_verification_top_netlist(cmd_context.option_enable(cmd, opt_print_formal_verification_top_netlist));
options.set_print_preconfig_top_testbench(cmd_context.option_enable(cmd, opt_print_preconfig_top_testbench));
@ -86,6 +86,8 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
options.set_print_top_testbench(cmd_context.option_enable(cmd, opt_print_top_testbench));
options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_print_simulation_ini));
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init));
options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
fpga_verilog_testbench(openfpga_ctx.module_graph(),
@ -94,10 +96,11 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
g_vpr_ctx.atom(),
g_vpr_ctx.placement(),
openfpga_ctx.io_location_map(),
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.simulation_setting(),
openfpga_ctx.arch().config_protocol.type(),
openfpga_ctx.arch().config_protocol,
options);
/* TODO: should identify the error code from internal function execution */

View File

@ -33,12 +33,6 @@ ShellCommandId add_openfpga_write_fabric_verilog_command(openfpga::Shell<Openfpg
/* Add an option '--include_timing' */
shell_cmd.add_option("include_timing", false, "Enable timing annotation in Verilog netlists");
/* Add an option '--include_signal_init' */
shell_cmd.add_option("include_signal_init", false, "Initialize all the signals in Verilog netlists");
/* Add an option '--support_icarus_simulator' */
shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog netlists to support icarus simulator");
/* Add an option '--print_user_defined_template' */
shell_cmd.add_option("print_user_defined_template", false, "Generate a template Verilog files for user-defined circuit models");
@ -72,6 +66,10 @@ ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell<Open
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
/* Add an option '--fabric_netlist_file_path'*/
CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric Verilog netlist");
shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING);
/* Add an option '--reference_benchmark_file_path'*/
CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist");
shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING);
@ -95,6 +93,12 @@ ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell<Open
/* Add an option '--explicit_port_mapping' */
shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists");
/* Add an option '--include_signal_init' */
shell_cmd.add_option("include_signal_init", false, "Initialize all the signals in Verilog testbenches");
/* Add an option '--support_icarus_simulator' */
shell_cmd.add_option("support_icarus_simulator", false, "Fine-tune Verilog testbenches to support icarus simulator");
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");

View File

@ -30,7 +30,6 @@ namespace openfpga {
* for a FPGA fabric
*******************************************************************/
int build_device_module_graph(ModuleManager& module_manager,
IoLocationMap& io_location_map,
DecoderLibrary& decoder_lib,
const OpenfpgaContext& openfpga_ctx,
const DeviceContext& vpr_device_ctx,
@ -112,15 +111,15 @@ int build_device_module_graph(ModuleManager& module_manager,
/* Build FPGA fabric top-level module */
status = build_top_module(module_manager,
io_location_map,
decoder_lib,
openfpga_ctx.arch().circuit_lib,
vpr_device_ctx.grid,
openfpga_ctx.arch().tile_annotations,
vpr_device_ctx.rr_graph,
openfpga_ctx.device_rr_gsb(),
openfpga_ctx.tile_direct(),
openfpga_ctx.arch().arch_direct,
openfpga_ctx.arch().config_protocol.type(),
openfpga_ctx.arch().config_protocol,
sram_model,
frame_view, compress_routing, duplicate_grid_pin,
fabric_key, generate_random_fabric_key);

View File

@ -16,7 +16,6 @@
namespace openfpga {
int build_device_module_graph(ModuleManager& module_manager,
IoLocationMap& io_location_map,
DecoderLibrary& decoder_lib,
const OpenfpgaContext& openfpga_ctx,
const DeviceContext& vpr_device_ctx,

View File

@ -256,7 +256,15 @@ void rename_primitive_module_port_names(ModuleManager& module_manager,
/* We only care about user-defined models */
if ( (true == circuit_lib.model_verilog_netlist(model).empty())
&& (true == circuit_lib.model_spice_netlist(model).empty()) ) {
continue;
/* Exception circuit models as primitive cells
* - Inverter, buffer, pass-gate logic, logic gate
* which should be renamed even when auto-generated
*/
if ( (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model))
&& (CIRCUIT_MODEL_PASSGATE != circuit_lib.model_type(model))
&& (CIRCUIT_MODEL_GATE != circuit_lib.model_type(model)) ) {
continue;
}
}
/* Skip Routing channel wire models because they need a different name. Do it later */
if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) {

View File

@ -0,0 +1,90 @@
/********************************************************************
* This file includes functions that are used to build the global port
* information for the top-level module of the FPGA fabric
* It helps OpenFPGA to build testbenches with the attributes of the global ports
*******************************************************************/
#include <map>
#include <algorithm>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_time.h"
#include "vtr_log.h"
#include "openfpga_naming.h"
#include "circuit_library_utils.h"
#include "build_fabric_global_port_info.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Find all the GPIO ports in the grid module
* and cache their port/pin index in the top-level module
*******************************************************************/
FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager,
const TileAnnotation& tile_annotation,
const CircuitLibrary& circuit_lib) {
vtr::ScopedStartFinishTimer timer("Create global port info for top module");
FabricGlobalPortInfo fabric_global_port_info;
/* Find top-level module */
std::string top_module_name = generate_fpga_top_module_name();
ModuleId top_module = module_manager.find_module(top_module_name);
if (true != module_manager.valid_module_id(top_module)) {
VTR_LOG_ERROR("Unable to find the top-level module '%s'!\n",
top_module_name.c_str());
exit(1);
}
/* Add the global ports from circuit library */
for (const CircuitPortId& global_port : find_circuit_library_global_ports(circuit_lib)) {
/* We should find a port in the top module */
ModulePortId module_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(global_port));
/* Only add those ports have been defined in top-level module */
if (false == module_manager.valid_module_port_id(top_module, module_port)) {
continue;
}
/* Add the port information */
FabricGlobalPortId fabric_port = fabric_global_port_info.create_global_port(module_port);
fabric_global_port_info.set_global_port_is_clock(fabric_port, CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(global_port));
fabric_global_port_info.set_global_port_is_reset(fabric_port, circuit_lib.port_is_reset(global_port));
fabric_global_port_info.set_global_port_is_set(fabric_port, circuit_lib.port_is_set(global_port));
fabric_global_port_info.set_global_port_is_prog(fabric_port, circuit_lib.port_is_prog(global_port));
fabric_global_port_info.set_global_port_is_config_enable(fabric_port, circuit_lib.port_is_config_enable(global_port));
fabric_global_port_info.set_global_port_default_value(fabric_port, circuit_lib.port_default_value(global_port));
}
/* Add the global ports from tile annotation */
for (const TileGlobalPortId& global_port : tile_annotation.global_ports()) {
/* We should find a port in the top module */
ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(global_port));
/* Only add those ports have been defined in top-level module */
if (false == module_manager.valid_module_port_id(top_module, module_port)) {
continue;
}
/* Avoid adding redundant ports */
bool already_in_list = false;
for (const FabricGlobalPortId& port : fabric_global_port_info.global_ports()) {
if (module_port == fabric_global_port_info.global_module_port(port)) {
already_in_list = true;
break;
}
}
if (true == already_in_list) {
continue;
}
/* Add the port information */
FabricGlobalPortId fabric_port = fabric_global_port_info.create_global_port(module_port);
fabric_global_port_info.set_global_port_is_clock(fabric_port, tile_annotation.global_port_is_clock(global_port));
fabric_global_port_info.set_global_port_is_reset(fabric_port, tile_annotation.global_port_is_reset(global_port));
fabric_global_port_info.set_global_port_is_set(fabric_port, tile_annotation.global_port_is_set(global_port));
fabric_global_port_info.set_global_port_default_value(fabric_port, tile_annotation.global_port_default_value(global_port));
}
return fabric_global_port_info;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,27 @@
#ifndef BUILD_FABRIC_GLOBAL_PORT_INFO_H
#define BUILD_FABRIC_GLOBAL_PORT_INFO_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "tile_annotation.h"
#include "circuit_library.h"
#include "fabric_global_port_info.h"
#include "module_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager,
const TileAnnotation& tile_annotation,
const CircuitLibrary& circuit_lib);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,122 @@
/********************************************************************
* This file includes functions that are used to build the location
* map information for the top-level module of the FPGA fabric
* It helps OpenFPGA to link the I/O port index in top-level module
* to the VPR I/O mapping results
*******************************************************************/
#include <map>
#include <algorithm>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_time.h"
#include "vtr_log.h"
/* Headers from vpr library */
#include "vpr_utils.h"
#include "openfpga_reserved_words.h"
#include "openfpga_naming.h"
#include "module_manager_utils.h"
#include "openfpga_device_grid_utils.h"
#include "build_fabric_io_location_map.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Find all the GPIO ports in the grid module
* and cache their port/pin index in the top-level module
*******************************************************************/
IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
const DeviceGrid& grids) {
vtr::ScopedStartFinishTimer timer("Create I/O location mapping for top module");
IoLocationMap io_location_map;
std::map<std::string, size_t> io_counter;
/* Create the coordinate range for each side of FPGA fabric */
std::map<e_side, std::vector<vtr::Point<size_t>>> io_coordinates = generate_perimeter_grid_coordinates( grids);
/* Walk through all the grids on the perimeter, which are I/O grids */
for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) {
for (const vtr::Point<size_t>& io_coordinate : io_coordinates[io_side]) {
/* Bypass EMPTY grid */
if (true == is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) {
continue;
}
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
if ( (0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset)
|| (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) {
continue;
}
t_physical_tile_type_ptr grid_type = grids[io_coordinate.x()][io_coordinate.y()].type;
/* Find the module name for this type of grid */
std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX);
std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), io_side);
ModuleId grid_module = module_manager.find_module(grid_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(grid_module));
/* Find all the GPIO ports in the grid module */
/* MUST DO: register in io location mapping!
* I/O location mapping is a critical look-up for testbench generators
* As we add the I/O grid instances to top module by following order:
* TOP -> RIGHT -> BOTTOM -> LEFT
* The I/O index will increase in this way as well.
* This organization I/O indices is also consistent to the way
* that GPIOs are wired in function connect_gpio_module()
*
* Note: if you change the GPIO function, you should update here as well!
*/
for (int z = 0; z < grids[io_coordinate.x()][io_coordinate.y()].type->capacity; ++z) {
for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) {
for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(grid_module, module_io_port_type)) {
/* Only care mappable I/O */
if (false == module_manager.port_is_mappable_io(grid_module, gpio_port_id)) {
continue;
}
const BasicPort& gpio_port = module_manager.module_port(grid_module, gpio_port_id);
auto curr_io_index = io_counter.find(gpio_port.get_name());
/* Index always start from zero */
if (curr_io_index == io_counter.end()) {
io_counter[gpio_port.get_name()] = 0;
}
io_location_map.set_io_index(io_coordinate.x(), io_coordinate.y(), z,
gpio_port.get_name(),
io_counter[gpio_port.get_name()]);
io_counter[gpio_port.get_name()]++;
}
}
}
}
}
/* Check all the GPIO ports in the top-level module has been mapped */
std::string top_module_name = generate_fpga_top_module_name();
ModuleId top_module = module_manager.find_module(top_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) {
for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(top_module, module_io_port_type)) {
/* Only care mappable I/O */
if (false == module_manager.port_is_mappable_io(top_module, gpio_port_id)) {
continue;
}
const BasicPort& gpio_port = module_manager.module_port(top_module, gpio_port_id);
VTR_ASSERT(io_counter[gpio_port.get_name()] == gpio_port.get_width());
}
}
return io_location_map;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,25 @@
#ifndef BUILD_FABRIC_IO_LOCATION_MAP_H
#define BUILD_FABRIC_IO_LOCATION_MAP_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "device_grid.h"
#include "io_location_map.h"
#include "module_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
const DeviceGrid& grids);
} /* end namespace openfpga */
#endif

View File

@ -159,6 +159,11 @@ void add_primitive_module_fpga_global_io_port(ModuleManager& module_manager,
const CircuitPortId& circuit_port) {
BasicPort module_port(generate_fpga_global_io_port_name(std::string(GIO_INOUT_PREFIX), circuit_lib, primitive_model, circuit_port), circuit_lib.port_size(circuit_port));
ModulePortId primitive_io_port_id = module_manager.add_port(primitive_module, module_port, module_io_port_type);
/* Set if the port is mappable or not */
if (true == circuit_lib.port_is_data_io(circuit_port)) {
module_manager.set_port_is_mappable_io(primitive_module, primitive_io_port_id, true);
}
ModulePortId logic_io_port_id = module_manager.find_module_port(logic_module, circuit_lib.port_prefix(circuit_port));
BasicPort logic_io_port = module_manager.module_port(logic_module, logic_io_port_id);
VTR_ASSERT(logic_io_port.get_width() == module_port.get_width());

View File

@ -636,13 +636,13 @@ void build_frame_memory_module(ModuleManager& module_manager,
module_manager.add_configurable_child(mem_module, sram_mem_module, sram_instance);
/* Wire data_in port to SRAM BL port */
ModulePortId sram_bl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_lib_name(sram_bl_ports[0]));
ModulePortId sram_bl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_prefix(sram_bl_ports[0]));
add_module_bus_nets(module_manager, mem_module,
mem_module, 0, mem_data_port,
sram_mem_module, sram_instance, sram_bl_port);
/* Wire decoder data_out port to sram WL ports */
ModulePortId sram_wl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_lib_name(sram_wl_ports[0]));
ModulePortId sram_wl_port = module_manager.find_module_port(sram_mem_module, circuit_lib.port_prefix(sram_wl_ports[0]));
ModulePortId decoder_data_port = module_manager.find_module_port(decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
ModuleNetId wl_net = module_manager.create_module_net(mem_module);
/* Source node of the input net is the input of memory module */

View File

@ -26,6 +26,7 @@
#include "build_top_module_directs.h"
#include "build_module_graph_utils.h"
#include "openfpga_device_grid_utils.h"
#include "build_top_module.h"
/* begin namespace openfpga */
@ -92,7 +93,6 @@ size_t add_top_module_grid_instance(ModuleManager& module_manager,
static
vtr::Matrix<size_t> add_top_module_grid_instances(ModuleManager& module_manager,
const ModuleId& top_module,
IoLocationMap& io_location_map,
const DeviceGrid& grids) {
vtr::ScopedStartFinishTimer timer("Add grid instances to top module");
@ -132,32 +132,9 @@ vtr::Matrix<size_t> add_top_module_grid_instances(ModuleManager& module_manager,
/* Instanciate I/O grids */
/* Create the coordinate range for each side of FPGA fabric */
std::vector<e_side> io_sides{TOP, RIGHT, BOTTOM, LEFT};
std::map<e_side, std::vector<vtr::Point<size_t>>> io_coordinates;
std::map<e_side, std::vector<vtr::Point<size_t>>> io_coordinates = generate_perimeter_grid_coordinates( grids);
/* TOP side*/
for (size_t ix = 1; ix < grids.width() - 1; ++ix) {
io_coordinates[TOP].push_back(vtr::Point<size_t>(ix, grids.height() - 1));
}
/* RIGHT side */
for (size_t iy = 1; iy < grids.height() - 1; ++iy) {
io_coordinates[RIGHT].push_back(vtr::Point<size_t>(grids.width() - 1, iy));
}
/* BOTTOM side*/
for (size_t ix = 1; ix < grids.width() - 1; ++ix) {
io_coordinates[BOTTOM].push_back(vtr::Point<size_t>(ix, 0));
}
/* LEFT side */
for (size_t iy = 1; iy < grids.height() - 1; ++iy) {
io_coordinates[LEFT].push_back(vtr::Point<size_t>(0, iy));
}
/* Add instances of I/O grids to top_module */
size_t io_counter = 0;
for (const e_side& io_side : io_sides) {
for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) {
for (const vtr::Point<size_t>& io_coordinate : io_coordinates[io_side]) {
/* Bypass EMPTY grid */
if (true == is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) {
@ -178,21 +155,6 @@ vtr::Matrix<size_t> add_top_module_grid_instances(ModuleManager& module_manager,
/* Add a grid module to top_module*/
grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = add_top_module_grid_instance(module_manager, top_module, grids[io_coordinate.x()][io_coordinate.y()].type, io_side, io_coordinate);
/* MUST DO: register in io location mapping!
* I/O location mapping is a critical look-up for testbench generators
* As we add the I/O grid instances to top module by following order:
* TOP -> RIGHT -> BOTTOM -> LEFT
* The I/O index will increase in this way as well.
* This organization I/O indices is also consistent to the way
* that GPIOs are wired in function connect_gpio_module()
*
* Note: if you change the GPIO function, you should update here as well!
*/
for (int z = 0; z < grids[io_coordinate.x()][io_coordinate.y()].type->capacity; ++z) {
io_location_map.set_io_index(io_coordinate.x(), io_coordinate.y(), z, io_counter);
io_counter++;
}
}
}
@ -322,15 +284,15 @@ vtr::Matrix<size_t> add_top_module_connection_block_instances(ModuleManager& mod
* 5. Add module nets/submodules to connect configuration ports
*******************************************************************/
int build_top_module(ModuleManager& module_manager,
IoLocationMap& io_location_map,
DecoderLibrary& decoder_lib,
const CircuitLibrary& circuit_lib,
const DeviceGrid& grids,
const TileAnnotation& tile_annotation,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const TileDirect& tile_direct,
const ArchDirect& arch_direct,
const e_config_protocol_type& sram_orgz_type,
const ConfigProtocol& config_protocol,
const CircuitModelId& sram_model,
const bool& frame_view,
const bool& compact_routing_hierarchy,
@ -353,7 +315,7 @@ int build_top_module(ModuleManager& module_manager,
/* Add sub modules, which are grid, SB and CBX/CBY modules as instances */
/* Add all the grids across the fabric */
vtr::Matrix<size_t> grid_instance_ids = add_top_module_grid_instances(module_manager, top_module, io_location_map, grids);
vtr::Matrix<size_t> grid_instance_ids = add_top_module_grid_instances(module_manager, top_module, grids);
/* Add all the SBs across the fabric */
vtr::Matrix<size_t> sb_instance_ids = add_top_module_switch_block_instances(module_manager, top_module, device_rr_gsb, compact_routing_hierarchy);
/* Add all the CBX and CBYs across the fabric */
@ -384,6 +346,12 @@ int build_top_module(ModuleManager& module_manager,
*/
add_module_global_ports_from_child_modules(module_manager, top_module);
/* Add global ports from grid ports that are defined as global in tile annotation */
status = add_top_module_global_ports_from_grid_modules(module_manager, top_module, tile_annotation, grids, grid_instance_ids);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}
/* Add GPIO ports from the sub-modules under this Verilog module
* This is a much easier job after adding sub modules (instances),
* we just need to find all the I/O ports from the child modules and build a list of it
@ -396,13 +364,24 @@ int build_top_module(ModuleManager& module_manager,
*/
if (true == fabric_key.empty()) {
organize_top_module_memory_modules(module_manager, top_module,
circuit_lib, sram_orgz_type, sram_model,
circuit_lib, config_protocol, sram_model,
grids, grid_instance_ids,
device_rr_gsb, sb_instance_ids, cb_instance_ids,
compact_routing_hierarchy);
} else {
VTR_ASSERT_SAFE(false == fabric_key.empty());
/* Give a warning message that the fabric key may overwrite existing region organization.
* Only applicable when number of regions defined in configuration protocol is different
* than the number of regions defined in the fabric key
*/
if (size_t(config_protocol.num_regions()) != fabric_key.regions().size()) {
VTR_LOG_WARN("Fabric key will overwrite the region organization (='%ld') than architecture definition (=%d)!\n",
fabric_key.regions().size(),
config_protocol.num_regions());
}
status = load_top_module_memory_modules_from_fabric_key(module_manager, top_module,
circuit_lib, config_protocol,
fabric_key);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
@ -411,7 +390,7 @@ int build_top_module(ModuleManager& module_manager,
/* Shuffle the configurable children in a random sequence */
if (true == generate_random_fabric_key) {
shuffle_top_module_configurable_children(module_manager, top_module);
shuffle_top_module_configurable_children(module_manager, top_module, config_protocol);
}
/* Add shared SRAM ports from the sub-modules under this Verilog module
@ -427,11 +406,13 @@ int build_top_module(ModuleManager& module_manager,
* This is a much easier job after adding sub modules (instances),
* we just need to find all the I/O ports from the child modules and build a list of it
*/
size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, top_module, circuit_lib, sram_model, sram_orgz_type);
if (0 < module_num_config_bits) {
vtr::vector<ConfigRegionId, size_t> top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type());
if (!top_module_num_config_bits.empty()) {
add_top_module_sram_ports(module_manager, top_module,
circuit_lib, sram_model,
sram_orgz_type, module_num_config_bits);
config_protocol,
top_module_num_config_bits);
}
/* Add module nets to connect memory cells inside
@ -440,8 +421,8 @@ int build_top_module(ModuleManager& module_manager,
if (0 < module_manager.configurable_children(top_module).size()) {
add_top_module_nets_memory_config_bus(module_manager, decoder_lib,
top_module,
sram_orgz_type, circuit_lib.design_tech_type(sram_model),
module_num_config_bits);
config_protocol, circuit_lib.design_tech_type(sram_model),
top_module_num_config_bits);
}
return status;

View File

@ -8,14 +8,15 @@
#include <string>
#include "vtr_geometry.h"
#include "device_grid.h"
#include "tile_annotation.h"
#include "rr_graph_obj.h"
#include "device_rr_gsb.h"
#include "circuit_library.h"
#include "decoder_library.h"
#include "tile_direct.h"
#include "arch_direct.h"
#include "config_protocol.h"
#include "module_manager.h"
#include "io_location_map.h"
#include "fabric_key.h"
/********************************************************************
@ -26,15 +27,15 @@
namespace openfpga {
int build_top_module(ModuleManager& module_manager,
IoLocationMap& io_location_map,
DecoderLibrary& decoder_lib,
const CircuitLibrary& circuit_lib,
const DeviceGrid& grids,
const TileAnnotation& tile_annotation,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const TileDirect& tile_direct,
const ArchDirect& arch_direct,
const e_config_protocol_type& sram_orgz_type,
const ConfigProtocol& config_protocol,
const CircuitModelId& sram_model,
const bool& frame_view,
const bool& compact_routing_hierarchy,

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