The Vivado Build Pipeline
Running make bit triggers two separate Vivado invocations. The first, driven by
sources.tcl, assembles the Vivado project from the project’s ruckus.tcl declarations.
The second, driven by build.tcl, runs synthesis, implementation, and bitstream generation.
Both invocations run Vivado in batch mode (no GUI).
Build Flow Diagram
make bit
│
├──[Phase 1: Project Assembly]──────────────────────────────────────────────────────
│ vivado -mode batch -source sources.tcl
│ │
│ ├──► Load env_var.tcl + proc.tcl
│ ├──► CheckWritePermission
│ ├──► CheckGitVersion (git >= 2.9.0, git-lfs >= 2.1.1)
│ ├──► Create images/ directory if absent
│ ├──► Open or create Vivado project (.xpr)
│ ├──► VivadoRefresh (update IP catalog)
│ ├──► GenBuildString → BuildInfoPkg.vhd
│ ├──► Check git hash / firmware version; reset synth if changed
│ ├──► loadRuckusTcl $PROJ_DIR ────────────────► ruckus.tcl recursion
│ │ │ │
│ │ │ loadSource / loadConstraints / loadIpCore
│ │ │ loadRuckusTcl (sub-modules)
│ │ └───────────────────────────────────────────────────────
│ ├──► Set PATH_MODE AbsoluteFirst on all filesets
│ ├──► UpgradeIpCores (if ::IP_LIST non-empty)
│ ├──► [hook: ${VIVADO_DIR}/sources.tcl]
│ ├──► Write dirList.txt, ipList.txt, bdList.txt
│ └──► close_project
│
└──[Phase 2: Build]─────────────────────────────────────────────────────────────────
vivado -mode batch -source build.tcl
│
├──► open_project + load properties.tcl + messages.tcl
├──► update_compile_order
├──► CheckPrjConfig (verify sources_1 and sim_1)
├──► CheckImpl / CheckSynth (reset runs if needed)
├──► BuildIpCores (re-synthesize out-of-date IP cores)
├──► [hook: ${VIVADO_DIR}/pre_synthesis.tcl]
├──► launch_runs synth_1 -jobs $PARALLEL_SYNTH
│ ├──► [hook: ${VIVADO_DIR}/pre_synth_run.tcl] (in-run)
│ └──► [hook: ${VIVADO_DIR}/post_synth_run.tcl] (in-run)
├──► [hook: ${VIVADO_DIR}/post_synthesis.tcl]
├──► [exit if SYNTH_ONLY=1 or SYNTH_DCP=1]
├──► launch_runs -to_step write_bitstream impl_1
│ ├──► [hook: ${VIVADO_DIR}/pre_route_run.tcl] (in-run)
│ └──► [hook: ${VIVADO_DIR}/post_route_run.tcl] (in-run)
├──► CheckTiming (exits if violations; see TIG_* overrides)
├──► [hook: ${VIVADO_DIR}/post_route.tcl]
├──► CreateFpgaBit / CreateVersalOutputs
├──► [hook: ${VIVADO_DIR}/post_build.tcl]
└──► images/$(IMAGENAME).bit [and .mcs, .ltx, .pdi, .xsa as configured]
Phase 1: sources.tcl in Detail
sources.tcl assembles the Vivado project file (.xpr) from the project’s source
declarations. Key steps:
Load
env_var.tclandproc.tclto set up all build variables and custom procedures.CheckWritePermission— verify the ruckus installation is writable (required for internal bookkeeping files).CheckGitVersion— require git >= 2.9.0 and git-lfs >= 2.1.1; abort if too old.Create the
images/output directory if it does not yet exist.Open or create the Vivado project (
.xpr) viaproject.tcl, then runVivadoRefreshto update the IP catalog.GenBuildString— generatesBuildInfoPkg.vhdin the project’s source directory, embedding the firmware version and git hash as VHDL constants.Check whether the git hash or firmware version has changed since the last run; if so, reset the synthesis run to force a full rebuild.
Initialize global lists (
::DIR_PATH,::DIR_LIST,::IP_LIST,::IP_FILES,::BD_FILES) to empty, then callloadRuckusTcl ${PROJ_DIR}to recursively traverse allruckus.tclfiles. This is the entry point for all source, constraint, IP core, and block design declarations. See The ruckus.tcl Recursive Loading Model for how this recursion works.Set
PATH_MODE AbsoluteFirston all file sets (sources, simulation, constraints) so Vivado uses absolute paths regardless of where the project is opened.Upgrade any IP cores discovered during the
ruckus.tcltraversal (::IP_LIST).SourceTclFile ${VIVADO_DIR}/sources.tcl— fire the project-specific sources hook, allowing additional source additions after the recursive load is complete.Write
dirList.txt,ipList.txt, andbdList.txttoOUT_DIRfor reference, then close the project.
Phase 2: build.tcl in Detail
build.tcl opens the assembled project and runs the full synthesis-to-bitstream flow.
Key steps:
Load
env_var.tclandproc.tcl, then open the project and applyproperties.tclandmessages.tclsettings.update_compile_order— refresh the compile order for thesources_1fileset.CheckPrjConfig— verify thatsources_1andsim_1are valid; abort if not.CheckImpl/CheckSynth— inspect run state; reset any incomplete or stale runs.BuildIpCores— re-synthesize any IP cores that are out-of-date (skipped if no IPs).source ${RUCKUS_DIR}/vivado/pre_synthesis.tcl— generates block design wrappers and dispatches the${VIVADO_DIR}/pre_synthesis.tclhook.launch_runs synth_1 -jobs $PARALLEL_SYNTH— run synthesis; wait and check result.source ${RUCKUS_DIR}/vivado/post_synthesis.tcl— dispatches the${VIVADO_DIR}/post_synthesis.tclhook.If
SYNTH_ONLY=1: write BuildInfo and exit 0 (partial flow). IfSYNTH_DCP=1: export a design checkpoint (DCP) and exit 0.launch_runs -to_step write_bitstream impl_1— run place-and-route through bitstream generation; wait and check result.CheckTiming— inspect timing report; exit with an error if setup or hold violations exist. Timing ignore groups (TIG_*overrides) can suppress specific violations.source ${RUCKUS_DIR}/vivado/post_route.tcl— runs BuildInfo, optional pyrogue/YAML packaging, optional MicroBlaze ELF integration, and dispatches the${VIVADO_DIR}/post_route.tclhook.CreateFpgaBit(non-Versal) orCreateVersalOutputs(Versal) — copies the bitstream and any additional output files toimages/$(IMAGENAME).*.SourceTclFile ${VIVADO_DIR}/post_build.tcl— fire the post-build hook.close_projectand exit 0.
Interactive Builds with make gui
Running make gui opens Vivado in interactive GUI mode instead of batch mode.
Before presenting the GUI, ruckus still runs Phase 1 in full — sources.tcl assembles
the Vivado project exactly as it would for make bit. By the time Vivado’s window
appears, the project is fully assembled: all sources, constraints, IP cores, and block
designs are registered and the IP catalog is up to date.
Common use cases for make gui:
Early project exploration — inspect the assembled source tree, fileset membership, and IP configurations before committing to a full batch build.
Reviewing synthesis and implementation results — open a project where
synth_1orimpl_1has already run and examine timing reports, resource utilization, or schematic views interactively.Running XSIM simulation — launch the simulator from the Vivado GUI against the assembled simulation fileset.
Investigating timing closure failures — explore the timing report, highlight critical paths in the device view, and experiment with placement constraints.
Reading error and warning messages — the Vivado Messages window aggregates synthesis and implementation diagnostics in a filterable view that is easier to navigate than the raw log files.
make bit remains the preferred target for production and CI builds because it runs
entirely in batch mode and exits with a non-zero status on any error. Use make gui
when interactive exploration or debugging is needed; make gui is the natural starting
point for any session where direct access to the Vivado GUI is required.
Dynamic Function eXchange (DFX) and Partial Build Flows
AMD’s current terminology for partial FPGA reconfiguration is Dynamic Function eXchange
(DFX); the legacy name is partial reconfiguration. See AMD UG909 for the full DFX
design flow. The partial build flows below (SYNTH_ONLY, SYNTH_DCP) are the
ruckus mechanisms most commonly used when working with DFX projects — the synthesized
checkpoint (DCP) produced by make dcp serves as the static-region input for a
subsequent DFX implementation run.
Two environment variables enable partial builds:
SYNTH_ONLY=1— the build exits after synthesis completes and writes a BuildInfo file. Usemake synto invoke this flow.SYNTH_DCP=1— the build exports a synthesis design checkpoint (DCP) after synthesis completes. Usemake dcpto invoke this flow. The DCP can be used as a starting point for implementation in another project.
These are the standard mechanisms for running only part of the Vivado pipeline. For the complete hook script reference — including all Tier 1 and Tier 2 hook filenames and when they fire — see Output Artifacts and Hook Scripts.