diff --git a/.travis.yml b/.travis.yml
index d4f2d90ad..431f5a02c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,87 +1,116 @@
language: cpp
+
+# cache results
+
cache:
directories:
- - "$TRAVIS_BUILD_DIR/abc"
- - "$TRAVIS_BUILD_DIR/yosys"
- - "$TRAVIS_BUILD_DIR/ace2"
- - "$TRAVIS_BUILD_DIR/libs"
- - "$HOME/.ccache"
- - "$HOME/deps"
+ - $TRAVIS_BUILD_DIR/abc
+ - $TRAVIS_BUILD_DIR/yosys
+ - $TRAVIS_BUILD_DIR/ace2
+ - $TRAVIS_BUILD_DIR/libs
+ - $HOME/.ccache
+# - $HOME/deps
+
+# Currently sudo is not required, NO ENV is used
+
+# Supported Operating systems
+#os:
+# - linux
+# - osx
+# Create a matrix to branch the building environment
matrix:
include:
- - os: linux
- sudo: false
- dist: bionic
- compiler: g++-8
- addons:
- apt:
- sources:
- - sourceline: ppa:ubuntu-toolchain-r/test
- packages:
- - autoconf
- - automake
- - bash
- - bison
- - build-essential
- - cmake
- - ctags
- - curl
- - doxygen
- - flex
- - fontconfig
- - g++-8
- - gcc-8
- - gdb
- - git
- - gperf
- - iverilog
- - libcairo2-dev
- - libevent-dev
- - libfontconfig1-dev
- - liblist-moreutils-perl
- - libncurses5-dev
- - libx11-dev
- - libxft-dev
- - libxml++2.6-dev
- - perl
- - python
- - texinfo
- - time
- - valgrind
- - zip
- - qt5-default
+ - os: linux
+ # Compiler is specified in ./travis/common.sh
+ sudo: false
+ dist: bionic
+ compiler: g++-8
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test # For newer GCC
+ - george-edison55-precise-backports # For cmake
+ packages:
+ - autoconf
+ - automake
+ - bash
+ - bison
+ - build-essential
+ - cmake
+ - ctags
+ - curl
+ - doxygen
+ - flex
+ - fontconfig
+ - g++-8
+ - gcc-8
+ - gdb
+ - git
+ - gperf
+ - iverilog
+ - libcairo2-dev
+ - libevent-dev
+ - libfontconfig1-dev
+ - liblist-moreutils-perl
+ - libncurses5-dev
+ - libx11-dev
+ - libxft-dev
+ - libxml++2.6-dev
+ - perl
+ - python
+ - texinfo
+ - time
+ - valgrind
+ - zip
+ - qt5-default
+# - os: osx
+# osx_image: xcode10.2 # we target latest MacOS Mojave
+# sudo: true
+# compiler: gcc-4.9 # Use clang instead of gcc in MacOS
+# addons:
+# homebrew:
+# packages:
+# - bison
+# - cmake
+# - ctags
+# - flex
+# - fontconfig
+# - git
+# - gcc@6
+# - gcc@4.9
+# - gawk
+# - icarus-verilog
+# - libxml++
+# - qt5
+
before_install:
-- openssl aes-256-cbc -K $encrypted_6f6cf68308be_key -iv $encrypted_6f6cf68308be_iv -in deploy_key.enc -out ./deploy_key -d
-- eval "$(ssh-agent -s)"
-- chmod 600 ./deploy_key
-- cp $TRAVIS_BUILD_DIR/deploy_key ~/.ssh/id_rsa
-- echo -e "Host *\n StrictHostKeyChecking no\n" >> ~/.ssh/config
-- ssh u1249762@lab1-1.eng.utah.edu pwd
-- ssh u1249762@lab1-1.eng.utah.edu "mkdir /var/tmp/travis_bc/$TRAVIS_JOB_ID"
-- echo $TRAVIS_JOB_ID >> build_id.txt
-- scp build_id.txt u1249762@lab1-1.eng.utah.edu:/var/tmp/travis_bc/$TRAVIS_JOB_ID/
-- source .travis/common.sh
+ - source .travis/common.sh
+
install:
-- DEPS_DIR="${HOME}/deps"
-- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
-- |
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
- CMAKE_URL="https://cmake.org/files/v3.12/cmake-3.12.4-Linux-x86_64.tar.gz"
- mkdir -p cmake && travis_retry wget --no-clobber --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
- export PATH=${DEPS_DIR}/cmake/bin:${PATH}
- echo ${PATH}
- else
- brew install cmake || brew upgrade cmake
- fi
-- cmake --version
-- cd -
-- source .travis/install.sh
+ - DEPS_DIR="${HOME}/deps"
+ - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
+ - |
+ if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
+ CMAKE_URL="https://cmake.org/files/v3.12/cmake-3.12.4-Linux-x86_64.tar.gz"
+ mkdir -p cmake && travis_retry wget --no-clobber --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
+ export PATH=${DEPS_DIR}/cmake/bin:${PATH}
+ echo ${PATH}
+ else
+ brew install cmake || brew upgrade cmake
+ fi
+ - cmake --version
+ - cd -
+ - source .travis/install.sh
+
script:
-- ".travis/script.sh"
+ - .travis/script.sh
+ #- .travis/regression.sh
+
after_failure:
-- ".travis/after_failure.sh"
+ - .travis/after_failure.sh
+
after_success:
-- ".travis/after_success.sh"
+ - .travis/after_success.sh
notifications:
slack:
secure: L8tzicFh+EKcK21GBA2m3rQ3jmnDdqiRXIZcb0iqYlhT0V5asYvCqwlpPDUDV1wmBXqPgRJBI/jitAJlKFWu74pLTVc6FscUIDYM7S0DJfHEcufLknZx88lMmmV0IsYLQe3/s89tWoudMf1bNBo/8YWzLDffqUQ7s/rTPD9SWLppb01X0Xm158oDlA0rWETs35nuNFgJxWcSyIyIvnRNE3dHjzmBETUR9mYDsUSYlcOI44FMD8rE6emicdkqdn1zVxScobrl4Dt2bPsMfKopgIKK1x+38AuaqQa7t5F5ICnF0WfxmQ6/TcRNwIij0fDu68w/fcU8SyV+Ex5aZBKYUU7PG7ELTOq+q1geDoTlbguvFSIT4EzqErc4hbJmcUn79BKLhdjshZtGihKatntJx2faXYNYGFjwmnPFRYpqsozydztgMjzv4prZ5yoh7jhoDiGj44QcpXlQ9otM17JdfqveowMLHBYzATsxIRG93irZfXG/E3S8FvXg8mYOIEn8UK7H6i8VWL3JHlw8RbpLdNLswZOUlpEaDAeTm5tvYcw7FGH2nlZ2e5aXLxN6dTovSSRztQHbWdJTGG0N+xldBXcCiChmok4nXGReIkMc+99nZjRsiCB0R16tCNb25/p7NAVkItfVe1qRTzdnhi1hdE7LPURK4kxoFRJ6sFVuYjw=
diff --git a/.travis/script.sh b/.travis/script.sh
index 09187ef2a..dc0f1f18a 100755
--- a/.travis/script.sh
+++ b/.travis/script.sh
@@ -19,24 +19,19 @@ end_section "OpenFPGA.build"
start_section "OpenFPGA.TaskTun" "${GREEN}..Running_Regression..${NC}"
cd -
echo -e "Testing single-mode architectures";
-python3 openfpga_flow/scripts/run_fpga_task.py single_mode
-python3 openfpga_flow/scripts/run_fpga_task.py single_mode --remove_run_dir all
-#python3 openfpga_flow/scripts/run_fpga_task.py s298
+python3 openfpga_flow/scripts/run_fpga_task.py single_mode --debug --show_thread_logs
+#python3 openfpga_flow/scripts/run_fpga_task.py s298
echo -e "Testing multi-mode architectures";
-python3 openfpga_flow/scripts/run_fpga_task.py blif_vpr_flow --maxthreads 2
-python3 openfpga_flow/scripts/run_fpga_task.py blif_vpr_flow --remove_run_dir all
+python3 openfpga_flow/scripts/run_fpga_task.py multi_mode --maxthreads 4 --debug --show_thread_logs
echo -e "Testing compact routing techniques";
-python3 openfpga_flow/scripts/run_fpga_task.py compact_routing
-python3 openfpga_flow/scripts/run_fpga_task.py compact_routing --remove_run_dir all
+python3 openfpga_flow/scripts/run_fpga_task.py compact_routing --debug --show_thread_logs
echo -e "Testing tileable architectures";
-python3 openfpga_flow/scripts/run_fpga_task.py tileable_routing
-python3 openfpga_flow/scripts/run_fpga_task.py tileable_routing --remove_run_dir all
+python3 openfpga_flow/scripts/run_fpga_task.py tileable_routing --debug --show_thread_logs
echo -e "Testing Verilog generation with explicit port mapping ";
-python3 openfpga_flow/scripts/run_fpga_task.py explicit_verilog
-python3 openfpga_flow/scripts/run_fpga_task.py explicit_verilog --remove_run_dir all
+python3 openfpga_flow/scripts/run_fpga_task.py explicit_verilog --debug --show_thread_logs
end_section "OpenFPGA.TaskTun"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6f9964539..a6d51a7c3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -182,6 +182,13 @@ set_target_properties(libace ace
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ace2"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ace2")
+# Set output locations to be in the main source tree under the relevant folder
+set_target_properties(libini
+ PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/libs/external/libini"
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/libs/external/libini"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/libs/external/libini")
+
# Set output locations to be in the main source tree under the relevant folder
set_target_properties(libvtrutil
PROPERTIES
diff --git a/libs/external/libini/CMakeLists.txt b/libs/external/libini/CMakeLists.txt
index 2730c6325..c09ff863b 100644
--- a/libs/external/libini/CMakeLists.txt
+++ b/libs/external/libini/CMakeLists.txt
@@ -7,6 +7,7 @@ files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
#Create the library
add_library(libini STATIC
- ${LIB_HEADERS})
+ ${LIB_HEADERS})
+
target_include_directories(libini PUBLIC ${LIB_INCLUDE_DIRS})
-set_target_properties(libini PROPERTIES PREFIX "" LINKER_LANGUAGE CXX)
\ No newline at end of file
+set_target_properties(libini PROPERTIES PREFIX "" LINKER_LANGUAGE CXX)
diff --git a/openfpga_flow/VerilogNetlists/dpram.v b/openfpga_flow/VerilogNetlists/dpram.v
new file mode 100644
index 000000000..45bdbecc0
--- /dev/null
+++ b/openfpga_flow/VerilogNetlists/dpram.v
@@ -0,0 +1,56 @@
+//-----------------------------------------------------
+// Design Name : dual_port_ram_32x512
+// File Name : dpram.v
+// Function : Dual port RAM 32x512
+// Coder : Aurelien Alacchi
+//-----------------------------------------------------
+
+module dual_port_ram_32x512 (
+ input clk,
+ input wen,
+ input ren,
+ input[0:8] waddr,
+ input[0:8] raddr,
+ input[0:31] d_in,
+ output[0:31] d_out );
+
+ dual_port_sram_32x512 memory_0 (
+ .wclk (clk),
+ .wen (wen),
+ .waddr (waddr),
+ .data_in (d_in),
+ .rclk (clk),
+ .ren (ren),
+ .raddr (raddr),
+ .d_out (d_out) );
+
+endmodule
+
+module dual_port_sram_32x512 (
+ input wclk,
+ input wen,
+ input[0:8] waddr,
+ input[0:31] data_in,
+ input rclk,
+ input ren,
+ input[0:8] raddr,
+ output[0:31] d_out );
+
+ reg[0:31] ram[0:511];
+ reg[0:31] internal;
+
+ assign d_out = internal;
+
+ always @(posedge wclk) begin
+ if(wen) begin
+ ram[waddr] <= data_in;
+ end
+ end
+
+ always @(posedge rclk) begin
+ if(ren) begin
+ internal <= ram[raddr];
+ end
+ end
+
+endmodule
diff --git a/openfpga_flow/VerilogNetlists/ff.v b/openfpga_flow/VerilogNetlists/ff.v
index bd556f936..f0097019e 100644
--- a/openfpga_flow/VerilogNetlists/ff.v
+++ b/openfpga_flow/VerilogNetlists/ff.v
@@ -76,9 +76,9 @@ endmodule //End Of Module static_dff
//-----------------------------------------------------
module sc_dff_compact (
/* Global ports go first */
-input pReset, // Reset input
+input reset, // Reset input
//input set, // set input
-input prog_clk, // Clock Input
+input clk, // Clock Input
/* Local ports follow */
input D, // Data Input
output Q, // Q output
@@ -88,8 +88,8 @@ output Qb // Q output
reg q_reg;
//-------------Code Starts Here---------
-always @ ( posedge prog_clk or posedge pReset /*or posedge set*/)
-if (pReset) begin
+always @ ( posedge clk or posedge reset /*or posedge set*/)
+if (reset) begin
q_reg <= 1'b0;
//end else if (set) begin
// q_reg <= 1'b1;
diff --git a/openfpga_flow/VerilogNetlists/mux2.v b/openfpga_flow/VerilogNetlists/mux2.v
new file mode 100644
index 000000000..b539b7a69
--- /dev/null
+++ b/openfpga_flow/VerilogNetlists/mux2.v
@@ -0,0 +1,53 @@
+//-----------------------------------------------------
+// Design Name : MUX2
+// File Name : mux2.v
+// Function : Standard cell (static gate) implementation
+// of 2-input multiplexers
+// Coder : Xifan Tang
+//-----------------------------------------------------
+
+module MUX2(
+ input A, // Data input 0
+ input B, // Data input 1
+ input S0, // Select port
+ output Y // Data output
+ );
+
+ assign Y = S0 ? B : A;
+
+// Note:
+// MUX2 appears will appear in LUTs, routing multiplexers,
+// being a component in combinational loops
+// To help convergence in simulation
+// i.e., to avoid the X (undetermined) signals,
+// the following timing constraints and signal initialization
+// has to be added!
+
+`ifdef ENABLE_TIMING
+// ------ BEGIN Pin-to-pin Timing constraints -----
+ specify
+ (A => Y) = (0.001, 0.001);
+ (B => Y) = (0.001, 0.001);
+ (S0 => Y) = (0.001, 0.001);
+ endspecify
+// ------ END Pin-to-pin Timing constraints -----
+`endif
+
+`ifdef ENABLE_SIGNAL_INITIALIZATION
+// ------ BEGIN driver initialization -----
+ initial begin
+ `ifdef ENABLE_FORMAL_VERIFICATION
+ $deposit(A, 1'b0);
+ $deposit(B, 1'b0);
+ $deposit(S0, 1'b0);
+ `else
+ $deposit(A, $random);
+ $deposit(B, $random);
+ $deposit(S0, $random);
+ `endif
+
+ end
+// ------ END driver initialization -----
+`endif
+
+endmodule
diff --git a/openfpga_flow/arch/template/k4_N4_sram_chain_FC_behavioral_verilog_template.xml b/openfpga_flow/arch/template/k4_N4_sram_chain_FC_behavioral_verilog_template.xml
index 29badf323..0c932d704 100644
--- a/openfpga_flow/arch/template/k4_N4_sram_chain_FC_behavioral_verilog_template.xml
+++ b/openfpga_flow/arch/template/k4_N4_sram_chain_FC_behavioral_verilog_template.xml
@@ -321,12 +321,12 @@
-
+
-
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml
index fa32d4e41..9af75ba69 100644
--- a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml
@@ -379,12 +379,12 @@
-
+
-
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_DPRAM_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_DPRAM_template.xml
index 10cd18ddd..b053a80cd 100644
--- a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_DPRAM_template.xml
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_DPRAM_template.xml
@@ -146,7 +146,7 @@
-
+
@@ -163,8 +163,8 @@
-
-
+
+
@@ -344,14 +344,14 @@
-
+
-
-
+
+
@@ -386,17 +386,17 @@
-
+
-
+
-
+
@@ -421,16 +421,16 @@
-
+
-
-
-
+
+
+
-
+
@@ -613,31 +613,31 @@
-
+
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
-
-
-
-
+
+
+
+
-
-
+
+
@@ -647,8 +647,8 @@
-
-
+
+
@@ -656,8 +656,8 @@
-
-
+
+
@@ -674,13 +674,13 @@
-
-
+
memory_dp.d_in
- memory_dp.clk memory_dp.wen memory_dp.waddr
+ memory_dp.clk memory_dp.wen memory_dp.waddr
memory_dp.d_out
memory_dp.ren memory_dp.raddr
-
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_behavioral_verilog_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_behavioral_verilog_template.xml
index 4d26f30ad..f22464011 100644
--- a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_behavioral_verilog_template.xml
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_behavioral_verilog_template.xml
@@ -379,12 +379,12 @@
-
+
-
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_local_encoder_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_local_encoder_template.xml
index 48e1503c7..fd4ef33fb 100644
--- a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_local_encoder_template.xml
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_local_encoder_template.xml
@@ -379,12 +379,12 @@
-
+
-
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml
index ff9d23ac1..7b20e6ff9 100644
--- a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml
@@ -377,12 +377,12 @@
-
+
-
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_stdcell_mux2_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_stdcell_mux2_template.xml
new file mode 100644
index 000000000..410edebcf
--- /dev/null
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_stdcell_mux2_template.xml
@@ -0,0 +1,1030 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12 5e-12 5e-12
+
+
+ 10e-12 5e-12 5e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12 10e-12
+
+
+ 10e-12 10e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+
+
+
+ 1 1 1 1 1
+ 1 1 1 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 255e-12
+ 255e-12
+ 255e-12
+ 255e-12
+ 255e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 202e-12
+ 202e-12
+ 202e-12
+ 202e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ clb.cin clb.cin_trick clb.regin clb.clk
+ clb.I0[9:0] clb.I1[9:0] clb.O[9:0]
+ clb.cout clb.regout clb.I2[9:0] clb.I3[9:0] clb.O[19:10]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml
index fa32d4e41..9af75ba69 100644
--- a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml
@@ -379,12 +379,12 @@
-
+
-
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml
index ce1615d0b..4cea2b20c 100644
--- a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml
@@ -379,12 +379,12 @@
-
+
-
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tree_mux_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tree_mux_template.xml
index c362da80c..078a876da 100644
--- a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tree_mux_template.xml
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tree_mux_template.xml
@@ -379,12 +379,12 @@
-
+
-
+
diff --git a/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.act b/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.act
index 9bc344191..b91e3bfa6 100644
--- a/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.act
+++ b/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.act
@@ -13,7 +13,6 @@ i_11_ 0.495600 0.504600
i_12_ 0.502800 0.507600
i_13_ 0.494600 0.500600
i_14_ 0.504800 0.502800
-i_15_ 0.487600 0.495200
i_16_ 0.504000 0.505200
i_17_ 0.497400 0.512600
i_18_ 0.502200 0.502200
diff --git a/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.blif b/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.blif
index 7ba78bd10..69f1a70c6 100644
--- a/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.blif
+++ b/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.blif
@@ -1,7 +1,7 @@
# Benchmark "apex2" written by ABC on Tue Mar 12 09:34:21 2019
.model apex2
.inputs i_0_ i_1_ i_2_ i_3_ i_4_ i_5_ i_6_ i_7_ i_8_ i_9_ i_10_ i_11_ i_12_ \
- i_13_ i_14_ i_15_ i_16_ i_17_ i_18_ i_19_ i_20_ i_21_ i_22_ i_23_ i_24_ \
+ i_13_ i_14_ i_16_ i_17_ i_18_ i_19_ i_20_ i_21_ i_22_ i_23_ i_24_ \
i_25_ i_26_ i_27_ i_28_ i_29_ i_30_ i_31_ i_32_ i_33_ i_34_ i_35_ i_36_ \
i_37_ i_38_
.outputs o_0_ o_1_ o_2_
diff --git a/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.v b/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.v
index b1e082d06..5a7719ec8 100644
--- a/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.v
+++ b/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.v
@@ -1,13 +1,12 @@
/* Generated by Yosys 0.8+133 (git sha1 2a2e0a4, gcc 7.3.0 -fPIC -Os) */
-module apex2(i_0_, i_1_, i_2_, i_3_, i_4_, i_5_, i_6_, i_7_, i_8_, i_9_, i_10_, i_11_, i_12_, i_13_, i_14_, i_15_, i_16_, i_17_, i_18_, i_19_, i_20_, i_21_, i_22_, i_23_, i_24_, i_25_, i_26_, i_27_, i_28_, i_29_, i_30_, i_31_, i_32_, i_33_, i_34_, i_35_, i_36_, i_37_, i_38_, o_0_, o_1_, o_2_);
+module apex2(i_0_, i_1_, i_2_, i_3_, i_4_, i_5_, i_6_, i_7_, i_8_, i_9_, i_10_, i_11_, i_12_, i_13_, i_14_, i_16_, i_17_, i_18_, i_19_, i_20_, i_21_, i_22_, i_23_, i_24_, i_25_, i_26_, i_27_, i_28_, i_29_, i_30_, i_31_, i_32_, i_33_, i_34_, i_35_, i_36_, i_37_, i_38_, o_0_, o_1_, o_2_);
input i_0_;
input i_10_;
input i_11_;
input i_12_;
input i_13_;
input i_14_;
- input i_15_;
input i_16_;
input i_17_;
input i_18_;
diff --git a/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.act b/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.act
new file mode 100644
index 000000000..d8c59ec70
--- /dev/null
+++ b/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.act
@@ -0,0 +1,95 @@
+clk 0.5 0.2
+wen 0.5 0.2
+wen_st0 0.5 0.2
+wen_st1 0.5 0.2
+ren 0.5 0.2
+raddr_0_ 0.5 0.2
+raddr_1_ 0.5 0.2
+raddr_2_ 0.5 0.2
+raddr_3_ 0.5 0.2
+raddr_4_ 0.5 0.2
+raddr_5_ 0.5 0.2
+waddr_0_ 0.5 0.2
+waddr_1_ 0.5 0.2
+waddr_2_ 0.5 0.2
+waddr_3_ 0.5 0.2
+waddr_4_ 0.5 0.2
+waddr_5_ 0.5 0.2
+waddr_st0_0_ 0.5 0.2
+waddr_st0_1_ 0.5 0.2
+waddr_st0_2_ 0.5 0.2
+waddr_st0_3_ 0.5 0.2
+waddr_st0_4_ 0.5 0.2
+waddr_st0_5_ 0.5 0.2
+waddr_st1_0_ 0.5 0.2
+waddr_st1_1_ 0.5 0.2
+waddr_st1_2_ 0.5 0.2
+waddr_st1_3_ 0.5 0.2
+waddr_st1_4_ 0.5 0.2
+waddr_st1_5_ 0.5 0.2
+a_0_ 0.5 0.2
+a_1_ 0.5 0.2
+a_2_ 0.5 0.2
+a_3_ 0.5 0.2
+a_4_ 0.5 0.2
+a_5_ 0.5 0.2
+a_6_ 0.5 0.2
+a_st0_0_ 0.5 0.2
+a_st0_1_ 0.5 0.2
+a_st0_2_ 0.5 0.2
+a_st0_3_ 0.5 0.2
+a_st0_4_ 0.5 0.2
+a_st0_5_ 0.5 0.2
+a_st0_6_ 0.5 0.2
+a_st1_0_ 0.5 0.2
+a_st1_1_ 0.5 0.2
+a_st1_2_ 0.5 0.2
+a_st1_3_ 0.5 0.2
+a_st1_4_ 0.5 0.2
+a_st1_5_ 0.5 0.2
+a_st1_6_ 0.5 0.2
+b_0_ 0.5 0.2
+b_1_ 0.5 0.2
+b_2_ 0.5 0.2
+b_3_ 0.5 0.2
+b_4_ 0.5 0.2
+b_5_ 0.5 0.2
+b_6_ 0.5 0.2
+b_st0_0_ 0.5 0.2
+b_st0_1_ 0.5 0.2
+b_st0_2_ 0.5 0.2
+b_st0_3_ 0.5 0.2
+b_st0_4_ 0.5 0.2
+b_st0_5_ 0.5 0.2
+b_st0_6_ 0.5 0.2
+b_st1_0_ 0.5 0.2
+b_st1_1_ 0.5 0.2
+b_st1_2_ 0.5 0.2
+b_st1_3_ 0.5 0.2
+b_st1_4_ 0.5 0.2
+b_st1_5_ 0.5 0.2
+b_st1_6_ 0.5 0.2
+q_0_ 0.5 0.2
+q_1_ 0.5 0.2
+q_2_ 0.5 0.2
+q_3_ 0.5 0.2
+q_4_ 0.5 0.2
+q_5_ 0.5 0.2
+q_6_ 0.5 0.2
+q_7_ 0.5 0.2
+AplusB_0_ 0.5 0.2
+AplusB_1_ 0.5 0.2
+AplusB_2_ 0.5 0.2
+AplusB_3_ 0.5 0.2
+AplusB_4_ 0.5 0.2
+AplusB_5_ 0.5 0.2
+AplusB_6_ 0.5 0.2
+AplusB_7_ 0.5 0.2
+cint01 0.5 0.2
+cint02 0.5 0.2
+cint03 0.5 0.2
+cint04 0.5 0.2
+cint05 0.5 0.2
+cint06 0.5 0.2
+cint07 0.5 0.2
+zero00 0 0
diff --git a/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.blif b/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.blif
new file mode 100644
index 000000000..a76ccdef5
--- /dev/null
+++ b/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.blif
@@ -0,0 +1,126 @@
+# Benchmark pipelined_32b_adder
+.model pipelined_32b_adder
+.inputs clk wen ren raddr_0_ raddr_1_ raddr_2_ raddr_3_ raddr_4_ raddr_5_ waddr_0_ waddr_1_ waddr_2_ waddr_3_ waddr_4_ waddr_5_ a_0_ a_1_ a_2_ a_3_ a_4_ a_5_ a_6_ b_0_ b_1_ b_2_ b_3_ b_4_ b_5_ b_6_
+.outputs q_0_ q_1_ q_2_ q_3_ q_4_ q_5_ q_6_ q_7_
+
+# Start pipeline
+# Pipeline a
+.subckt shift D=a_0_ clk=clk Q=a_st0_0_
+.subckt shift D=a_st0_0_ clk=clk Q=a_st1_0_
+.subckt shift D=a_1_ clk=clk Q=a_st0_1_
+.subckt shift D=a_st0_1_ clk=clk Q=a_st1_1_
+.subckt shift D=a_2_ clk=clk Q=a_st0_2_
+.subckt shift D=a_st0_2_ clk=clk Q=a_st1_2_
+.subckt shift D=a_3_ clk=clk Q=a_st0_3_
+.subckt shift D=a_st0_3_ clk=clk Q=a_st1_3_
+.subckt shift D=a_4_ clk=clk Q=a_st0_4_
+.subckt shift D=a_st0_4_ clk=clk Q=a_st1_4_
+.subckt shift D=a_5_ clk=clk Q=a_st0_5_
+.subckt shift D=a_st0_5_ clk=clk Q=a_st1_5_
+.subckt shift D=a_6_ clk=clk Q=a_st0_6_
+.subckt shift D=a_st0_6_ clk=clk Q=a_st1_6_
+
+# Pipeline b
+.subckt shift D=b_0_ clk=clk Q=b_st0_0_
+.subckt shift D=b_st0_0_ clk=clk Q=b_st1_0_
+.subckt shift D=b_1_ clk=clk Q=b_st0_1_
+.subckt shift D=b_st0_1_ clk=clk Q=b_st1_1_
+.subckt shift D=b_2_ clk=clk Q=b_st0_2_
+.subckt shift D=b_st0_2_ clk=clk Q=b_st1_2_
+.subckt shift D=b_3_ clk=clk Q=b_st0_3_
+.subckt shift D=b_st0_3_ clk=clk Q=b_st1_3_
+.subckt shift D=b_4_ clk=clk Q=b_st0_4_
+.subckt shift D=b_st0_4_ clk=clk Q=b_st1_4_
+.subckt shift D=b_5_ clk=clk Q=b_st0_5_
+.subckt shift D=b_st0_5_ clk=clk Q=b_st1_5_
+.subckt shift D=b_6_ clk=clk Q=b_st0_6_
+.subckt shift D=b_st0_6_ clk=clk Q=b_st1_6_
+
+# Pipeline waddr
+.subckt shift D=waddr_0_ clk=clk Q=waddr_st0_0_
+.subckt shift D=waddr_st0_0_ clk=clk Q=waddr_st1_0_
+.subckt shift D=waddr_1_ clk=clk Q=waddr_st0_1_
+.subckt shift D=waddr_st0_1_ clk=clk Q=waddr_st1_1_
+.subckt shift D=waddr_2_ clk=clk Q=waddr_st0_2_
+.subckt shift D=waddr_st0_2_ clk=clk Q=waddr_st1_2_
+.subckt shift D=waddr_3_ clk=clk Q=waddr_st0_3_
+.subckt shift D=waddr_st0_3_ clk=clk Q=waddr_st1_3_
+.subckt shift D=waddr_4_ clk=clk Q=waddr_st0_4_
+.subckt shift D=waddr_st0_4_ clk=clk Q=waddr_st1_4_
+.subckt shift D=waddr_5_ clk=clk Q=waddr_st0_5_
+.subckt shift D=waddr_st0_5_ clk=clk Q=waddr_st1_5_
+# Pipeline wen
+.subckt shift D=wen clk=clk Q=wen_st0
+.subckt shift D=wen_st0 clk=clk Q=wen_st1
+# End pipeline
+
+# Start adder
+.subckt adder a=a_st1_0_ b=b_st1_0_ cin=zero00 cout=cint01 sumout=AplusB_0_
+.subckt adder a=a_st1_1_ b=b_st1_1_ cin=cint01 cout=cint02 sumout=AplusB_1_
+.subckt adder a=a_st1_2_ b=b_st1_2_ cin=cint02 cout=cint03 sumout=AplusB_2_
+.subckt adder a=a_st1_3_ b=b_st1_3_ cin=cint03 cout=cint04 sumout=AplusB_3_
+.subckt adder a=a_st1_4_ b=b_st1_4_ cin=cint04 cout=cint05 sumout=AplusB_4_
+.subckt adder a=a_st1_5_ b=b_st1_5_ cin=cint05 cout=cint06 sumout=AplusB_5_
+.subckt adder a=a_st1_6_ b=b_st1_6_ cin=cint06 cout=cint07 sumout=AplusB_6_
+.subckt adder a=zero00 b=zero00 cin=cint07 cout=unconn sumout=AplusB_7_
+# End adder
+
+# Start DPRAM
+.subckt dual_port_ram_32x512 clk=clk wen=wen_st1 ren=ren \
+waddr[0]=waddr_st1_0_ waddr[1]=waddr_st1_1_ waddr[2]=waddr_st1_2_ waddr[3]=waddr_st1_3_ waddr[4]=waddr_st1_4_ \
+waddr[5]=waddr_st1_5_ waddr[6]=zero00 waddr[7]=zero00 waddr[8]=zero00 \
+raddr[0]=raddr_0_ raddr[1]=raddr_1_ raddr[2]=raddr_2_ raddr[3]=raddr_3_ raddr[4]=raddr_4_ raddr[5]=raddr_5_ \
+raddr[6]=zero00 raddr[7]=zero00 raddr[8]=zero00 \
+d_in[0]=AplusB_0_ d_in[1]=AplusB_1_ d_in[2]=AplusB_2_ d_in[3]=AplusB_3_ d_in[4]=AplusB_4_ d_in[5]=AplusB_5_ \
+d_in[6]=AplusB_6_ d_in[7]=AplusB_7_ d_in[8]=zero00 d_in[9]=zero00 d_in[10]=zero00 d_in[11]=zero00 \
+d_in[12]=zero00 d_in[13]=zero00 d_in[14]=zero00 d_in[15]=zero00 d_in[16]=zero00 d_in[17]=zero00 \
+d_in[18]=zero00 d_in[19]=zero00 d_in[20]=zero00 d_in[21]=zero00 d_in[22]=zero00 d_in[23]=zero00 \
+d_in[24]=zero00 d_in[25]=zero00 d_in[26]=zero00 d_in[27]=zero00 d_in[28]=zero00 d_in[29]=zero00 \
+d_in[30]=zero00 d_in[31]=zero00 \
+d_out[0]=q_0_ d_out[1]=q_1_ d_out[2]=q_2_ d_out[3]=q_3_ d_out[4]=q_4_ d_out[5]=q_5_ \
+d_out[6]=q_6_ d_out[7]=q_7_ d_out[8]=unconn d_out[9]=unconn d_out[10]=unconn \
+d_out[11]=unconn d_out[12]=unconn d_out[13]=unconn d_out[14]=unconn d_out[15]=unconn \
+d_out[16]=unconn d_out[17]=unconn d_out[18]=unconn d_out[19]=unconn d_out[20]=unconn \
+d_out[21]=unconn d_out[22]=unconn d_out[23]=unconn d_out[24]=unconn d_out[25]=unconn \
+d_out[26]=unconn d_out[27]=unconn d_out[28]=unconn d_out[29]=unconn d_out[30]=unconn d_out[31]=unconn
+# End DPRAM
+
+# Start global variable
+.names zero00
+0
+# End global variable
+
+
+.end
+
+# Start blackbox definition
+.model dual_port_ram_32x512
+.inputs clk ren wen waddr[0] waddr[1] waddr[2] waddr[3] waddr[4] waddr[5] \
+ waddr[6] waddr[7] waddr[8] raddr[0] raddr[1] raddr[2] \
+ raddr[3] raddr[4] raddr[5] raddr[6] raddr[7] raddr[8] \
+ d_in[0] d_in[1] d_in[2] d_in[3] d_in[4] d_in[5] d_in[6] d_in[7] d_in[8] \
+ d_in[9] d_in[10] d_in[11] d_in[12] d_in[13] d_in[14] d_in[15] d_in[16] \
+ d_in[17] d_in[18] d_in[19] d_in[20] d_in[21] d_in[22] d_in[23] d_in[24] \
+ d_in[25] d_in[26] d_in[27] d_in[28] d_in[29] d_in[30] d_in[31]
+.outputs d_out[0] d_out[1] d_out[2] d_out[3] d_out[4] d_out[5] d_out[6] \
+ d_out[7] d_out[8] d_out[9] d_out[10] d_out[11] d_out[12] d_out[13] \
+ d_out[14] d_out[15] d_out[16] d_out[17] d_out[18] d_out[19] d_out[20] \
+ d_out[21] d_out[22] d_out[23] d_out[24] d_out[25] d_out[26] d_out[27] \
+ d_out[28] d_out[29] d_out[30] d_out[31]
+.blackbox
+.end
+
+
+.model adder
+.inputs a b cin
+.outputs cout sumout
+.blackbox
+.end
+
+
+.model shift
+.inputs D clk
+.outputs Q
+.blackbox
+.end
+# End blackbox definition
diff --git a/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.v b/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.v
new file mode 100644
index 000000000..c963eb22f
--- /dev/null
+++ b/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.v
@@ -0,0 +1,107 @@
+//-----------------------------------------------------
+// Design Name : pipelined_8bit_adder
+// File Name : pipelined_8bit_adder.v
+// Function : Pipelined 8-bit adders, whose sum and carry outputs
+// are cached in a memory
+// Coder : Aurelien Alacchi
+//-----------------------------------------------------
+
+`timescale 1 ns/ 1 ps
+
+// To match the port definition in BLIF format, so that we can do verification
+// Each input/output bus is expanded here.
+// In future, we should be able to support buses in verification!
+
+module pipelined_8bit_adder(
+ input clk,
+ input ren,
+ input wen,
+ input raddr_0_,
+ input raddr_1_,
+ input raddr_2_,
+ input raddr_3_,
+ input raddr_4_,
+ input raddr_5_,
+ input waddr_0_,
+ input waddr_1_,
+ input waddr_2_,
+ input waddr_3_,
+ input waddr_4_,
+ input waddr_5_,
+ input a_0_,
+ input a_1_,
+ input a_2_,
+ input a_3_,
+ input a_4_,
+ input a_5_,
+ input a_6_,
+ input b_0_,
+ input b_1_,
+ input b_2_,
+ input b_3_,
+ input b_4_,
+ input b_5_,
+ input b_6_,
+ output q_0_,
+ output q_1_,
+ output q_2_,
+ output q_3_,
+ output q_4_,
+ output q_5_,
+ output q_6_,
+ output q_7_);
+
+ wire [5:0] raddr;
+ wire [5:0] waddr;
+ wire [6:0] a;
+ wire [6:0] b;
+ wire [7:0] q;
+
+
+ assign raddr = { raddr_5_, raddr_4_, raddr_3_, raddr_2_, raddr_1_, raddr_0_ };
+ assign waddr = { waddr_5_, waddr_4_, waddr_3_, waddr_2_, waddr_1_, waddr_0_ };
+ assign a = { a_6_, a_5_, a_4_, a_3_, a_2_, a_1_, a_0_ };
+ assign b = { b_6_, b_5_, b_4_, b_3_, b_2_, b_1_, b_0_ };
+ assign q_7_ = q[7];
+ assign q_6_ = q[6];
+ assign q_5_ = q[5];
+ assign q_4_ = q[4];
+ assign q_3_ = q[3];
+ assign q_2_ = q[2];
+ assign q_1_ = q[1];
+ assign q_0_ = q[0];
+
+ reg[7:0] ram[63:0];
+ reg[6:0] a_st0;
+ reg[6:0] a_st1;
+ reg[6:0] b_st0;
+ reg[6:0] b_st1;
+ reg[8:0] waddr_st0;
+ reg[8:0] waddr_st1;
+ reg wen_st0;
+ reg wen_st1;
+ reg[7:0] q_int;
+
+ wire[7:0] AplusB;
+
+ assign AplusB = a_st1 + b_st1;
+ assign q = q_int;
+
+ always@(posedge clk) begin
+ waddr_st0 <= waddr;
+ waddr_st1 <= waddr_st0;
+ a_st0 <= a;
+ a_st1 <= a_st0;
+ b_st0 <= b;
+ b_st1 <= b_st0;
+ wen_st0 <= wen;
+ wen_st1 <= wen_st0;
+ if(wen_st1) begin
+ ram[waddr_st1] <= AplusB;
+ end
+ if(ren) begin
+ q_int <= ram[raddr];
+ end
+ end
+
+endmodule
diff --git a/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder_formal_random_top_tb.v b/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder_formal_random_top_tb.v
new file mode 100644
index 000000000..4276260c2
--- /dev/null
+++ b/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder_formal_random_top_tb.v
@@ -0,0 +1,267 @@
+//-----------------------------------------------------
+// Design Name : pipelined_8bit_adder_top_formal_verification_random_tb
+// File Name : pipelined_8bit_adder.v
+// Function : Testbench for pipelined 8-bit adders, whose sum and carry outputs
+// are cached in a dual-port memory.
+// This testbench will do a verification of FPGA implementation
+// of the pipelined 8-bit adders against the reference
+// (original) Verilog netlist
+// To provide a practical testing, this testbench will :
+// - Instantiate a pre-programmed FPGA and the proper
+// benchmark
+// - Load memories with random values
+// - Randomly write and read from the memories
+// - Watch for any difference between FPGA and Benchmark
+// outputs, after memories are fully loaded
+//
+// PLEASE USE this testbench instead of the auto-generated test
+// benches when performing verification!
+// Coder : Aurelien Alacchi and Xifan Tang
+//-----------------------------------------------------
+
+`timescale 1 ns/ 100 ps
+
+module pipelined_8bit_adder_top_formal_verification_random_tb();
+ reg clk;
+ reg[5:0] raddr;
+ reg[5:0] waddr;
+ reg ren;
+ reg wen;
+ reg[6:0] a;
+ reg[6:0] b;
+ wire[7:0] q_gfpga;
+ wire[7:0] q_bench;
+ reg[7:0] q_flag;
+
+ pipelined_8bit_adder_top_formal_verification DUT(
+ .clk_fm (clk),
+ .ren_fm (ren),
+ .wen_fm (wen),
+ .raddr_0__fm (raddr[0]),
+ .raddr_1__fm (raddr[1]),
+ .raddr_2__fm (raddr[2]),
+ .raddr_3__fm (raddr[3]),
+ .raddr_4__fm (raddr[4]),
+ .raddr_5__fm (raddr[5]),
+ .waddr_0__fm (waddr[0]),
+ .waddr_1__fm (waddr[1]),
+ .waddr_2__fm (waddr[2]),
+ .waddr_3__fm (waddr[3]),
+ .waddr_4__fm (waddr[4]),
+ .waddr_5__fm (waddr[5]),
+ .a_0__fm (a[0]),
+ .a_1__fm (a[1]),
+ .a_2__fm (a[2]),
+ .a_3__fm (a[3]),
+ .a_4__fm (a[4]),
+ .a_5__fm (a[5]),
+ .a_6__fm (a[6]),
+ .b_0__fm (b[0]),
+ .b_1__fm (b[1]),
+ .b_2__fm (b[2]),
+ .b_3__fm (b[3]),
+ .b_4__fm (b[4]),
+ .b_5__fm (b[5]),
+ .b_6__fm (b[6]),
+ .out_q_0__fm (q_gfpga[0]),
+ .out_q_1__fm (q_gfpga[1]),
+ .out_q_2__fm (q_gfpga[2]),
+ .out_q_3__fm (q_gfpga[3]),
+ .out_q_4__fm (q_gfpga[4]),
+ .out_q_5__fm (q_gfpga[5]),
+ .out_q_6__fm (q_gfpga[6]),
+ .out_q_7__fm (q_gfpga[7])
+ );
+
+ pipelined_8bit_adder ref0(
+ .clk (clk),
+ .ren (ren),
+ .wen (wen),
+ .raddr_0_ (raddr[0]),
+ .raddr_1_ (raddr[1]),
+ .raddr_2_ (raddr[2]),
+ .raddr_3_ (raddr[3]),
+ .raddr_4_ (raddr[4]),
+ .raddr_5_ (raddr[5]),
+ .waddr_0_ (waddr[0]),
+ .waddr_1_ (waddr[1]),
+ .waddr_2_ (waddr[2]),
+ .waddr_3_ (waddr[3]),
+ .waddr_4_ (waddr[4]),
+ .waddr_5_ (waddr[5]),
+ .a_0_ (a[0]),
+ .a_1_ (a[1]),
+ .a_2_ (a[2]),
+ .a_3_ (a[3]),
+ .a_4_ (a[4]),
+ .a_5_ (a[5]),
+ .a_6_ (a[6]),
+ .b_0_ (b[0]),
+ .b_1_ (b[1]),
+ .b_2_ (b[2]),
+ .b_3_ (b[3]),
+ .b_4_ (b[4]),
+ .b_5_ (b[5]),
+ .b_6_ (b[6]),
+ .q_0_ (q_bench[0]),
+ .q_1_ (q_bench[1]),
+ .q_2_ (q_bench[2]),
+ .q_3_ (q_bench[3]),
+ .q_4_ (q_bench[4]),
+ .q_5_ (q_bench[5]),
+ .q_6_ (q_bench[6]),
+ .q_7_ (q_bench[7])
+ );
+
+ integer nb_error = 0;
+ integer count = 0;
+ integer lim_max = 64 - 1;
+ integer write_complete = 0;
+
+//----- Initialization
+ initial begin
+ clk <= 1'b0;
+ a <= 7'h00;
+ b <= 7'h00;
+ wen <= 1'b0;
+ ren <= 1'b0;
+ waddr <= 6'h00;
+ raddr <= 6'h00;
+ while(1) begin
+ #2.5
+ clk <= !clk;
+ end
+ end
+
+//----- Input Stimulis
+ always@(negedge clk) begin
+ if(write_complete == 0) begin
+ wen <= 1'b1;
+ ren <= 1'b0;
+ count <= count + 1;
+ waddr <= waddr + 1;
+ if(count == lim_max) begin
+ write_complete = 1;
+ end
+ end else begin
+ wen <= $random;
+ ren <= $random;
+ waddr <= $random;
+ raddr <= $random;
+ end
+ a <= $random;
+ b <= $random;
+ end
+
+
+ always@(negedge clk) begin
+ if(!(q_gfpga[0] === q_bench[0]) && !(q_bench[0] === 1'bx)) begin
+ q_flag[0] <= 1'b1;
+ end else begin
+ q_flag[0] <= 1'b0;
+ end
+ if(!(q_gfpga[1] === q_bench[1]) && !(q_bench[1] === 1'bx)) begin
+ q_flag[1] <= 1'b1;
+ end else begin
+ q_flag[1] <= 1'b0;
+ end
+ if(!(q_gfpga[2] === q_bench[2]) && !(q_bench[2] === 1'bx)) begin
+ q_flag[2] <= 1'b1;
+ end else begin
+ q_flag[2] <= 1'b0;
+ end
+ if(!(q_gfpga[3] === q_bench[3]) && !(q_bench[3] === 1'bx)) begin
+ q_flag[3] <= 1'b1;
+ end else begin
+ q_flag[3] <= 1'b0;
+ end
+ if(!(q_gfpga[4] === q_bench[4]) && !(q_bench[4] === 1'bx)) begin
+ q_flag[4] <= 1'b1;
+ end else begin
+ q_flag[4] <= 1'b0;
+ end
+ if(!(q_gfpga[5] === q_bench[5]) && !(q_bench[5] === 1'bx)) begin
+ q_flag[5] <= 1'b1;
+ end else begin
+ q_flag[5] <= 1'b0;
+ end
+ if(!(q_gfpga[6] === q_bench[6]) && !(q_bench[6] === 1'bx)) begin
+ q_flag[6] <= 1'b1;
+ end else begin
+ q_flag[6] <= 1'b0;
+ end
+ if(!(q_gfpga[7] === q_bench[7]) && !(q_bench[7] === 1'bx)) begin
+ q_flag[7] <= 1'b1;
+ end else begin
+ q_flag[7] <= 1'b0;
+ end
+ end
+
+
+ always@(posedge q_flag[0]) begin
+ if(q_flag[0]) begin
+ nb_error = nb_error + 1;
+ $display("Mismatch on q_gfpga[0] at time = %t", $realtime);
+ end
+ end
+ always@(posedge q_flag[1]) begin
+ if(q_flag[1]) begin
+ nb_error = nb_error + 1;
+ $display("Mismatch on q_gfpga[1] at time = %t", $realtime);
+ end
+ end
+ always@(posedge q_flag[2]) begin
+ if(q_flag[2]) begin
+ nb_error = nb_error + 1;
+ $display("Mismatch on q_gfpga[2] at time = %t", $realtime);
+ end
+ end
+ always@(posedge q_flag[3]) begin
+ if(q_flag[3]) begin
+ nb_error = nb_error + 1;
+ $display("Mismatch on q_gfpga[3] at time = %t", $realtime);
+ end
+ end
+ always@(posedge q_flag[4]) begin
+ if(q_flag[4]) begin
+ nb_error = nb_error + 1;
+ $display("Mismatch on q_gfpga[4] at time = %t", $realtime);
+ end
+ end
+ always@(posedge q_flag[5]) begin
+ if(q_flag[5]) begin
+ nb_error = nb_error + 1;
+ $display("Mismatch on q_gfpga[5] at time = %t", $realtime);
+ end
+ end
+ always@(posedge q_flag[6]) begin
+ if(q_flag[6]) begin
+ nb_error = nb_error + 1;
+ $display("Mismatch on q_gfpga[6] at time = %t", $realtime);
+ end
+ end
+ always@(posedge q_flag[7]) begin
+ if(q_flag[7]) begin
+ nb_error = nb_error + 1;
+ $display("Mismatch on q_gfpga[7] at time = %t", $realtime);
+ end
+ end
+
+ initial begin
+ $dumpfile("pipelined_8bit_adder_formal.vcd");
+ $dumpvars(1, pipelined_8bit_adder_top_formal_verification_random_tb);
+ end
+
+ initial begin
+ $timeformat(-9, 2, "ns", 20);
+ $display("Simulation start");
+ #1500 // Can be changed by the user for his need
+ if(nb_error == 0) begin
+ $display("Simulation Succeed");
+ end else begin
+ $display("Simulation Failed with %d error(s)", nb_error);
+ end
+ $finish;
+ end
+
+endmodule
diff --git a/openfpga_flow/scripts/run_simulation_task.py b/openfpga_flow/scripts/run_simulation_task.py
new file mode 100644
index 000000000..ad1e5f863
--- /dev/null
+++ b/openfpga_flow/scripts/run_simulation_task.py
@@ -0,0 +1,71 @@
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# Script Name : regression.py
+# Description : This script designed to run:
+# openfpga_flow tasks
+# run_{simulator}.py
+# Args : python3 regression.py --help
+# Author : Aurelien Alacchi
+# Email : aurelien.alacchi@utah.edu
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+
+import os
+import sys
+import shutil
+import time
+from datetime import timedelta
+import shlex
+import argparse
+from configparser import ConfigParser, ExtendedInterpolation
+import logging
+import glob
+import subprocess
+import threading
+import csv
+from string import Template
+import pprint
+from importlib import util
+from collections import OrderedDict
+
+modelsim="modelsim"
+vcs="vcs"
+formality="formality"
+modelsim_file="simulation_deck_info.ini"
+ini_list=""
+
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# Parse commandline arguments
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+parser = argparse.ArgumentParser()
+parser.add_argument('tasks', nargs='+')
+parser.add_argument('--maxthreads', type=int, default=2,
+ help="Number of fpga_flow threads to run default = 2," +
+ "Typically <= Number of processors on the system")
+parser.add_argument('--simulator', type=str, default=modelsim,
+ help="Simulator to use. Set at \"" + modelsim + "\" by default. Can also be \"" + vcs + "\" or \"" + formality + "\"")
+args = parser.parse_args()
+
+
+args.tasks=str(args.tasks).strip('[]')
+#print(args.tasks)
+#print(args.maxthreads)
+
+command="python3 openfpga_flow/scripts/run_fpga_task.py " + args.tasks + " --maxthreads " + str(args.maxthreads) + " --debug --show_thread_logs"
+
+print(command)
+
+os.system(command)
+
+if(args.simulator == modelsim):
+ command="python3 openfpga_flow/scripts/run_modelsim.py"
+ os.system("grep \"INFO - Run directory :\" openfpga_flow/tasks/" + args.tasks + "/latest/*.log > paths_ini.txt")
+ arguments = " --skip_prompt --run_sim";
+ fp = open("paths_ini.txt")
+ line = fp.readline()
+ while line:
+ ini_list= ini_list + line + modelsim_file
+ line = fp.readline()
+ ini_list = ini_list.replace("INFO - Run directory :", "")
+ ini_list = ini_list.replace("\n", "/")
+ fp.close()
+ print(command + ini_list + arguments)
+ os.system(command + ini_list + arguments)
diff --git a/openfpga_flow/tasks/blif_vpr_flow/config/task.conf b/openfpga_flow/tasks/blif_vpr_flow/config/task.conf
deleted file mode 100644
index 152fcd6be..000000000
--- a/openfpga_flow/tasks/blif_vpr_flow/config/task.conf
+++ /dev/null
@@ -1,66 +0,0 @@
-# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
-# Configuration file for running experiments
-# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
-# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
-# Each job execute fpga_flow script on combination of architecture & benchmark
-# timeout_each_job is timeout for each job
-# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
-
-[GENERAL]
-power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
-power_analysis = true
-spice_output=false
-verilog_output=true
-timeout_each_job = 20*60
-fpga_flow=vpr_blif
-
-[ARCHITECTURES]
-# arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_DPRAM_template.xml
-arch1=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml
-arch2=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_local_encoder_template.xml
-arch3=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_behavioral_verilog_template.xml
-arch4=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml
-arch5=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml
-#arch5=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tree_mux_template.xml
-#arch4=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k8_N10_sram_chain_FC_template.xml
-
-[BENCHMARKS]
-bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.blif
-
-[SYNTHESIS_PARAM]
-bench0_top = test_modes
-bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.act
-bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.v
-bench0_chan_width = 300
-
-#[SCRIPT_PARAM_FIX_ROUTE_CHAN_WIDTH]
-#fix_route_chan_width=300
-#vpr_fpga_verilog_include_icarus_simulator=
-#vpr_fpga_verilog_formal_verification_top_netlist=
-#vpr_fpga_verilog_include_timing=
-#vpr_fpga_verilog_include_signal_init=
-#vpr_fpga_verilog_print_autocheck_top_testbench=
-#vpr_fpga_bitstream_generator=
-#vpr_fpga_verilog_print_user_defined_template=
-#vpr_fpga_verilog_print_report_timing_tcl=
-#vpr_fpga_verilog_print_sdc_pnr=
-#vpr_fpga_verilog_print_sdc_analysis=
-##vpr_fpga_x2p_compact_routing_hierarchy=
-#end_flow_with_test=
-
-[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
-min_route_chan_width=1.3
-vpr_fpga_verilog_include_icarus_simulator=
-vpr_fpga_verilog_formal_verification_top_netlist=
-vpr_fpga_verilog_include_timing=
-vpr_fpga_verilog_include_signal_init=
-vpr_fpga_verilog_print_autocheck_top_testbench=
-vpr_fpga_bitstream_generator=
-vpr_fpga_verilog_print_user_defined_template=
-vpr_fpga_verilog_print_report_timing_tcl=
-vpr_fpga_verilog_print_sdc_pnr=
-vpr_fpga_verilog_print_sdc_analysis=
-#vpr_fpga_verilog_explicit_mapping=
-#vpr_fpga_x2p_compact_routing_hierarchy=
-end_flow_with_test=
-
diff --git a/openfpga_flow/tasks/heterogeneous_dpram/config/task.conf b/openfpga_flow/tasks/heterogeneous_dpram/config/task.conf
new file mode 100644
index 000000000..b567b74e0
--- /dev/null
+++ b/openfpga_flow/tasks/heterogeneous_dpram/config/task.conf
@@ -0,0 +1,43 @@
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# Configuration file for running experiments
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
+# Each job execute fpga_flow script on combination of architecture & benchmark
+# timeout_each_job is timeout for each job
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+
+[GENERAL]
+power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
+power_analysis = true
+spice_output=false
+verilog_output=true
+timeout_each_job = 20*60
+fpga_flow=vpr_blif
+
+[ARCHITECTURES]
+arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_DPRAM_template.xml
+
+[BENCHMARKS]
+bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.blif
+
+[SYNTHESIS_PARAM]
+bench0_top = pipelined_8bit_adder
+bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.act
+bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/pipelined_8bit_adder/pipelined_8bit_adder.v
+bench0_chan_width = 100
+
+[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
+min_route_chan_width=1.3
+vpr_fpga_verilog_include_icarus_simulator=
+vpr_fpga_verilog_formal_verification_top_netlist=
+vpr_fpga_verilog_include_timing=
+vpr_fpga_verilog_include_signal_init=
+vpr_fpga_verilog_print_autocheck_top_testbench=
+vpr_fpga_bitstream_generator=
+#vpr_fpga_verilog_print_user_defined_template=
+#vpr_fpga_verilog_print_report_timing_tcl=
+#vpr_fpga_verilog_print_sdc_pnr=
+#vpr_fpga_verilog_print_sdc_analysis=
+vpr_fpga_verilog_explicit_mapping=
+vpr_fpga_x2p_compact_routing_hierarchy=
+end_flow_with_test=
diff --git a/openfpga_flow/tasks/mcnc_big20/config/task.conf b/openfpga_flow/tasks/mcnc_big20/config/task.conf
index 50d2402b8..05961d06b 100644
--- a/openfpga_flow/tasks/mcnc_big20/config/task.conf
+++ b/openfpga_flow/tasks/mcnc_big20/config/task.conf
@@ -15,15 +15,19 @@ timeout_each_job = 20*60
fpga_flow=vpr_blif
[ARCHITECTURES]
-arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml
+#arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml
#arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k4_N4_sram_chain_FC_behavioral_verilog_template.xml
-#arch1=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml
+arch1=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml
[BENCHMARKS]
-bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/alu4/alu4.blif
+# Pass
+#bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/alu4/alu4.blif
+# Pass, but port does not match, i_15_ is dangling
#bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/apex2/apex2.blif
+# Pass
#bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/apex4/apex4.blif
-#bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/bigkey/bigkey.blif
+bench3=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/bigkey/bigkey.blif
+# To be tested
#bench4=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/clma/clma.blif
#bench5=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/des/des.blif
#bench6=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/diffeq/diffeq.blif
@@ -34,8 +38,10 @@ bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/alu4/alu4.blif
#bench11=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/frisc/frisc.blif
#bench12=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/misex3/misex3.blif
#bench13=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/pdc/pdc.blif
-#bench14=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/s298/s298.blif # Pass
-#bench15=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/s38417/s38417.blif # Multi-mode support fails to repack
+# Pass
+#bench14=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/s298/s298.blif
+# Multi-mode support fails to repack
+#bench15=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/s38417/s38417.blif
#bench16=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/s38584/s38584.blif
#bench17=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/seq/seq.blif
#bench18=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/mcnc_big20/spla/spla.blif
@@ -147,10 +153,10 @@ vpr_fpga_verilog_include_signal_init=
vpr_fpga_verilog_print_autocheck_top_testbench=
vpr_fpga_bitstream_generator=
vpr_fpga_verilog_print_user_defined_template=
-vpr_fpga_verilog_print_report_timing_tcl=
-vpr_fpga_verilog_print_sdc_pnr=
-vpr_fpga_verilog_print_sdc_analysis=
+#vpr_fpga_verilog_print_report_timing_tcl=
+#vpr_fpga_verilog_print_sdc_pnr=
+#vpr_fpga_verilog_print_sdc_analysis=
vpr_fpga_verilog_explicit_mapping=
vpr_fpga_x2p_compact_routing_hierarchy=
-end_flow_with_test=
+#end_flow_with_test=
diff --git a/openfpga_flow/tasks/multi_mode/config/task.conf b/openfpga_flow/tasks/multi_mode/config/task.conf
index 5157bb235..18f471cf7 100644
--- a/openfpga_flow/tasks/multi_mode/config/task.conf
+++ b/openfpga_flow/tasks/multi_mode/config/task.conf
@@ -16,15 +16,21 @@ fpga_flow=vpr_blif
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml
+arch1=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_local_encoder_template.xml
+arch2=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_behavioral_verilog_template.xml
+arch3=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml
+arch4=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml
+arch5=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tree_mux_template.xml
+arch6=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_stdcell_mux2_template.xml
[BENCHMARKS]
-bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/test_modes/k4_N4/K4N4_test_modes.blif
+bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.blif
[SYNTHESIS_PARAM]
-bench0_top = K4n4_test
-bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/test_modes/k4_N4/K4N4_test_modes.act
-bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/test_modes/k4_N4/K4N4_test_modes.v
-bench0_chan_width = 100
+bench0_top = test_modes
+bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.act
+bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/test_modes/k6_N10/K6N10_test_modes.v
+bench0_chan_width = 300
#[SCRIPT_PARAM_FIX_ROUTE_CHAN_WIDTH]
#fix_route_chan_width=300
@@ -38,10 +44,10 @@ bench0_chan_width = 100
#vpr_fpga_verilog_print_report_timing_tcl=
#vpr_fpga_verilog_print_sdc_pnr=
#vpr_fpga_verilog_print_sdc_analysis=
-#vpr_fpga_x2p_compact_routing_hierarchy=
+##vpr_fpga_x2p_compact_routing_hierarchy=
#end_flow_with_test=
-[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH_0]
+[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
min_route_chan_width=1.3
vpr_fpga_verilog_include_icarus_simulator=
vpr_fpga_verilog_formal_verification_top_netlist=
@@ -56,3 +62,4 @@ vpr_fpga_verilog_print_sdc_analysis=
#vpr_fpga_verilog_explicit_mapping=
#vpr_fpga_x2p_compact_routing_hierarchy=
end_flow_with_test=
+
diff --git a/openfpga_flow/tasks/single_mode/config/task.conf b/openfpga_flow/tasks/single_mode/config/task.conf
index 4d721002b..e3e2d3e8c 100644
--- a/openfpga_flow/tasks/single_mode/config/task.conf
+++ b/openfpga_flow/tasks/single_mode/config/task.conf
@@ -55,4 +55,5 @@ vpr_fpga_verilog_print_sdc_pnr=
vpr_fpga_verilog_print_sdc_analysis=
vpr_fpga_verilog_explicit_mapping=
vpr_fpga_x2p_compact_routing_hierarchy=
+#vpr_fpga_verilog_print_simulation_ini=
end_flow_with_test=
diff --git a/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp b/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp
index 4ceab180e..bf70df367 100644
--- a/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp
+++ b/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp
@@ -410,7 +410,7 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
for (size_t iport = 0; iport < global_ports.size() - 1; ++iport) {
for (size_t jport = iport + 1; jport < global_ports.size(); ++jport) {
/* Bypass those do not share the same name */
- if (0 != circuit_lib.port_lib_name(global_ports[iport]).compare(circuit_lib.port_lib_name(global_ports[jport]))) {
+ if (0 != circuit_lib.port_prefix(global_ports[iport]).compare(circuit_lib.port_prefix(global_ports[jport]))) {
continue;
}
@@ -421,7 +421,7 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
if (circuit_lib.port_default_value(global_ports[iport]) != circuit_lib.port_default_value(global_ports[jport])) {
vpr_printf(TIO_MESSAGE_ERROR,
"Global ports %s from circuit model %s and %s share the same name but have different dfefault values(%lu and %lu)!\n",
- circuit_lib.port_lib_name(global_ports[iport]).c_str(),
+ circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str(),
circuit_lib.port_default_value(global_ports[iport]),
@@ -433,7 +433,7 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
if (circuit_lib.port_is_reset(global_ports[iport]) != circuit_lib.port_is_reset(global_ports[jport])) {
vpr_printf(TIO_MESSAGE_ERROR,
"Global ports %s from circuit model %s and %s share the same name but have different is_reset attributes!\n",
- circuit_lib.port_lib_name(global_ports[iport]).c_str(),
+ circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str()
);
@@ -442,7 +442,7 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
if (circuit_lib.port_is_set(global_ports[iport]) != circuit_lib.port_is_set(global_ports[jport])) {
vpr_printf(TIO_MESSAGE_ERROR,
"Global ports %s from circuit model %s and %s share the same name but have different is_set attributes!\n",
- circuit_lib.port_lib_name(global_ports[iport]).c_str(),
+ circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str()
);
@@ -451,7 +451,7 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
if (circuit_lib.port_is_config_enable(global_ports[iport]) != circuit_lib.port_is_config_enable(global_ports[jport])) {
vpr_printf(TIO_MESSAGE_ERROR,
"Global ports %s from circuit model %s and %s share the same name but have different is_config_enable attributes!\n",
- circuit_lib.port_lib_name(global_ports[iport]).c_str(),
+ circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str()
);
@@ -460,7 +460,7 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
if (circuit_lib.port_is_prog(global_ports[iport]) != circuit_lib.port_is_prog(global_ports[jport])) {
vpr_printf(TIO_MESSAGE_ERROR,
"Global ports %s from circuit model %s and %s share the same name but have different is_prog attributes!\n",
- circuit_lib.port_lib_name(global_ports[iport]).c_str(),
+ circuit_lib.port_prefix(global_ports[iport]).c_str(),
circuit_lib.model_name(iport_parent_model).c_str(),
circuit_lib.model_name(jport_parent_model).c_str()
);
@@ -579,14 +579,17 @@ void check_circuit_library(const CircuitLibrary& circuit_lib) {
num_err += check_required_default_circuit_model(circuit_lib, SPICE_MODEL_WIRE);
/* If we have any errors, exit */
- vpr_printf(TIO_MESSAGE_INFO,
- "Finished checking circuit library with %d errors!\n",
- num_err);
if (0 < num_err) {
+ vpr_printf(TIO_MESSAGE_INFO,
+ "Finished checking circuit library with %d errors!\n",
+ num_err);
exit(1);
}
+ vpr_printf(TIO_MESSAGE_INFO,
+ "Checking circuit library passed.\n");
+
return;
}
diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp
index cb7641b0a..22145b38f 100644
--- a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp
+++ b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp
@@ -226,7 +226,7 @@ std::vector find_circuit_library_global_ports(const CircuitLibrar
/* Check if a same port with the same name has already been in the list */
bool add_to_list = true;
for (const auto& global_port : global_ports) {
- if (0 == circuit_lib.port_lib_name(port).compare(circuit_lib.port_lib_name(global_port))) {
+ if (0 == circuit_lib.port_prefix(port).compare(circuit_lib.port_prefix(global_port))) {
/* Same name, skip list update */
add_to_list = false;
break;
@@ -240,3 +240,26 @@ std::vector find_circuit_library_global_ports(const CircuitLibrar
return global_ports;
}
+
+/********************************************************************
+ * A generic function to find all the unique user-defined
+ * Verilog netlists in a circuit library
+ * Netlists with same names will be considered as one
+ *******************************************************************/
+std::vector find_circuit_library_unique_verilog_netlists(const CircuitLibrary& circuit_lib) {
+ std::vector netlists;
+
+ for (const CircuitModelId& model : circuit_lib.models()) {
+ /* Skip empty netlist names */
+ if (true == circuit_lib.model_verilog_netlist(model).empty()) {
+ continue;
+ }
+ /* See if the netlist name is already in the list */
+ std::vector::iterator it = std::find(netlists.begin(), netlists.end(), circuit_lib.model_verilog_netlist(model));
+ if (it == netlists.end()) {
+ netlists.push_back(circuit_lib.model_verilog_netlist(model));
+ }
+ }
+
+ return netlists;
+}
diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h
index c0c8251c7..056777c61 100644
--- a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h
+++ b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h
@@ -29,4 +29,6 @@ size_t find_circuit_num_config_bits(const CircuitLibrary& circuit_lib,
std::vector find_circuit_library_global_ports(const CircuitLibrary& circuit_lib);
+std::vector find_circuit_library_unique_verilog_netlists(const CircuitLibrary& circuit_lib);
+
#endif
diff --git a/vpr7_x2p/vpr/CMakeLists.txt b/vpr7_x2p/vpr/CMakeLists.txt
index 0fa11717e..2e70b82fa 100644
--- a/vpr7_x2p/vpr/CMakeLists.txt
+++ b/vpr7_x2p/vpr/CMakeLists.txt
@@ -65,14 +65,14 @@ if (ENABLE_VPR_GRAPHIC_CXX_FLAG)
libarchfpga
X11
libvtrutil
- readline
- libini)
+ libini
+ readline)
else ()
target_link_libraries(libvpr
libarchfpga
libvtrutil
- readline
- libini)
+ libini
+ readline)
endif()
#Create the executables
diff --git a/vpr7_x2p/vpr/SRC/base/OptionTokens.c b/vpr7_x2p/vpr/SRC/base/OptionTokens.c
index 78b956ce3..b8ef5c44a 100644
--- a/vpr7_x2p/vpr/SRC/base/OptionTokens.c
+++ b/vpr7_x2p/vpr/SRC/base/OptionTokens.c
@@ -100,6 +100,8 @@ struct s_TokenPair OptionBaseTokenList[] = {
{ "fpga_verilog_report_timing_rpt_path", OT_FPGA_VERILOG_SYN_REPORT_TIMING_RPT_PATH }, /* Specify the simulator path for Verilog netlists */
{ "fpga_verilog_print_sdc_pnr", OT_FPGA_VERILOG_SYN_PRINT_SDC_PNR }, /* Specify the simulator path for Verilog netlists */
{ "fpga_verilog_print_sdc_analysis", OT_FPGA_VERILOG_SYN_PRINT_SDC_ANALYSIS }, /* Specify the simulator path for Verilog netlists */
+ { "fpga_verilog_print_simulation_ini", OT_FPGA_VERILOG_SYN_PRINT_SIMULATION_INI }, /* Specify the simulator path for Verilog netlists */
+ { "fpga_verilog_simulation_ini_file", OT_FPGA_VERILOG_SYN_SIMULATION_INI_FILE }, /* Specify the simulator path for Verilog netlists */
/* Xifan Tang: Bitstream generator */
{ "fpga_bitstream_generator", OT_FPGA_BITSTREAM_GENERATOR }, /* turn on bitstream generator, and specify the output file */
// { "fpga_bitstream_output_file", OT_FPGA_BITSTREAM_OUTPUT_FILE }, /* turn on bitstream generator, and specify the output file */ // AA: temporarily deprecated
diff --git a/vpr7_x2p/vpr/SRC/base/OptionTokens.h b/vpr7_x2p/vpr/SRC/base/OptionTokens.h
index 46a44ac05..5b20ef1cd 100644
--- a/vpr7_x2p/vpr/SRC/base/OptionTokens.h
+++ b/vpr7_x2p/vpr/SRC/base/OptionTokens.h
@@ -117,6 +117,8 @@ enum e_OptionBaseToken {
OT_FPGA_VERILOG_SYN_REPORT_TIMING_RPT_PATH,
OT_FPGA_VERILOG_SYN_PRINT_SDC_PNR,
OT_FPGA_VERILOG_SYN_PRINT_SDC_ANALYSIS,
+ OT_FPGA_VERILOG_SYN_PRINT_SIMULATION_INI,
+ OT_FPGA_VERILOG_SYN_SIMULATION_INI_FILE,
/* Xifan Tang: Bitstream generator */
OT_FPGA_BITSTREAM_GENERATOR,
OT_FPGA_BITSTREAM_OUTPUT_FILE,
diff --git a/vpr7_x2p/vpr/SRC/base/ReadOptions.c b/vpr7_x2p/vpr/SRC/base/ReadOptions.c
index 108e9d355..e51dcf530 100644
--- a/vpr7_x2p/vpr/SRC/base/ReadOptions.c
+++ b/vpr7_x2p/vpr/SRC/base/ReadOptions.c
@@ -559,6 +559,10 @@ ProcessOption(INP char **Args, INOUTP t_options * Options) {
return Args;
case OT_FPGA_VERILOG_SYN_PRINT_SDC_ANALYSIS:
return Args;
+ case OT_FPGA_VERILOG_SYN_PRINT_SIMULATION_INI:
+ return Args;
+ case OT_FPGA_VERILOG_SYN_SIMULATION_INI_FILE:
+ return ReadString(Args, &Options->fpga_verilog_simulation_ini_path);
/* Xifan TANG: Bitstream generator */
case OT_FPGA_BITSTREAM_GENERATOR:
return Args;
diff --git a/vpr7_x2p/vpr/SRC/base/ReadOptions.h b/vpr7_x2p/vpr/SRC/base/ReadOptions.h
index a637f5792..a242ba0b1 100644
--- a/vpr7_x2p/vpr/SRC/base/ReadOptions.h
+++ b/vpr7_x2p/vpr/SRC/base/ReadOptions.h
@@ -107,6 +107,7 @@ struct s_options {
char* fpga_verilog_reference_benchmark_file;
char* fpga_verilog_modelsim_ini_path;
char* fpga_verilog_report_timing_path;
+ char* fpga_verilog_simulation_ini_path;
/* Xifan TANG: Bitstream generator */
char* fpga_bitstream_file;
};
diff --git a/vpr7_x2p/vpr/SRC/base/SetupVPR.c b/vpr7_x2p/vpr/SRC/base/SetupVPR.c
index 5b0e90004..f1443c4f7 100644
--- a/vpr7_x2p/vpr/SRC/base/SetupVPR.c
+++ b/vpr7_x2p/vpr/SRC/base/SetupVPR.c
@@ -1113,6 +1113,8 @@ static void SetupSynVerilogOpts(t_options Options,
syn_verilog_opts->print_sdc_pnr = FALSE;
syn_verilog_opts->print_sdc_analysis = FALSE;
syn_verilog_opts->include_icarus_simulator = FALSE;
+ syn_verilog_opts->print_simulation_ini = FALSE;
+ syn_verilog_opts->simulation_ini_path = NULL;
/* Turn on Syn_verilog options */
if (Options.Count[OT_FPGA_VERILOG_SYN]) {
@@ -1183,6 +1185,14 @@ static void SetupSynVerilogOpts(t_options Options,
syn_verilog_opts->print_sdc_analysis = TRUE;
}
+ if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_SIMULATION_INI]) {
+ syn_verilog_opts->print_simulation_ini = TRUE;
+
+ if (Options.Count[OT_FPGA_VERILOG_SYN_SIMULATION_INI_FILE]) {
+ syn_verilog_opts->simulation_ini_path = my_strdup(Options.fpga_verilog_simulation_ini_path);
+ }
+ }
+
/* SynVerilog needs the input from spice modeling */
if (FALSE == arch->read_xml_spice) {
arch->read_xml_spice = syn_verilog_opts->dump_syn_verilog;
diff --git a/vpr7_x2p/vpr/SRC/base/vpr_api.c b/vpr7_x2p/vpr/SRC/base/vpr_api.c
index 7d1730883..3b2471a72 100644
--- a/vpr7_x2p/vpr/SRC/base/vpr_api.c
+++ b/vpr7_x2p/vpr/SRC/base/vpr_api.c
@@ -211,6 +211,8 @@ void vpr_print_usage(void) {
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_verilog_report_timing_rpt_path \n");
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_verilog_print_sdc_pnr\n");
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_verilog_print_sdc_analysis\n");
+ vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_verilog_print_simulation_ini\n");
+ vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_verilog_simulation_ini_file \n");
/* Xifan Tang: Bitstream generator */
vpr_printf(TIO_MESSAGE_INFO, "Bitstream Generator Options:\n");
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_bitstream_generator\n");
diff --git a/vpr7_x2p/vpr/SRC/base/vpr_types.h b/vpr7_x2p/vpr/SRC/base/vpr_types.h
index 7b87d664a..0c3491d8d 100755
--- a/vpr7_x2p/vpr/SRC/base/vpr_types.h
+++ b/vpr7_x2p/vpr/SRC/base/vpr_types.h
@@ -1281,6 +1281,8 @@ struct s_syn_verilog_opts {
boolean print_report_timing_tcl;
boolean print_sdc_pnr;
boolean print_sdc_analysis;
+ boolean print_simulation_ini;
+ char* simulation_ini_path;
};
/* Xifan TANG: bitstream generator */
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.cpp
new file mode 100644
index 000000000..9eac8c52a
--- /dev/null
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.cpp
@@ -0,0 +1,624 @@
+/********************************************************************
+ * This file includes functions that are used to write SDC commands
+ * to disable unused ports of grids, such as Configurable Logic Block
+ * (CLBs), heterogeneous blocks, etc.
+ *******************************************************************/
+#include "vtr_assert.h"
+
+#include "fpga_x2p_reserved_words.h"
+#include "fpga_x2p_naming.h"
+#include "fpga_x2p_utils.h"
+#include "fpga_x2p_pbtypes_utils.h"
+
+#include "sdc_writer_utils.h"
+#include "analysis_sdc_writer_utils.h"
+#include "analysis_sdc_grid_writer.h"
+
+#include "globals.h"
+
+/********************************************************************
+ * Recursively visit all the pb_types in the hierarchy
+ * and disable all the ports
+ *
+ * Note: it is a must to disable all the ports in all the child pb_types!
+ * This can prohibit timing analyzer to consider any FF-to-FF path or
+ * combinatinal path inside an unused grid, when finding critical paths!!!
+ *******************************************************************/
+static
+void rec_print_analysis_sdc_disable_unused_pb_graph_nodes(std::fstream& fp,
+ const ModuleManager& module_manager,
+ const ModuleId& parent_module,
+ const std::string& hierarchy_name,
+ t_pb_graph_node* physical_pb_graph_node,
+ const e_side& border_side) {
+ t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type;
+
+ /* Validate file stream */
+ check_file_handler(fp);
+
+ /* Disable all the ports of current module (parent_module)!
+ * Hierarchy name already includes the instance name of parent_module
+ */
+ fp << "set_disable_timing ";
+ fp << hierarchy_name;
+ fp << "/*";
+ fp << std::endl;
+
+ /* Return if this is the primitive pb_type */
+ if (TRUE == is_primitive_pb_type(physical_pb_type)) {
+ return;
+ }
+
+ /* Go recursively */
+ int physical_mode_index = find_pb_type_physical_mode_index(*physical_pb_type);
+
+ /* Disable all the ports by iterating over its instance in the parent module */
+ for (int ichild = 0; ichild < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ichild) {
+ /* Generate the name of the Verilog module for this child */
+ std::string child_module_name_prefix = generate_grid_block_prefix(std::string(GRID_MODULE_NAME_PREFIX), border_side);
+ std::string child_module_name = generate_physical_block_module_name(child_module_name_prefix, &(physical_pb_type->modes[physical_mode_index].pb_type_children[ichild]));
+
+ ModuleId child_module = module_manager.find_module(child_module_name);
+ VTR_ASSERT(true == module_manager.valid_module_id(child_module));
+
+ /* Each child may exist multiple times in the hierarchy*/
+ for (int inst = 0; inst < physical_pb_type->modes[physical_mode_index].pb_type_children[ichild].num_pb; ++inst) {
+ std::string child_instance_name = module_manager.instance_name(parent_module, child_module, module_manager.child_module_instances(parent_module, child_module)[inst]);
+ /* Must have a valid instance name!!! */
+ VTR_ASSERT(false == child_instance_name.empty());
+
+ std::string updated_hierarchy_name = hierarchy_name + std::string("/") + child_instance_name + std::string("/");
+
+ rec_print_analysis_sdc_disable_unused_pb_graph_nodes(fp, module_manager, child_module, hierarchy_name,
+ &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ichild][inst]),
+ border_side);
+ }
+ }
+}
+
+/********************************************************************
+ * Disable an unused pin of a pb_graph_node (parent_module)
+ *******************************************************************/
+static
+void disable_pb_graph_node_unused_pin(std::fstream& fp,
+ const ModuleManager& module_manager,
+ const ModuleId& parent_module,
+ const std::string& hierarchy_name,
+ const t_pb_graph_pin& pb_graph_pin,
+ t_phy_pb* block_physical_pb) {
+ /* Validate file stream */
+ check_file_handler(fp);
+
+ int rr_node_index = pb_graph_pin.rr_node_index_physical_pb;
+
+ /* Identify if the net has been used or not */
+ if (false == is_rr_node_to_be_disable_for_analysis(&(block_physical_pb->rr_graph->rr_node[rr_node_index]))) {
+ /* Used pin; Nothing to do */
+ return;
+ }
+ /* Reach here, it means that this pin is not used. Disable timing analysis for the pin */
+ /* Find the module port by name */
+ std::string module_port_name = generate_pb_type_port_name(pb_graph_pin.port);
+ ModulePortId module_port = module_manager.find_module_port(parent_module, module_port_name);
+ VTR_ASSERT(true == module_manager.valid_module_port_id(parent_module, module_port));
+ BasicPort port_to_disable = module_manager.module_port(parent_module, module_port);
+ port_to_disable.set_width(pb_graph_pin.pin_number, pb_graph_pin.pin_number);
+
+ fp << "set_disable_timing ";
+ fp << hierarchy_name;
+ fp << "/";
+ fp << generate_sdc_port(port_to_disable);
+ fp << std::endl;
+}
+
+/********************************************************************
+ * Disable unused input ports and output ports of this pb_graph_node (parent_module)
+ * This function will iterate over all the input pins, output pins
+ * of the physical_pb_graph_node, and check if they are mapped
+ * For unused pins, we will find the port in parent_module
+ * and then print SDC commands to disable them
+ *******************************************************************/
+static
+void disable_pb_graph_node_unused_pins(std::fstream& fp,
+ const ModuleManager& module_manager,
+ const ModuleId& parent_module,
+ const std::string& hierarchy_name,
+ t_pb_graph_node* physical_pb_graph_node,
+ t_phy_pb* block_physical_pb) {
+
+ /* Disable unused input pins */
+ for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; ++iport) {
+ for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) {
+ disable_pb_graph_node_unused_pin(fp, module_manager, parent_module,
+ hierarchy_name,
+ physical_pb_graph_node->input_pins[iport][ipin],
+ block_physical_pb);
+ }
+ }
+
+ /* Disable unused output pins */
+ for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; ++iport) {
+ for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) {
+ disable_pb_graph_node_unused_pin(fp, module_manager, parent_module,
+ hierarchy_name,
+ physical_pb_graph_node->output_pins[iport][ipin],
+ block_physical_pb);
+ }
+ }
+
+ /* Disable unused clock pins */
+ for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; ++iport) {
+ for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) {
+ disable_pb_graph_node_unused_pin(fp, module_manager, parent_module,
+ hierarchy_name,
+ physical_pb_graph_node->clock_pins[iport][ipin],
+ block_physical_pb);
+ }
+ }
+}
+
+/********************************************************************
+ * Disable unused inputs of routing multiplexers of this pb_graph_node
+ * This function will first cache the nets for each input and output pins
+ * and store the results in a mux_name-to-net mapping
+ *******************************************************************/
+static
+void disable_pb_graph_node_unused_mux_inputs(std::fstream& fp,
+ const ModuleManager& module_manager,
+ const ModuleId& parent_module,
+ const std::string& hierarchy_name,
+ t_pb_graph_node* physical_pb_graph_node,
+ t_phy_pb* block_physical_pb,
+ const e_side& border_side) {
+ t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type;
+
+ int physical_mode_index = find_pb_type_physical_mode_index(*physical_pb_type);
+
+ std::map mux_instance_to_net_map;
+
+ /* Cache the nets for each input pins of each child pb_graph_node */
+ for (int ichild = 0; ichild < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ichild) {
+ for (int inst = 0; inst < physical_pb_type->modes[physical_mode_index].pb_type_children[ichild].num_pb; ++inst) {
+
+ t_pb_graph_node* child_pb_graph_node = &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ichild][inst]);
+
+ /* Cache the nets for input pins of the child pb_graph_node */
+ for (int iport = 0; iport < child_pb_graph_node->num_input_ports; ++iport) {
+ for (int ipin = 0; ipin < child_pb_graph_node->num_input_pins[iport]; ++ipin) {
+ int rr_node_index = child_pb_graph_node->input_pins[iport][ipin].rr_node_index_physical_pb;
+ /* Generate the mux name */
+ std::string mux_instance_name = generate_pb_mux_instance_name(GRID_MUX_INSTANCE_PREFIX, &(child_pb_graph_node->input_pins[iport][ipin]), std::string(""));
+ /* Cache the net */
+ mux_instance_to_net_map[mux_instance_name] = block_physical_pb->rr_graph->rr_node[rr_node_index].vpack_net_num;
+ }
+ }
+
+ /* Cache the nets for clock pins of the child pb_graph_node */
+ for (int iport = 0; iport < child_pb_graph_node->num_clock_ports; ++iport) {
+ for (int ipin = 0; ipin < child_pb_graph_node->num_clock_pins[iport]; ++ipin) {
+ int rr_node_index = child_pb_graph_node->clock_pins[iport][ipin].rr_node_index_physical_pb;
+ /* Generate the mux name */
+ std::string mux_instance_name = generate_pb_mux_instance_name(GRID_MUX_INSTANCE_PREFIX, &(child_pb_graph_node->clock_pins[iport][ipin]), std::string(""));
+ /* Cache the net */
+ mux_instance_to_net_map[mux_instance_name] = block_physical_pb->rr_graph->rr_node[rr_node_index].vpack_net_num;
+ }
+ }
+
+ }
+ }
+
+ /* Cache the nets for each output pins of this pb_graph_node */
+ for (int iport = 0; iport < physical_pb_graph_node->num_output_ports; ++iport) {
+ for (int ipin = 0; ipin < physical_pb_graph_node->num_output_pins[iport]; ++ipin) {
+ int rr_node_index = physical_pb_graph_node->output_pins[iport][ipin].rr_node_index_physical_pb;
+ /* Generate the mux name */
+ std::string mux_instance_name = generate_pb_mux_instance_name(GRID_MUX_INSTANCE_PREFIX, &(physical_pb_graph_node->output_pins[iport][ipin]), std::string(""));
+ /* Cache the net */
+ mux_instance_to_net_map[mux_instance_name] = block_physical_pb->rr_graph->rr_node[rr_node_index].vpack_net_num;
+ }
+ }
+
+ /* Now disable unused inputs of routing multiplexers, by tracing from input pins of the parent_module */
+ for (int iport = 0; iport < physical_pb_graph_node->num_input_ports; ++iport) {
+ for (int ipin = 0; ipin < physical_pb_graph_node->num_input_pins[iport]; ++ipin) {
+ /* Find the module port by name */
+ std::string module_port_name = generate_pb_type_port_name(physical_pb_graph_node->input_pins[iport][ipin].port);
+ ModulePortId module_port = module_manager.find_module_port(parent_module, module_port_name);
+ VTR_ASSERT(true == module_manager.valid_module_port_id(parent_module, module_port));
+
+ int rr_node_index = physical_pb_graph_node->input_pins[iport][ipin].rr_node_index_physical_pb;
+ t_rr_node* input_rr_node = &(block_physical_pb->rr_graph->rr_node[rr_node_index]);
+
+ disable_analysis_module_input_pin_net_sinks(fp, module_manager, parent_module,
+ hierarchy_name,
+ module_port, ipin,
+ input_rr_node,
+ mux_instance_to_net_map);
+ }
+ }
+
+ for (int iport = 0; iport < physical_pb_graph_node->num_clock_ports; ++iport) {
+ for (int ipin = 0; ipin < physical_pb_graph_node->num_clock_pins[iport]; ++ipin) {
+ /* Find the module port by name */
+ std::string module_port_name = generate_pb_type_port_name(physical_pb_graph_node->clock_pins[iport][ipin].port);
+ ModulePortId module_port = module_manager.find_module_port(parent_module, module_port_name);
+ VTR_ASSERT(true == module_manager.valid_module_port_id(parent_module, module_port));
+
+ int rr_node_index = physical_pb_graph_node->clock_pins[iport][ipin].rr_node_index_physical_pb;
+ t_rr_node* input_rr_node = &(block_physical_pb->rr_graph->rr_node[rr_node_index]);
+
+ disable_analysis_module_input_pin_net_sinks(fp, module_manager, parent_module,
+ hierarchy_name,
+ module_port, ipin,
+ input_rr_node,
+ mux_instance_to_net_map);
+ }
+ }
+
+ /* Now disable unused inputs of routing multiplexers, by tracing from output pins of the child_module */
+ for (int ichild = 0; ichild < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ichild) {
+ /* Generate the name of the Verilog module for this child */
+ std::string child_module_name_prefix = generate_grid_block_prefix(std::string(GRID_MODULE_NAME_PREFIX), border_side);
+ std::string child_module_name = generate_physical_block_module_name(child_module_name_prefix, &(physical_pb_type->modes[physical_mode_index].pb_type_children[ichild]));
+
+ ModuleId child_module = module_manager.find_module(child_module_name);
+ VTR_ASSERT(true == module_manager.valid_module_id(child_module));
+
+ for (int inst = 0; inst < physical_pb_type->modes[physical_mode_index].pb_type_children[ichild].num_pb; ++inst) {
+
+ t_pb_graph_node* child_pb_graph_node = &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ichild][inst]);
+
+ for (int iport = 0; iport < child_pb_graph_node->num_output_ports; ++iport) {
+ for (int ipin = 0; ipin < child_pb_graph_node->num_output_pins[iport]; ++ipin) {
+ /* Find the module port by name */
+ std::string module_port_name = generate_pb_type_port_name(child_pb_graph_node->output_pins[iport][ipin].port);
+ ModulePortId module_port = module_manager.find_module_port(child_module, module_port_name);
+ VTR_ASSERT(true == module_manager.valid_module_port_id(child_module, module_port));
+
+ int rr_node_index = child_pb_graph_node->output_pins[iport][ipin].rr_node_index_physical_pb;
+ t_rr_node* output_rr_node = &(block_physical_pb->rr_graph->rr_node[rr_node_index]);
+
+ /* Corner case: if the rr node has no fan-out we will skip this pin */
+ if (0 == output_rr_node->num_edges) {
+ continue;
+ }
+
+ disable_analysis_module_output_pin_net_sinks(fp, module_manager, parent_module,
+ hierarchy_name,
+ child_module, inst,
+ module_port, ipin,
+ output_rr_node,
+ mux_instance_to_net_map);
+ }
+ }
+ }
+ }
+}
+
+/********************************************************************
+ * Recursively visit all the pb_types in the hierarchy
+ * and disable all the unused resources, including:
+ * 1. input ports
+ * 2. output ports
+ * 3. unused inputs of routing multiplexers
+ *
+ * As this function is executed in a recursive way.
+ * To avoid repeated disable timing for ports, during each run of this function,
+ * only the unused input ports, output ports of the parent module will be disabled.
+ * In addition, we will cache all the net ids mapped to the input ports of
+ * child modules, and the net ids mapped to the output ports of parent module.
+ * As such, we can trace from
+ * 1. the input ports of parent module to disable unused inputs of routing multiplexer
+ * which drives the inputs of child modules
+ *
+ * Parent_module
+ * +---------------------------------------------
+ * | MUX child_module
+ * | +-------------+ +--------
+ * input_pin0(netA) --->|-------->| Routing |------>|
+ * input_pin1(netB) --->|----x--->| Multiplexer | netA |
+ * | +-------------+ |
+ * | |
+ *
+ * 2. the output ports of child module to disable unused inputs of routing multiplexer
+ * which drives the outputs of parent modules
+ *
+ * Case 1:
+ * parent_module
+ * --------------------------------------+
+ * child_module |
+ * -------------+ |
+ * | +-------------+ |
+ * output_pin0 (netA) |--->| Routing |----->|---->
+ * output_pin1 (netB) |-x->| Multiplexer | netA |
+ * | +-------------+ |
+ *
+ * Case 2:
+ *
+ * Parent_module
+ * +---------------------------------------------
+ * |
+ * | +--------------------------------------------+
+ * | | MUX child_module |
+ * | | +-------------+ +-----------+ |
+ * | +--->| Routing |------>| | |
+ * input_pin0(netA) --->|----x--->| Multiplexer | netA | output_pin|-----+
+ * | +-------------+ | | netA
+ * | | |
+ *
+ *
+ * Note: it is a must to disable all the ports in all the child pb_types!
+ * This can prohibit timing analyzer to consider any FF-to-FF path or
+ * combinatinal path inside an unused grid, when finding critical paths!!!
+ *******************************************************************/
+static
+void rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(std::fstream& fp,
+ const ModuleManager& module_manager,
+ const ModuleId& parent_module,
+ const std::string& hierarchy_name,
+ t_pb_graph_node* physical_pb_graph_node,
+ t_phy_pb* block_physical_pb,
+ const e_side& border_side) {
+ t_pb_type* physical_pb_type = physical_pb_graph_node->pb_type;
+
+ /* Disable unused input ports and output ports of this pb_graph_node (parent_module) */
+ disable_pb_graph_node_unused_pins(fp, module_manager, parent_module,
+ hierarchy_name, physical_pb_graph_node, block_physical_pb);
+
+ /* Return if this is the primitive pb_type
+ * Note: this must return before we disable any unused inputs of routing multiplexer!
+ * This is due to that primitive pb_type does NOT contain any routing multiplexers inside!!!
+ */
+ if (TRUE == is_primitive_pb_type(physical_pb_type)) {
+ return;
+ }
+
+ /* Disable unused inputs of routing multiplexers of this pb_graph_node */
+ disable_pb_graph_node_unused_mux_inputs(fp, module_manager, parent_module,
+ hierarchy_name, physical_pb_graph_node, block_physical_pb,
+ border_side);
+
+
+ int physical_mode_index = find_pb_type_physical_mode_index(*physical_pb_type);
+
+ /* Disable all the ports by iterating over its instance in the parent module */
+ for (int ichild = 0; ichild < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ichild) {
+ /* Generate the name of the Verilog module for this child */
+ std::string child_module_name_prefix = generate_grid_block_prefix(std::string(GRID_MODULE_NAME_PREFIX), border_side);
+ std::string child_module_name = generate_physical_block_module_name(child_module_name_prefix, &(physical_pb_type->modes[physical_mode_index].pb_type_children[ichild]));
+
+ ModuleId child_module = module_manager.find_module(child_module_name);
+ VTR_ASSERT(true == module_manager.valid_module_id(child_module));
+
+ /* Each child may exist multiple times in the hierarchy*/
+ for (int inst = 0; inst < physical_pb_type->modes[physical_mode_index].pb_type_children[ichild].num_pb; ++inst) {
+ std::string child_instance_name = module_manager.instance_name(parent_module, child_module, module_manager.child_module_instances(parent_module, child_module)[inst]);
+ /* Must have a valid instance name!!! */
+ VTR_ASSERT(false == child_instance_name.empty());
+
+ std::string updated_hierarchy_name = hierarchy_name + std::string("/") + child_instance_name + std::string("/");
+
+ rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(fp, module_manager, child_module, hierarchy_name,
+ &(physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ichild][inst]),
+ block_physical_pb, border_side);
+ }
+ }
+}
+
+/********************************************************************
+ * This function can work in two differnt modes:
+ * 1. For partially unused pb blocks
+ * ---------------------------------
+ * Disable the timing for only unused resources in a physical block
+ * We have to walk through pb_graph node, port by port and pin by pin.
+ * Identify which pins have not been used, and then disable the timing
+ * for these ports.
+ * Plus, for input ports, we will trace the routing multiplexers
+ * and disable the timing for unused inputs.
+ *
+ * 2. For fully unused pb_blocks
+ * -----------------------------
+ * Disable the timing for a fully unused grid!
+ * This is very straightforward!
+ * Just walk through each pb_type and disable all the ports using wildcards
+ *******************************************************************/
+static
+void print_analysis_sdc_disable_pb_block_unused_resources(std::fstream& fp,
+ t_type_ptr grid_type,
+ const vtr::Point& grid_coordinate,
+ const ModuleManager& module_manager,
+ const std::string& grid_instance_name,
+ const size_t& grid_z,
+ const e_side& border_side,
+ t_phy_pb* block_physical_pb,
+ const bool& unused_block) {
+ /* Check code: if this is an IO block, the border side MUST be valid */
+ if (IO_TYPE == grid_type) {
+ VTR_ASSERT(NUM_SIDES != border_side);
+ }
+
+ /* If the block is partially unused, we should have a physical pb */
+ if (false == unused_block) {
+ VTR_ASSERT(NULL != block_physical_pb);
+ }
+
+ /* Find an unique name to the pb instance in this grid
+ * Note: this must be consistent with the instance name we used in build_grid_module()!!!
+ */
+ /* TODO: validate that the instance name is used in module manager!!! */
+ std::string pb_module_name_prefix(GRID_MODULE_NAME_PREFIX);
+ std::string pb_module_name = generate_grid_physical_block_module_name(pb_module_name_prefix, grid_type->pb_graph_head->pb_type, border_side);
+ std::string pb_instance_name = generate_grid_physical_block_instance_name(pb_module_name_prefix, grid_type->pb_graph_head->pb_type, border_side, grid_z);
+
+ ModuleId pb_module = module_manager.find_module(pb_module_name);
+ VTR_ASSERT(true == module_manager.valid_module_id(pb_module));
+
+ /* Print comments */
+ fp << "#######################################" << std::endl;
+
+ if (true == unused_block) {
+ fp << "# Disable Timing for unused grid[" << grid_coordinate.x() << "][" << grid_coordinate.y() << "][" << grid_z << "]" << std::endl;
+ } else {
+ VTR_ASSERT_SAFE(false == unused_block);
+ fp << "# Disable Timing for unused resources in grid[" << grid_coordinate.x() << "][" << grid_coordinate.y() << "][" << grid_z << "]" << std::endl;
+ }
+
+ fp << "#######################################" << std::endl;
+
+ std::string hierarchy_name = grid_instance_name + std::string("/") + pb_instance_name + std::string("/");
+
+ /* Go recursively through the pb_graph hierarchy, and disable all the ports level by level */
+ if (true == unused_block) {
+ rec_print_analysis_sdc_disable_unused_pb_graph_nodes(fp, module_manager, pb_module, hierarchy_name, grid_type->pb_graph_head, border_side);
+ } else {
+ VTR_ASSERT_SAFE(false == unused_block);
+ rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(fp, module_manager, pb_module, hierarchy_name, grid_type->pb_graph_head, block_physical_pb, border_side);
+ }
+}
+
+/********************************************************************
+ * Disable the timing for a fully unused grid!
+ * This is very straightforward!
+ * Just walk through each pb_type and disable all the ports using wildcards
+ *******************************************************************/
+static
+void print_analysis_sdc_disable_unused_grid(std::fstream& fp,
+ const vtr::Point& grid_coordinate,
+ const std::vector>& L_grids,
+ const std::vector& L_blocks,
+ const ModuleManager& module_manager,
+ const e_side& border_side) {
+ /* Validate file stream */
+ check_file_handler(fp);
+
+ t_type_ptr grid_type = L_grids[grid_coordinate.x()][grid_coordinate.y()].type;
+ /* Bypass conditions for grids :
+ * 1. EMPTY type, which is by nature unused
+ * 2. Offset > 0, which has already been processed when offset = 0
+ */
+ if ( (NULL == grid_type)
+ || (EMPTY_TYPE == grid_type)
+ || (0 < L_grids[grid_coordinate.x()][grid_coordinate.y()].offset) ) {
+ return;
+ }
+
+ /* Find an unique name to the grid instane
+ * Note: this must be consistent with the instance name we used in build_top_module()!!!
+ */
+ /* TODO: validate that the instance name is used in module manager!!! */
+ 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), IO_TYPE == grid_type, border_side);
+ std::string grid_instance_name = generate_grid_block_instance_name(grid_module_name_prefix, std::string(grid_type->name), IO_TYPE == grid_type, border_side, grid_coordinate);
+
+ ModuleId grid_module = module_manager.find_module(grid_module_name);
+ VTR_ASSERT(true == module_manager.valid_module_id(grid_module));
+
+ /* Now we need to find the usage of this grid */
+ std::vector grid_usage(grid_type->capacity, false);
+
+ /* Print comments */
+ fp << "#######################################" << std::endl;
+ fp << "# Disable Timing for grid[" << grid_coordinate.x() << "][" << grid_coordinate.y() << "]" << std::endl;
+ fp << "#######################################" << std::endl;
+
+ /* For used grid, find the unused rr_node in the local rr_graph
+ * and then disable each port which is not used
+ * as well as the unused inputs of routing multiplexers!
+ */
+ for (int iblk = 0; iblk < L_grids[grid_coordinate.x()][grid_coordinate.y()].usage; ++iblk) {
+ int blk_id = L_grids[grid_coordinate.x()][grid_coordinate.y()].blocks[iblk];
+ VTR_ASSERT( (OPEN < L_blocks[blk_id].z) && (L_blocks[blk_id].z < grid_type->capacity) );
+ /* Mark the grid_usage */
+ grid_usage[L_blocks[blk_id].z] = true;
+ /* TODO:
+ verilog_generate_sdc_disable_one_unused_block(fp, &(L_blocks[blk_id]));
+ */
+ t_phy_pb* block_phy_pb = (t_phy_pb*) L_blocks[blk_id].phy_pb;
+ print_analysis_sdc_disable_pb_block_unused_resources(fp, grid_type, grid_coordinate, module_manager, grid_instance_name, iblk, border_side, block_phy_pb, false);
+ }
+
+ /* For unused grid, disable all the pins in the physical_pb_type */
+ for (int iblk = 0; iblk < grid_type->capacity; ++iblk) {
+ /* Bypass used blocks */
+ if (true == grid_usage[iblk]) {
+ continue;
+ }
+ print_analysis_sdc_disable_pb_block_unused_resources(fp, grid_type, grid_coordinate, module_manager, grid_instance_name, iblk, border_side, NULL, true);
+ }
+}
+
+/********************************************************************
+ * Top-level function writes SDC commands to disable unused ports
+ * of grids, such as Configurable Logic Block (CLBs), heterogeneous blocks, etc.
+ *
+ * This function will iterate over all the grids available in the FPGA fabric
+ * It will disable the timing analysis for
+ * 1. Grids, which are totally not used (no logic has been mapped to)
+ * 2. Unused part of grids, including the ports, inputs of routing multiplexers
+ *
+ * Note that it is a must to disable the unused inputs of routing multiplexers
+ * because it will cause unexpected paths in timing analysis
+ * For example:
+ * +---------------------+
+ * inputA (net0) ------->| |
+ * | Routing multiplexer |----> output (net0)
+ * inputB (net1) ------->| |
+ * +---------------------+
+ *
+ * During timing analysis, the path from inputA to output should be considered
+ * while the path from inputB to output should NOT be considered!!!
+ *
+ *******************************************************************/
+void print_analysis_sdc_disable_unused_grids(std::fstream& fp,
+ const vtr::Point& device_size,
+ const std::vector>& L_grids,
+ const std::vector& L_blocks,
+ const ModuleManager& module_manager) {
+
+ /* Process unused core grids */
+ for (size_t ix = 1; ix < device_size.x() - 1; ++ix) {
+ for (size_t iy = 1; iy < device_size.y() - 1; ++iy) {
+ /* We should not meet any I/O grid */
+ VTR_ASSERT(IO_TYPE != L_grids[ix][iy].type);
+
+ print_analysis_sdc_disable_unused_grid(fp, vtr::Point(ix, iy),
+ L_grids, L_blocks, module_manager, NUM_SIDES);
+ }
+ }
+
+ /* Instanciate I/O grids */
+ /* Create the coordinate range for each side of FPGA fabric */
+ std::vector io_sides{TOP, RIGHT, BOTTOM, LEFT};
+ std::map>> io_coordinates;
+
+ /* TOP side*/
+ for (size_t ix = 1; ix < device_size.x() - 1; ++ix) {
+ io_coordinates[TOP].push_back(vtr::Point(ix, device_size.y() - 1));
+ }
+
+ /* RIGHT side */
+ for (size_t iy = 1; iy < device_size.y() - 1; ++iy) {
+ io_coordinates[RIGHT].push_back(vtr::Point(device_size.x() - 1, iy));
+ }
+
+ /* BOTTOM side*/
+ for (size_t ix = 1; ix < device_size.x() - 1; ++ix) {
+ io_coordinates[BOTTOM].push_back(vtr::Point(ix, 0));
+ }
+
+ /* LEFT side */
+ for (size_t iy = 1; iy < device_size.y() - 1; ++iy) {
+ io_coordinates[LEFT].push_back(vtr::Point(0, iy));
+ }
+
+ /* Add instances of I/O grids to top_module */
+ for (const e_side& io_side : io_sides) {
+ for (const vtr::Point& io_coordinate : io_coordinates[io_side]) {
+ /* We should not meet any I/O grid */
+ VTR_ASSERT(IO_TYPE == L_grids[io_coordinate.x()][io_coordinate.y()].type);
+
+ print_analysis_sdc_disable_unused_grid(fp, io_coordinate,
+ L_grids, L_blocks, module_manager, io_side);
+ }
+ }
+}
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.h b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.h
new file mode 100644
index 000000000..a198cc129
--- /dev/null
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_grid_writer.h
@@ -0,0 +1,16 @@
+#ifndef ANALYSIS_SDC_GRID_WRITER_H
+#define ANALYSIS_SDC_GRID_WRITER_H
+
+#include
+#include
+#include "vtr_geometry.h"
+#include "vpr_types.h"
+#include "module_manager.h"
+
+void print_analysis_sdc_disable_unused_grids(std::fstream& fp,
+ const vtr::Point& device_size,
+ const std::vector>& L_grids,
+ const std::vector& L_blocks,
+ const ModuleManager& module_manager);
+
+#endif
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_routing_writer.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_routing_writer.cpp
new file mode 100644
index 000000000..0509c08de
--- /dev/null
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/backend_assistant/analysis_sdc_routing_writer.cpp
@@ -0,0 +1,549 @@
+/********************************************************************
+ * This file includes functions that are used to output a SDC file
+ * that constrain routing modules of a FPGA fabric (P&Red netlist)
+ * using a benchmark
+ *******************************************************************/
+#include