diff --git a/.github/workflows/conda_build_lib.yml b/.github/workflows/conda_build_lib.yml index 2c020b03..66562252 100644 --- a/.github/workflows/conda_build_lib.yml +++ b/.github/workflows/conda_build_lib.yml @@ -34,11 +34,11 @@ jobs: steps: # This step checks out a copy of your repository. - - uses: actions/checkout@v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 - - uses: actions/setup-python@v6 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: 3.12 diff --git a/.github/workflows/conda_build_proj.yml b/.github/workflows/conda_build_proj.yml index 3eecc934..117861a7 100644 --- a/.github/workflows/conda_build_proj.yml +++ b/.github/workflows/conda_build_proj.yml @@ -38,11 +38,11 @@ jobs: steps: # This step checks out a copy of your repository. - - uses: actions/checkout@v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 - - uses: actions/setup-python@v6 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: 3.12 diff --git a/.github/workflows/conda_build_win.yml b/.github/workflows/conda_build_win.yml index 38d08dd8..b24ac6f6 100644 --- a/.github/workflows/conda_build_win.yml +++ b/.github/workflows/conda_build_win.yml @@ -30,11 +30,11 @@ jobs: steps: # This step checks out a copy of your repository. - - uses: actions/checkout@v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 - - uses: actions/setup-python@v6 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: 3.12 diff --git a/.github/workflows/docker_build.yml b/.github/workflows/docker_build.yml index 319446ea..355c01ef 100644 --- a/.github/workflows/docker_build.yml +++ b/.github/workflows/docker_build.yml @@ -33,7 +33,7 @@ jobs: steps: # This step checks out a copy of your repository. - - uses: actions/checkout@v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 @@ -45,11 +45,11 @@ jobs: # Setup docker build environment - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 # Login to GHCR (GitHub Container Registry) / Docker registry - name: Login to GHCR / Docker registry - uses: docker/login-action@v3 + uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0 with: registry: ghcr.io username: ${{ inputs.gh_username }} @@ -57,7 +57,7 @@ jobs: # Build and push the docker image - name: Build and push image to GHCR / Docker registry - uses: docker/build-push-action@v6 + uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 with: context: . file: ./docker/${{ inputs.docker_name }}/Dockerfile diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 90eea034..26e49ff9 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -23,11 +23,11 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 - - uses: actions/setup-python@v6 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" cache: "pip" @@ -41,7 +41,7 @@ jobs: - name: Upload Pages artifact if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/upload-pages-artifact@v5 + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: path: docs/_build/html @@ -60,7 +60,7 @@ jobs: # can worsen a wedged Pages backend rather than help it recover. - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v5 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 continue-on-error: true - name: Wait before retrying deploy @@ -70,4 +70,4 @@ jobs: - name: Deploy to GitHub Pages (retry) id: deployment_retry if: steps.deployment.outcome == 'failure' - uses: actions/deploy-pages@v5 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 diff --git a/.github/workflows/gen_release.yml b/.github/workflows/gen_release.yml index 9db90d36..c2c1cdf9 100644 --- a/.github/workflows/gen_release.yml +++ b/.github/workflows/gen_release.yml @@ -28,11 +28,11 @@ jobs: if: startsWith(github.ref, 'refs/tags/') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 - - uses: actions/setup-python@v6 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: 3.12 diff --git a/.github/workflows/ruckus_ci.yml b/.github/workflows/ruckus_ci.yml index 6ea7d02f..9eabbc5b 100644 --- a/.github/workflows/ruckus_ci.yml +++ b/.github/workflows/ruckus_ci.yml @@ -23,11 +23,11 @@ jobs: steps: # This step checks out a copy of your repository. - - uses: actions/checkout@v6 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 - - uses: actions/setup-python@v6 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: 3.12 diff --git a/docs/how-to/index.rst b/docs/how-to/index.rst index dd315b8f..7355c895 100644 --- a/docs/how-to/index.rst +++ b/docs/how-to/index.rst @@ -13,6 +13,7 @@ setting up a project for the first time, see vitis_hls vitis_aie ghdl_simulation + xsim_rogue_cosim cadence_genus synopsys_dc firmware_release diff --git a/docs/how-to/xsim_rogue_cosim.rst b/docs/how-to/xsim_rogue_cosim.rst new file mode 100644 index 00000000..fb367993 --- /dev/null +++ b/docs/how-to/xsim_rogue_cosim.rst @@ -0,0 +1,160 @@ +How to Run the Rogue Co-Simulation in Vivado XSIM +=================================================== + +**Goal:** Run the surf Rogue TCP/SideBand co-simulation inside Vivado xsim, +either interactively in the GUI or in batch mode. + +The co-simulation HDL and C sources live in the **surf** submodule under +``axi/simlink/``; ruckus provides only the build and simulate orchestration +described here. Any ``axi/simlink/...`` path below is relative to the surf +submodule root, not ruckus. + +.. note:: + + This flow is GUI-interactive/local only and requires a licensed Vivado + install. It has no CI coverage — verification is manual against a local + Vivado + Rogue environment. + +Prerequisites +------------- + +- ``libzmq >= 4.1.0`` and ``pkg-config`` on the build machine. +- A Rogue-environment Python shell for the peer script (it imports + ``pyrogue`` / ``rogue``). +- Vivado 2023.1 or newer — the floor enforced by ``project.tcl``'s + ``VersionCheck``. The latest *tested* Vivado release is tracked centrally by + ``CheckVivadoVersion`` (see :doc:`../reference/tcl_api`), which warns when the + active Vivado is newer; this page intentionally does not restate a version. +- A surf version that provides the ``axi/simlink/xsim/`` DPI backend. Older + surf (legacy ``axi/simlink/sim`` + ``src`` VHPI layout) is VCS-only; use + ``make vcs`` there. + +Makefile Setup +-------------- + +Add the following to your project ``Makefile``: + +.. code-block:: makefile + + include $(TOP_DIR)/submodules/ruckus/system_vivado.mk + +No additional variables are required. The co-sim hook is registered +unconditionally by ``project.tcl`` and is a fast no-op for any project that +doesn't contain a Rogue co-sim source. + +.. note:: + + ``make xsim`` and ``make gui`` automatically select the surf xsim DPI-C + backend (they export ``RUCKUS_SIM_BACKEND=xsim``), so having Synopsys VCS + sourced in the same shell alongside Vivado — common in a combined setup + script — no longer misroutes the flow to the VCS/VHPI backend. Switching + between this xsim flow and ``make vcs`` in the same build directory swaps + the backend automatically; no ``make clean`` is needed. + +Steps +----- + +1. **Launch the GUI (or run batch xsim):** + + .. code-block:: bash + + make gui + + For a headless batch run, name the demo testbench and let the simulation + free-run so the peer can connect and drive it: + + .. code-block:: bash + + make xsim VIVADO_PROJECT_SIM=RogueTcpStreamXsimDemoTb + + The batch path elaborates ``VIVADO_PROJECT_SIM`` (default ``$(PROJECT)``, + the synthesis top), so it must name the demo testbench. The run length is + ``VIVADO_PROJECT_SIM_TIME``, whose default ``all`` free-runs until the + testbench calls ``$finish``/``$stop`` or is interrupted. The demo + testbenches have neither, so the run does not self-terminate — background + it, wait for the ``Listening on ports N & N+1`` print, start the peer, then + stop the simulation once the peer reports its result. To bound a run + instead, pass a time value, e.g. ``VIVADO_PROJECT_SIM_TIME="1000 ns"``. + + Either target triggers ruckus's pre-compile hook, which detects any of + ``RogueTcpStream.vhd``, ``RogueTcpMemory.vhd``, or ``RogueSideBand.vhd`` in + the simulation sources, builds the combined ``RogueTcpDpi.so`` via ``xsc``, + and binds it with ``-sv_lib RogueTcpDpi`` — no manual build step. + +2. **Watch the console for the build and bind:** + + Confirm the ``pkg-config``/``xsc`` build messages appear with no errors, + and, after ``launch_simulation``/``run``, the module's one-time + ``Listening on ports N & N+1`` print — that is the ready-for-peer signal. + +3. **Start the matching Rogue peer script:** + + .. code-block:: bash + + python3 prbsLoopbackDemo.py + + Run this in a separate terminal, pointed at the same host/port the demo + testbench is listening on. Ruckus and the DPI hook are entirely automatic + up to this point; starting the peer and, if switching modules, selecting + the desired top-level testbench in the target's ``ruckus.tcl`` + (``set_property top``) are the only manual steps. + +4. **Observe the waveform:** + + Data movement between the DPI adapter and the peer confirms the round + trip. + +Key Variables +------------- + +.. list-table:: + :header-rows: 1 + :widths: 22 15 63 + + * - Variable + - Default + - Description + * - ``VIVADO_PROJECT_SIM`` + - ``$(PROJECT)`` + - Top module for Vivado simulation. Set to the demo testbench (e.g. + ``RogueTcpStreamXsimDemoTb``) for a batch ``make xsim`` co-sim run. + * - ``VIVADO_PROJECT_SIM_TIME`` + - ``all`` + - Simulation run length. The default ``all`` free-runs until the + testbench calls ``$finish``/``$stop`` or is interrupted — required for + co-sim so the external peer can drive the testbench. Pass a time value + (e.g. ``1000 ns``) to bound the run instead. + +There is no co-sim-specific variable — the DPI hook auto-registers and +auto-detects, so the existing simulation variables above are the only ones +relevant to this flow. + +Troubleshooting +---------------- + +**"libzmq package was not found"** + .. code-block:: text + + libzmq package was not found + Please make sure that you have libzmq installed + or have sourced the necessary rogue setup scripts + + Install libzmq, or source the Rogue setup scripts that put it on + ``PKG_CONFIG_PATH``, then re-run ``make gui``/``make xsim``. + +**"no axi/simlink/xsim/ DPI co-simulation backend" at compile** + The surf version in your project predates the xsim DPI backend (legacy + ``axi/simlink/sim`` + ``src`` VHPI layout). The Vivado xsim co-sim requires + a surf that provides ``axi/simlink/xsim/``. Use ``make vcs`` for VCS + co-simulation with that surf version, or update surf. + +**"DPI function ... not found" at elaboration** + The ``.so`` is stale, ``-sv_lib`` was not bound, or the module-detection + guard did not fire because none of the three Rogue ``.vhd`` files are + present in the simulation sources. Confirm the module's source is in the + sim compile order and re-run the build. + +**Waveform runs with no data movement** + The peer script has not connected. Confirm it is running against the + correct host/port pair and that push/pull directions are not swapped — + see the port table in ``axi/simlink/README.md`` in surf. diff --git a/docs/reference/makefile_reference.rst b/docs/reference/makefile_reference.rst index 480f2c09..5f5b6e6b 100644 --- a/docs/reference/makefile_reference.rst +++ b/docs/reference/makefile_reference.rst @@ -29,7 +29,7 @@ Targets * - ``dcp`` - Synthesis + DCP export (sets ``SYNTH_DCP=1``). Exports the post-synthesis checkpoint. * - ``gui`` - - Open the Vivado project in GUI mode. + - Open the Vivado project in GUI mode. Automatically detects and builds the Rogue TCP/SideBand co-simulation DPI library when present; see :doc:`../how-to/xsim_rogue_cosim`. * - ``interactive`` - Open Vivado in TCL interactive mode. * - ``sources`` @@ -46,10 +46,8 @@ Targets - Generate PyRogue tarball. * - ``yaml`` - Generate CPSW YAML tarball. - * - ``wis`` - - Generate ``init_wis.tcl`` for Windows Vivado initialisation. * - ``xsim`` - - Run Vivado XSIM simulation. + - Run Vivado XSIM simulation. Automatically detects and builds the Rogue TCP/SideBand co-simulation DPI library when present; see :doc:`../how-to/xsim_rogue_cosim`. * - ``vcs`` - Generate VCS simulation scripts. * - ``msim`` @@ -298,15 +296,22 @@ Simulation Variables .. envvar:: VIVADO_PROJECT_SIM - Top module name for Vivado simulation. + Top module name for Vivado simulation. For a batch Rogue co-sim, set this to + the demo testbench (e.g. ``RogueTcpStreamXsimDemoTb``); see + :doc:`../how-to/xsim_rogue_cosim`. :default: ``$(PROJECT)`` .. envvar:: VIVADO_PROJECT_SIM_TIME - Default simulation run time. + Simulation run length. The default ``all`` free-runs until the testbench + calls ``$finish``/``$stop`` or is interrupted; a testbench with neither + (and a free-running clock) never self-terminates, so a batch ``make xsim`` + must be stopped manually. Pass a time value (e.g. ``1000 ns``) to bound the + run. ``all`` is required for the Rogue co-sim so the external peer can drive + the testbench — see :doc:`../how-to/xsim_rogue_cosim`. - :default: ``1000 ns`` + :default: ``all`` .. envvar:: SIM_CARGS_VERILOG diff --git a/system_vivado.mk b/system_vivado.mk index 16c20708..27010ee2 100644 --- a/system_vivado.mk +++ b/system_vivado.mk @@ -106,11 +106,18 @@ export USE_SEGMENTED_CONFIG = 0 endif # Vivado Simulation Variables +# When left undefined, the sim_1 top is auto-picked-up from the project +# (i.e. the "set_property top ... [get_filesets sim_1]" in the target's +# ruckus.tcl). Define VIVADO_PROJECT_SIM only to override that top. ifndef VIVADO_PROJECT_SIM -export VIVADO_PROJECT_SIM = $(PROJECT) +export VIVADO_PROJECT_SIM = endif +# Default sim run length. "all" runs until the testbench calls finish/stop or +# is interrupted; a time value (e.g. "1000 ns") runs that long. Testbenches +# without a finish/stop free-run under "all", so a batch "make xsim" there must +# be stopped manually. ifndef VIVADO_PROJECT_SIM_TIME -export VIVADO_PROJECT_SIM_TIME = 1000 ns +export VIVADO_PROJECT_SIM_TIME = all endif # Synthesis Variables @@ -400,12 +407,13 @@ yaml : $(SOURCE_DEPEND) @cd $(OUT_DIR); tclsh $(RUCKUS_DIR)/vivado/cpsw.tcl ############################################################### -#### Vivado WIS ############################################### +#### Rogue Co-Simulation Backend ############################## ############################################################### -.PHONY : wis -wis : $(SOURCE_DEPEND) - $(call ACTION_HEADER,"Generating init_wis.tcl file for Windows OS") - @cd $(OUT_DIR); vivado -mode batch -source $(RUCKUS_DIR)/vivado/wis.tcl +# Tell surf/axi/simlink/ruckus.tcl which Rogue co-sim backend the invoked +# target wants. Target-specific + exported so it propagates to the shared +# $(SOURCE_DEPEND) prerequisite recipe and into the vivado subprocess. +xsim gui : export RUCKUS_SIM_BACKEND := xsim +vcs : export RUCKUS_SIM_BACKEND := vcs ############################################################### #### Vivado XSIM Simulation ################################### diff --git a/vivado/gui.tcl b/vivado/gui.tcl index 20384c87..5c7253da 100644 --- a/vivado/gui.tcl +++ b/vivado/gui.tcl @@ -18,6 +18,30 @@ source -quiet $::env(RUCKUS_DIR)/vivado/proc.tcl source -quiet $::env(RUCKUS_DIR)/vivado/properties.tcl source -quiet $::env(RUCKUS_DIR)/vivado/messages.tcl +######################################################## +## Rogue co-sim GUI-path environment setup. +## The interactive "Run Simulation" freezes the xsim subprocess environment +## when launch_simulation starts -- which is earlier than the +## xsim.compile.tcl.pre hook (vivado/run/pre/xsim.tcl) fires -- so setting +## LD_PRELOAD from that hook is too late for the GUI. Set it here at GUI +## startup, before the user launches a simulation, so the xsim subprocess +## inherits it. Mirrors the batch simulate path in vivado/xsim.tcl and is +## guarded on the Rogue xsim backend, so it is a no-op for non-Rogue projects. +######################################################## +if { [RogueSimSources xsim] != "" } { + # GLIBCXX runtime fix: LD_PRELOAD a libstdc++ new enough for the co-sim's + # libzmq (see RoguePreloadLibStdCpp). + RoguePreloadLibStdCpp + # LD_LIBRARY_PATH parity so the interactively launched xsim subprocess + # finds RogueTcpDpi.so at runtime, mirroring vivado/xsim.tcl. + set simOutDir "${OUT_DIR}/${VIVADO_PROJECT}.sim/sim_1/behav/xsim" + if { [info exists ::env(LD_LIBRARY_PATH)] } { + set ::env(LD_LIBRARY_PATH) "${simOutDir}:$::env(LD_LIBRARY_PATH)" + } else { + set ::env(LD_LIBRARY_PATH) "${simOutDir}" + } +} + # Update the bitstream post script if { [isVersal] } { set_property STEPS.WRITE_DEVICE_IMAGE.TCL.POST ${RUCKUS_DIR}/vivado/run/post/gui_write.tcl [get_runs impl_1] diff --git a/vivado/proc/sim_management.tcl b/vivado/proc/sim_management.tcl index 6a85d287..e059e05e 100644 --- a/vivado/proc/sim_management.tcl +++ b/vivado/proc/sim_management.tcl @@ -95,3 +95,77 @@ proc MsimCompleteMessage {dirPath rogueSim} { puts "\t\$ ./sim_msim.sh" puts "********************************************************\n\n" } + +## Return the Rogue co-sim source files (RogueTcpStream/Memory/SideBand) in the +## simulation fileset, or "" if none -- the shared detector for whether a +## project uses the Rogue co-sim. Pass "vcs" to surface the get_files warning +## when absent, or "xsim" to suppress it (the xsim pre-compile hook runs for +## every xsim project, so a non-Rogue project must stay quiet). Called from +## vivado/vcs.tcl, vivado/xsim.tcl, vivado/sources.tcl, vivado/run/pre/xsim.tcl. +proc RogueSimSources {backend} { + set rogueFiles {RogueTcpStream.vhd RogueTcpMemory.vhd RogueSideBand.vhd} + if { ${backend} == "vcs" } { + return [get_files -compile_order sources -used_in simulation ${rogueFiles}] + } else { + return [get_files -quiet -compile_order sources -used_in simulation ${rogueFiles}] + } +} + +## Verify libzmq >= 4.1.0 is available via pkg-config for the Rogue co-sim, +## printing a clear diagnostic and exiting on failure. Called by the VCS flow +## (vivado/vcs.tcl) and the xsim pre-compile hook (vivado/run/pre/xsim.tcl). +proc RogueCheckLibZmq {} { + set err_ret [catch {exec pkg-config --exists {libzmq >= 4.1.0} --print-errors} libzmq] + if { ${libzmq} != "" } { + puts "\n\n\n\n\n********************************************************" + if { [string match "*Package libzmq was not found*" ${libzmq}] == 1 } { + puts "libzmq package was not found" + puts "Please make sure that you have libzmq installed" + puts "or have sourced the necessary rogue setup scripts" + } else { + puts ${libzmq} + } + puts "********************************************************\n\n\n\n\n" + exit -1 + } +} + +## LD_PRELOAD a libstdc++.so.6 new enough for the Rogue xsim co-sim's libzmq. +## Vivado's loader wrapper prepends its bundled libstdc++ (e.g. GLIBCXX 3.4.25 +## in 2025.2) to LD_LIBRARY_PATH, which is too old for a libzmq built against a +## newer GCC. LD_PRELOAD takes precedence over LD_LIBRARY_PATH, so it forces the +## newer GLIBCXX regardless of the loader's path injection (a plain +## LD_LIBRARY_PATH prepend would lose to the loader). Called from both the GUI +## pre-compile hook (vivado/run/pre/xsim.tcl) and the batch simulate path +## (vivado/xsim.tcl). Exits with an error if no suitable libstdc++ is found. +proc RoguePreloadLibStdCpp {} { + set candidates {} + # 1) libstdc++ from the prefix that ships libzmq (most ABI-consistent) + if { [catch {exec pkg-config --variable=libdir libzmq} zmqLibDir] == 0 && ${zmqLibDir} != "" } { + lappend candidates ${zmqLibDir}/libstdc++.so.6 + } + # 2) active gcc's libstdc++ (distro-layout agnostic) + if { [catch {exec gcc -print-file-name=libstdc++.so.6} gccLib] == 0 && [file exists ${gccLib}] } { + lappend candidates ${gccLib} + } + # 3) common system locations: RHEL/Rocky, then Debian/Ubuntu + lappend candidates /usr/lib64/libstdc++.so.6 + lappend candidates /usr/lib/x86_64-linux-gnu/libstdc++.so.6 + # Prepend the first existing candidate, preserving any existing LD_PRELOAD + foreach lib ${candidates} { + if { [file exists ${lib}] } { + if { [info exists ::env(LD_PRELOAD)] && $::env(LD_PRELOAD) != "" } { + set ::env(LD_PRELOAD) "${lib}:$::env(LD_PRELOAD)" + } else { + set ::env(LD_PRELOAD) ${lib} + } + return + } + } + # Fail loudly rather than let the sim die with an opaque GLIBCXX loader error + puts "\n\n\n\n\n********************************************************" + puts "ERROR: no libstdc++.so.6 with a modern GLIBCXX found for the Rogue xsim co-sim." + puts "Install a newer libstdc++ or source the rogue setup scripts, then retry." + puts "********************************************************\n\n\n\n\n" + exit -1 +} diff --git a/vivado/project.tcl b/vivado/project.tcl index 6491f0f3..da888acd 100644 --- a/vivado/project.tcl +++ b/vivado/project.tcl @@ -70,6 +70,13 @@ if { [VersionCompare 2014.2] <= 0 } { set_property xsim.unifast false [get_filesets sim_1] set_property -name {xsim.compile.xvlog.more_options} -value {-d SIM_SPEED_UP} -objects [get_filesets sim_1] + + # Register the DPI pre-compile hook unconditionally. The + # Rogue co-sim guard lives in the hook script itself, so this is a + # safe no-op for non-Rogue xsim projects. Registered here (not in + # xsim.tcl) because project.tcl is the only ruckus script sourced + # by both "make gui" and "make xsim" ahead of launch_simulation. + set_property -name {xsim.compile.tcl.pre} -value ${RUCKUS_DIR}/vivado/run/pre/xsim.tcl -objects [get_filesets sim_1] } # Enable general project multi-threading diff --git a/vivado/run/pre/xsim.tcl b/vivado/run/pre/xsim.tcl new file mode 100644 index 00000000..717c9303 --- /dev/null +++ b/vivado/run/pre/xsim.tcl @@ -0,0 +1,105 @@ +############################################################################## +## This file is an addition to the 'SLAC Firmware Standard Library'. +## It is subject to the license terms in the LICENSE.txt file found in the +## top-level directory of this distribution and at: +## https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +## No part of 'SLAC Firmware Standard Library', including this file, +## may be copied, modified, propagated, or distributed except according to +## the terms contained in the LICENSE.txt file. +############################################################################## + +## \file vivado/run/pre/xsim.tcl +# \brief Vivado xsim pre-compile hook (xsim.compile.tcl.pre, registered +# unconditionally by project.tcl). Detects the Rogue TCP/SideBand co-sim +# sources, builds their DPI shared library via xsc, and binds it to xelab. +# This script IS the guard: a non-Rogue xsim project is a fast no-op. +# Fires for both "make gui" -> Run Simulation and "make xsim" (batch), +# since project.tcl runs ahead of both launch paths. + +######################################################## +## Custom procs. Sourced before the guard (so the guard can use them) because +## this compile hook may run in a fresh Tcl interpreter without proc.tcl. +######################################################## +source -quiet $::env(RUCKUS_DIR)/vivado/proc/sim_management.tcl + +######################################################## +## Guard: only act when a Rogue co-sim source is present +######################################################## +set rogueSimPath [RogueSimSources xsim] +if { ${rogueSimPath} == "" } { + return +} + +######################################################## +## Locate the surf axi/simlink/xsim/ build directory (../xsim/ sibling of the +## detected RogueTcpStream.vhd, mirroring vcs.tcl's ../vcs/ resolution). Older +## surf predates the xsim DPI backend (legacy axi/simlink/sim + src VHPI +## layout) and has no xsim/ directory: the Vivado xsim Rogue co-sim cannot run +## there. Fail fast with a clear pointer to "make vcs" instead of dying later +## on a missing Makefile or an elaboration error. +######################################################## +set simTbDirName [file dirname [lindex ${rogueSimPath} 0]] +set simLinkDir ${simTbDirName}/../xsim/ +if { ![file exists ${simLinkDir}] } { + puts "*********************************************************************" + puts "ERROR: this surf has no axi/simlink/xsim/ DPI co-simulation backend." + puts " Rogue co-sim source found: [file normalize [lindex ${rogueSimPath} 0]]" + puts " The Vivado xsim (DPI-C) Rogue co-simulation requires a surf version" + puts " that provides axi/simlink/xsim/. Use 'make vcs' for VCS co-simulation" + puts " with this (older) surf version." + puts "*********************************************************************" + exit -1 +} + +######################################################## +## Version lock: the Rogue xsim DPI co-sim requires Vivado 2023.1+ (older xsc +## link drivers cannot resolve the host multiarch crt/libs for RogueTcpDpi.so). +## Sourced/checked only inside this Rogue-only path, so a non-Rogue xsim +## project on an older Vivado is completely unaffected. Covers both +## "make gui" -> Run Simulation and "make xsim", since this hook fires for both. +######################################################## +source -quiet $::env(RUCKUS_DIR)/vivado/proc/project_management.tcl +if { [VersionCheck 2023.1] < 0 } { + exit -1 +} + +######################################################## +## Check the zeromq library exists and its version +######################################################## +RogueCheckLibZmq + +######################################################## +## Vivado's current working directory at compile-hook time +## is the simulation run directory; stage the built .so there +######################################################## +set simOutDir [pwd] + +######################################################## +## Build RogueTcpDpi.so via xsc (axi/simlink/xsim/Makefile) +######################################################## +cd ${simLinkDir} +exec make +exec cp -f [glob -directory ${simLinkDir} *.so] ${simOutDir}/. +exec make clean +cd $::env(PROJ_DIR) + +######################################################## +## GLIBCXX runtime fix fallback: LD_PRELOAD a libstdc++ new enough for the +## co-sim's libzmq (see RoguePreloadLibStdCpp). This compile-stage hook fires +## after launch_simulation has already frozen the xsim subprocess environment, +## so the effective fix is applied earlier: vivado/gui.tcl for the interactive +## "Run Simulation" path and vivado/xsim.tcl for the batch path. This call is +## kept as belt-and-suspenders for any flow that reaches the hook first. +######################################################## +RoguePreloadLibStdCpp + +######################################################## +## The xelab "-sv_lib RogueTcpStream" binding is intentionally NOT set here. +## Vivado builds elaborate.sh from xsim.elaborate.xelab.more_options at +## launch_simulation start -- BEFORE this compile-stage (xsim.compile.tcl.pre) +## hook runs -- so a set_property here never reaches the xelab command line. +## The binding is registered at project-generation time in vivado/sources.tcl +## (guarded on the xsim RogueTcpStream backend) so it persists into the .xpr +## and is baked into the generated elaborate.sh. This hook only builds and +## stages RogueTcpDpi.so, which must exist before elaboration. +######################################################## diff --git a/vivado/sources.tcl b/vivado/sources.tcl index 8c33a278..76c7b307 100644 --- a/vivado/sources.tcl +++ b/vivado/sources.tcl @@ -86,8 +86,9 @@ close ${out} set_property top ${PROJECT} [current_fileset] # set_property top "glbl" [get_filesets sim_1] -# If VIVADO_PROJECT_SIM variable exist, set as sim top -if { [info exists ::env(VIVADO_PROJECT_SIM)] } { +# If VIVADO_PROJECT_SIM is defined, use it to override the sim_1 top +# (otherwise keep the top set by the target's ruckus.tcl) +if { $::env(VIVADO_PROJECT_SIM) != "" } { set_property top ${VIVADO_PROJECT_SIM} [get_filesets sim_1] } @@ -112,6 +113,28 @@ if { [get_files -of_objects [get_filesets {constrs_1}]] != "" } { set_property PATH_MODE AbsoluteFirst [get_files -of_objects [get_filesets {constrs_1}]] } +# Bind the Rogue TCP/SideBand DPI shared library for Vivado xsim co-simulation. +# This MUST run at project-generation time: after the simulation backend +# sources are loaded (so the guard resolves) and before launch_simulation +# generates elaborate.sh. Setting xsim.elaborate.xelab.more_options from the +# xsim.compile.tcl.pre hook is too late -- elaborate.sh is already generated. +# Guarded on the xsim Rogue backends, so it is a no-op for non-Rogue +# projects and for the GHDL/VCS simulation backends. +set rogueXsimSrc "" +foreach rogueFile [RogueSimSources xsim] { + if { [string match {*/xsim/RogueTcpStream.vhd} ${rogueFile}] || + [string match {*/xsim/RogueTcpMemory.vhd} ${rogueFile}] || + [string match {*/xsim/RogueSideBand.vhd} ${rogueFile}] } { + set rogueXsimSrc ${rogueFile} + } +} +if { ${rogueXsimSrc} != "" } { + set xelabOpt [get_property {xsim.elaborate.xelab.more_options} [get_filesets sim_1]] + if { [string first {-sv_lib RogueTcpDpi} ${xelabOpt}] == -1 } { + set_property -name {xsim.elaborate.xelab.more_options} -value "${xelabOpt} -sv_lib RogueTcpDpi" -objects [get_filesets sim_1] + } +} + # Check if we can upgrade IP cores if { $::IP_LIST != "" } { foreach ipPntr $::IP_LIST { diff --git a/vivado/vcs.tcl b/vivado/vcs.tcl index 4b90f0f4..647f54cf 100644 --- a/vivado/vcs.tcl +++ b/vivado/vcs.tcl @@ -255,26 +255,14 @@ export_simulation -force -absolute_path -simulator vcs -include ${include} -defi ## Build the simlink directory (required for softrware co-simulation) ##################################################################################################### -set rogueSimPath [get_files -compile_order sources -used_in simulation {RogueTcpStream.vhd RogueTcpMemory.vhd RogueSideBand.vhd}] +set rogueSimPath [RogueSimSources vcs] if { ${rogueSimPath} != "" } { # Set the flag true set rogueSimEn true # Check the zeromq library exists and its version - set err_ret [catch {exec pkg-config --exists {libzmq >= 4.1.0} --print-errors} libzmq] - if { ${libzmq} != "" } { - puts "\n\n\n\n\n********************************************************" - if { [string match "*Package libzmq was not found*" ${libzmq}] == 1 } { - puts "libzmq package was not found" - puts "Please make sure that you have libzmq installed" - puts "or have sourced the necessary rogue setup scripts" - } else { - puts ${libzmq} - } - puts "********************************************************\n\n\n\n\n" - exit -1 - } + RogueCheckLibZmq # Create the setup environment script: C-SHELL set envScript [open ${simTbOutDir}/setup_env.csh w] diff --git a/vivado/wis.tcl b/vivado/wis.tcl deleted file mode 100644 index fa942823..00000000 --- a/vivado/wis.tcl +++ /dev/null @@ -1,96 +0,0 @@ -############################################################################## -# This file is part of 'SLAC Firmware Standard Library'. -# It is subject to the license terms in the LICENSE.txt file found in the -# top-level directory of this distribution and at: -# https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. -# No part of 'SLAC Firmware Standard Library', including this file, -# may be copied, modified, propagated, or distributed except according to -# the terms contained in the LICENSE.txt file. -############################################################################## - -## \file vivado/wis.tcl -# \brief Creates a tcl script that copies the current values of the KotoDpm project's -# Linux OS environment variables. The purpose of the init.tcl output script is to -# properly establish the environment variables within the Windows version of Vivado without the need -# to first load Cygwin. This is useful because while using Vivado with Cygwin, Vivado runs roughly 2x slower. - -# Get variables and procedures -source -quiet $::env(RUCKUS_DIR)/vivado/env_var.tcl -source -quiet $::env(RUCKUS_DIR)/vivado/proc.tcl - -# Open the project -open_project -quiet ${VIVADO_PROJECT} - -# create and open output file -set fp [open init_wis.tcl w] - -######################################################## -## Declare a list of Linux environment variables to copy to script -######################################################## -# SLAC Project Variables -set linuxVars "PRJ_PART" -lappend linuxVars "PROJECT" -lappend linuxVars "PRJ_VERSION" -lappend linuxVars "PROJ_DIR" -lappend linuxVars "TOP_DIR" -lappend linuxVars "IMAGES_DIR" -lappend linuxVars "OUT_DIR" -lappend linuxVars "SYN_DIR" -lappend linuxVars "IMPL_DIR" -lappend linuxVars "VIVADO_DIR" -lappend linuxVars "VIVADO_PROJECT" -lappend linuxVars "VIVADO_VERSION" -lappend linuxVars "RUCKUS_DIR" - -# SLAC Vivado SDK Variables -lappend linuxVars "SDK_PRJ" -lappend linuxVars "SDK_LIB" -lappend linuxVars "SDK_ELF" - -# Partial Reconfiguration Variables -lappend linuxVars "RECONFIG_CHECKPOINT" -lappend linuxVars "RECONFIG_ENDPOINT" -lappend linuxVars "RECONFIG_PBLOCK" - -# Set GIT variables -lappend linuxVars "GIT_BYPASS" -lappend linuxVars "GIT_STATUS" -lappend linuxVars "GIT_HASH_LONG" -lappend linuxVars "GIT_HASH_SHORT" -lappend linuxVars "GIT_HASH_MSG" - -# Set Non-Environmental variables -lappend linuxVars "vivado_cmd" - -######################################################## -## Copy list to tcl script -######################################################## -# Create fp header -puts $fp "## Script Generation Information" - -# Report Vivado version -puts $fp "# Vivado version: [version -short]" - -# Report OS Information -puts $fp "# Script generated by mother OS: $tcl_platform(os) $tcl_platform(osVersion)" - -# Report user information -puts $fp "# Generated by user: $tcl_platform(user)" - -# Report general build string -puts $fp "# Build String: $env(BUILD_STRING)" - -# write matching environment variables to file -puts $fp " " -puts $fp "# Set Environment Variables" -for {set i 0} {$i < [llength $linuxVars]} {incr i} { - if {[info exists env([lindex $linuxVars $i])]} { - puts $fp "set env([lindex $linuxVars $i]) $env([lindex $linuxVars $i])" - } -} - -# Close the file -close $fp - -# Close the project -close_project diff --git a/vivado/xsim.tcl b/vivado/xsim.tcl index 2d421920..a656fb83 100644 --- a/vivado/xsim.tcl +++ b/vivado/xsim.tcl @@ -48,6 +48,39 @@ if { [CheckPrjConfig sim_1] != true } { generate_target -quiet {simulation} [get_ips] export_ip_user_files -no_script +######################################################## +## Rogue co-sim batch-path env parity. The guard +## + xsc build + -sv_lib injection live in run/pre/xsim.tcl +## (registered by project.tcl); this is belt-and-suspenders +## only for the batch xsim subprocess -- no duplicate build. +######################################################## +set rogueSimPath [RogueSimSources xsim] +if { ${rogueSimPath} != "" } { + + # Version lock: the Rogue xsim DPI co-sim requires Vivado 2023.1+ (see + # vivado/run/pre/xsim.tcl). Fail fast on the "make xsim" batch path, before + # launch_simulation. Only reached when the co-sim is used, so a non-Rogue + # xsim project on an older Vivado is unaffected. + if { [VersionCheck 2023.1] < 0 } { + exit -1 + } + + # GLIBCXX runtime fix for the batch xsim subprocess: LD_PRELOAD a libstdc++ + # new enough for the co-sim's libzmq (see RoguePreloadLibStdCpp). The GUI + # path applies the same fix from vivado/run/pre/xsim.tcl. + RoguePreloadLibStdCpp + + # LD_LIBRARY_PATH parity so a script-launched xsim subprocess + # finds libRogueTcpStream.so at runtime, mirroring vcs.tcl's + # setup_env LD_LIBRARY_PATH prepend + set simOutDir "${OUT_DIR}/${VIVADO_PROJECT}.sim/sim_1/behav/xsim" + if { [info exists ::env(LD_LIBRARY_PATH)] } { + set ::env(LD_LIBRARY_PATH) "${simOutDir}:$::env(LD_LIBRARY_PATH)" + } else { + set ::env(LD_LIBRARY_PATH) "${simOutDir}" + } +} + ######################################################## ## Simulate Process ######################################################## @@ -55,7 +88,11 @@ set sim_rc [catch { # Set sim properties set_property target_simulator XSim [current_project] - set_property top ${VIVADO_PROJECT_SIM} [get_filesets sim_1] + # Only override the sim_1 top when VIVADO_PROJECT_SIM is explicitly defined; + # otherwise keep the top auto-picked-up from the target's ruckus.tcl + if { ${VIVADO_PROJECT_SIM} != "" } { + set_property top ${VIVADO_PROJECT_SIM} [get_filesets sim_1] + } set_property top_lib xil_defaultlib [get_filesets sim_1] # Launch the xsim