Skip to content
Snippets Groups Projects
Commit 165d4c97 authored by Yaman Umuroglu's avatar Yaman Umuroglu
Browse files

Merge branch 'feature/ooc_synth' into dev

parents 53cd7941 d6e6aada
No related branches found
No related tags found
No related merge requests found
......@@ -37,7 +37,7 @@ WORKDIR /workspace
RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get install -y build-essential libglib2.0-0 libsm6 libxext6 libxrender-dev
RUN apt install verilator
RUN apt-get install -y verilator zsh
RUN apt-get -y install sshpass
RUN echo "StrictHostKeyChecking no" >> /etc/ssh/ssh_config
......@@ -52,6 +52,8 @@ RUN git clone https://github.com/Xilinx/finn-hlslib.git /workspace/finn-hlslib
RUN git clone https://github.com/maltanar/pyverilator /workspace/pyverilator
# PYNQ-HelloWorld
RUN git clone https://github.com/maltanar/PYNQ-HelloWorld.git /workspace/PYNQ-HelloWorld
# oh-my-xilinx
RUN git clone https://bitbucket.org/maltanar/oh-my-xilinx.git /workspace/oh-my-xilinx
# checkout desired FINN branch for testing
RUN git clone --branch $FINN_CI_BRANCH https://github.com/Xilinx/finn /workspace/finn
......@@ -64,6 +66,8 @@ ENV PYTHONPATH "${PYTHONPATH}:/workspace/finn/src"
ENV PYTHONPATH "${PYTHONPATH}:/workspace/pyverilator"
ENV PYNQSHELL_PATH "/workspace/PYNQ-HelloWorld/boards"
ENV VIVADO_IP_CACHE "$BUILD_PATH/vivado_ip_cache"
ENV PATH "${PATH}:/workspace/oh-my-xilinx"
ENV OHMYXILINX "/workspace/oh-my-xilinx"
# colorful terminal output
RUN echo "PS1='\[\033[1;36m\]\u\[\033[1;31m\]@\[\033[1;32m\]\h:\[\033[1;35m\]\w\[\033[1;31m\]\$\[\033[0m\] '" >> /root/.bashrc
......
......@@ -37,16 +37,12 @@ ARG PASSWD
ARG JUPYTER_PORT
ARG NETRON_PORT
EXPOSE $JUPYTER_PORT
EXPOSE $NETRON_PORT
WORKDIR /workspace
RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get install -y build-essential libglib2.0-0 libsm6 libxext6 libxrender-dev
RUN apt-get install verilator
RUN apt-get install nano
RUN apt-get install -y verilator nano zsh
RUN apt-get -y install sshpass
RUN echo "StrictHostKeyChecking no" >> /etc/ssh/ssh_config
......@@ -81,12 +77,16 @@ RUN git clone https://github.com/Xilinx/finn-hlslib.git /workspace/finn-hlslib
RUN git clone https://github.com/maltanar/pyverilator /workspace/pyverilator
# PYNQ-HelloWorld
RUN git clone https://github.com/maltanar/PYNQ-HelloWorld.git /workspace/PYNQ-HelloWorld
# oh-my-xilinx
RUN git clone https://bitbucket.org/maltanar/oh-my-xilinx.git /workspace/oh-my-xilinx
# for this developer-oriented Docker container we assume the FINN repo is cloned and mounted from the host
# at /workspace/finn -- see run-docker.sh for an example of how to do this.
ENV PYTHONPATH "${PYTHONPATH}:/workspace/finn/src"
ENV PYTHONPATH "${PYTHONPATH}:/workspace/pyverilator"
ENV PYNQSHELL_PATH "/workspace/PYNQ-HelloWorld/boards"
ENV PATH "${PATH}:/workspace/oh-my-xilinx"
ENV OHMYXILINX "/workspace/oh-my-xilinx"
WORKDIR /home/$UNAME/finn
RUN echo "PS1='\[\033[1;36m\]\u\[\033[1;31m\]@\[\033[1;32m\]\h:\[\033[1;35m\]\w\[\033[1;31m\]\$\[\033[0m\] '" >> /home/$UNAME/.bashrc
......@@ -100,5 +100,8 @@ RUN chmod 755 /usr/local/bin/finn_entrypoint.sh
RUN chmod 755 /usr/local/bin/quicktest.sh
USER $UNAME
EXPOSE $JUPYTER_PORT
EXPOSE $NETRON_PORT
ENTRYPOINT ["finn_entrypoint.sh"]
CMD ["bash"]
......@@ -18,6 +18,7 @@ CNPY_COMMIT=4e8810b1a8637695171ed346ce68f6984e585ef4
HLSLIB_COMMIT=13e9b0772a27a3a1efc40c878d8e78ed09efb716
PYVERILATOR_COMMIT=c97a5ba41bbc7c419d6f25c74cdf3bdc3393174f
PYNQSHELL_COMMIT=0c82a61b0ec1a07fa275a14146233824ded7a13d
OMX_COMMIT=1bae737669901e762f581af73348332b5c4b2ada
gecho "Setting up known-good commit versions for FINN dependencies"
......@@ -42,6 +43,10 @@ git -C /workspace/pyverilator checkout $PYVERILATOR_COMMIT --quiet
gecho "PYNQ shell @ $PYNQSHELL_COMMIT"
git -C /workspace/PYNQ-HelloWorld pull --quiet
git -C /workspace/PYNQ-HelloWorld checkout $PYNQSHELL_COMMIT --quiet
# oh-my-xilinx
gecho "oh-my-xilinx @ $OMX_COMMIT"
git -C /workspace/oh-my-xilinx pull --quiet
git -C /workspace/oh-my-xilinx checkout $OMX_COMMIT --quiet
# source Vivado env.vars
source $VIVADO_PATH/settings64.sh
......
# Copyright (c) 2020, Xilinx
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of FINN nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
from shutil import copy2
from finn.transformation import Transformation
from finn.util.vivado import out_of_context_synth
from finn.util.basic import make_build_dir
class SynthOutOfContext(Transformation):
"""Run out-of-context Vivado synthesis on a stitched IP design."""
def __init__(self, part, clk_period_ns, clk_name="ap_clk_0"):
super().__init__()
self.part = part
self.clk_period_ns = clk_period_ns
self.clk_name = clk_name
def apply(self, model):
def file_to_basename(x):
return os.path.basename(os.path.realpath(x))
vivado_stitch_proj_dir = model.get_metadata_prop("vivado_stitch_proj")
assert vivado_stitch_proj_dir is not None, "Need stitched IP to run."
top_module_name = model.get_metadata_prop("wrapper_filename")
top_module_name = file_to_basename(top_module_name).strip(".v")
build_dir = make_build_dir("synth_out_of_context_")
with open(vivado_stitch_proj_dir + "/all_verilog_srcs.txt", "r") as f:
all_verilog_srcs = f.read().split()
for file in all_verilog_srcs:
if file.endswith(".v"):
copy2(file, build_dir)
ret = out_of_context_synth(
build_dir, top_module_name, self.part, self.clk_name, self.clk_period_ns
)
model.set_metadata_prop("res_total_ooc_synth", str(ret))
return (model, False)
# Copyright (c) 2020, Xilinx
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of FINN nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import subprocess
def which(program):
"Python equivalent of the shell cmd 'which'."
# source:
# https://stackoverflow.com/questions/377017/test-if-executable-exists-in-python
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
return None
def out_of_context_synth(
verilog_dir,
top_name,
fpga_part="xczu3eg-sbva484-1-e",
clk_name="ap_clk_0",
clk_period_ns=5.0,
):
"Run out-of-context Vivado synthesis, return resources and slack."
# ensure that the OH_MY_XILINX envvar is set
if "OHMYXILINX" not in os.environ:
raise Exception("The environment variable OHMYXILINX is not defined.")
# ensure that vivado is in PATH: source $VIVADO_PATH/settings64.sh
if which("vivado") is None:
raise Exception("vivado is not in PATH, ensure settings64.sh is sourced.")
omx_path = os.environ["OHMYXILINX"]
script = "vivadocompile.sh"
# vivadocompile.sh <top-level-entity> <clock-name (optional)> <fpga-part (optional)>
call_omx = "zsh %s/%s %s %s %s %f" % (
omx_path,
script,
top_name,
clk_name,
fpga_part,
float(clk_period_ns),
)
call_omx = call_omx.split()
proc = subprocess.Popen(
call_omx, cwd=verilog_dir, stdout=subprocess.PIPE, env=os.environ
)
proc.communicate()
vivado_proj_folder = "%s/results_%s" % (verilog_dir, top_name)
res_counts_path = vivado_proj_folder + "/res.txt"
with open(res_counts_path, "r") as myfile:
res_data = myfile.read().split("\n")
ret = {}
ret["vivado_proj_folder"] = vivado_proj_folder
for res_line in res_data:
res_fields = res_line.split("=")
print(res_fields)
try:
ret[res_fields[0]] = float(res_fields[1])
except ValueError:
ret[res_fields[0]] = 0
except IndexError:
ret[res_fields[0]] = 0
if ret["WNS"] == 0:
ret["fmax_mhz"] = 0
else:
ret["fmax_mhz"] = 1000.0 / (clk_period_ns - ret["WNS"])
return ret
......@@ -53,6 +53,7 @@ from finn.transformation.general import GiveUniqueNodeNames
from finn.util.basic import gen_finn_dt_tensor, pynq_part_map
from finn.util.fpgadataflow import pyverilate_stitched_ip
from finn.util.test import load_test_checkpoint_or_skip
from finn.transformation.fpgadataflow.synth_ooc import SynthOutOfContext
test_pynq_board = os.getenv("PYNQ_BOARD", default="Pynq-Z1")
test_fpga_part = pynq_part_map[test_pynq_board]
......@@ -281,6 +282,27 @@ def test_fpgadataflow_ipstitch_rtlsim():
assert (rtlsim_res == x).all()
@pytest.mark.vivado
@pytest.mark.slow
def test_fpgadataflow_ipstitch_synth_ooc():
model = load_test_checkpoint_or_skip(
ip_stitch_model_dir + "/test_fpgadataflow_ip_stitch.onnx"
)
model = model.transform(SynthOutOfContext(test_fpga_part, 5))
ret = model.get_metadata_prop("res_total_ooc_synth")
assert ret is not None
# example expected output: (details may differ based on Vivado version etc)
# "{'vivado_proj_folder': ...,
# 'LUT': 708.0, 'FF': 1516.0, 'DSP': 0.0, 'BRAM': 0.0, 'WNS': 0.152, '': 0,
# 'fmax_mhz': 206.27062706270627}"
ret = eval(ret)
assert ret["LUT"] > 0
assert ret["FF"] > 0
assert ret["DSP"] == 0
assert ret["BRAM"] == 0
assert ret["fmax_mz"] > 100
@pytest.mark.vivado
def test_fpgadataflow_ipstitch_pynq_projgen():
model = load_test_checkpoint_or_skip(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment