Ug894 Vivado TCL Scripting
Ug894 Vivado TCL Scripting
User Guide
Introduction
The Tool Command Language, or Tcl, is an interpreted programming language with
variables, procedures (procs), and control structures, to interface to a variety of design tools
and to the design data.
TIP: For more information, see the Vivado Design Suite Tcl Command Reference Guide (UG835) [Ref 1],
or type <command> -help .
For information on launching and using the Vivado® Design Suite, see the Vivado Design Suite User
Guide: Getting Started (UG910) [Ref 2].
The language is easily extended with new function calls; has been expanded to support new
tools and technology since its inception and adoption in the early 1990s. It has been
adopted as the standard application programming interface, or API, among most EDA
vendors to control and extend their applications.
Xilinx® has adopted Tcl as the native programming language for the Vivado Design Suite,
as it is easily adopted and mastered by designers familiar with this industry standard
language. The Tcl interpreter inside the Vivado Design Suite provides the full power and
flexibility of Tcl to control the application, access design objects and their properties, and
create custom reports. Using Tcl, you can adapt your design flow to meet specific design
challenges.
Tcl provides built-in commands to read and write files to the local file system. This enables
you to dynamically create directories, start FPGA design projects, add files to the projects,
run synthesis and implementation. You can customize the reports generated from design
projects, on device utilization and quality of results, to share across the organization.
You can also use Tcl to implement new design approaches, or work around existing
problems, inserting and deleting design objects, or modifying properties as needed. You
can write scripts to replay established portions of your design flow to standardize the
process.
Many of the Tcl commands discussed in the following text and script examples are specific
to the Vivado Design Suite. You can find detailed information regarding Vivado specific Tcl
commands in the Vivado Design Suite Tcl Command Reference Guide (UG835) [Ref 1], or in
the Help system of the Vivado tools.
The Vivado IDE uses Xilinx Design Constraints (XDC) to specify the design constraints. XDC
is based on a subset of all the Tcl commands available in Vivado and is interpreted exactly
like Tcl. The XDC commands are primarily timing constraints, physical constraints, object
queries and a few Tcl built-in commands: set, list, and expr. For a complete description
of the XDC commands, see Appendix B of the Vivado Design Suite User Guide: Using
Constraints (UG903) [Ref 3]. Unlike Tcl scripts, XDC files are managed by the Vivado IDE so
that any constraint edited through the graphical interface or the Timing Constraints Editor
can be saved back to its original XDC file. For this reason, only XDC commands can be used
in a XDC file. If you need to use other Tcl commands to write your constraints, you must use
a Tcl script.
The Vivado tools write a journal file called vivado.jou into the directory from which
Vivado was launched. The journal is a record of the Tcl commands run during the session
that can be used as a starting point to create new Tcl scripts.
A log file, vivado.log is also created by the tool and includes the output of the
commands that are executed. Both the journal and log file are useful to verify which
commands were run and what result they produced.
Additional Tcl commands are provided by the Tcl interpreter that is built into the Vivado
Design Suite. For Tcl built-in commands, Tcl reference material is provided by the Tcl
Developer Xchange website, which maintains the open source code base and
documentation for Tcl, and is located at Tcl Developer Xchange [Ref 8].
In this document you will see some examples of Tcl commands and Tcl scripts, and the
results that are returned by the Vivado Design Suite when these commands are run. The
commands and their return values appear with the following formats:
A word is a string that can be a single word, or multiple words within braces, {}, or multiple
words within quotation marks, "". Semicolons, brackets, tabs, spaces, and new-lines, within
quotation marks or braces are treated as ordinary characters. However, the backslash, \, is
treated as a special character even within braces and quotation marks, as discussed below.
The first word identifies the command, and all subsequent words are passed to the
command as arguments.
In the preceding example, the first word is the Tcl set command, which is used to assign
variables. The second and third words are passed to the set command as the variable name
(outputDir), and the variable value (./Tutorial_Created_Data/cpu_output).
When a backslash, ‘\’, is used in a word, then the Tcl interpreter performs backslash
substitution. In most cases, this means that the character following the backslash is treated
as a standard character in the word. This is used to add quotes, braces, dollar signs, or other
special characters to a string. Refer to a Tcl/Tk reference source for more information on
how the Tcl interpreter handles the backslash character.
puts $outputDir
./Tutorial_Created_Data/cpu_output
puts \$outputDir
$outputDir
There is a also difference between the use of braces and quotation marks. No substitutions
are performed on the characters between the braces. Words, or strings, within braces are
taken verbatim, and are not evaluated for variable or command substitution by the Tcl
interpreter. The word consists of exactly the characters between the outer braces, not
including the braces themselves, as shown in the example below. Strings within quotation
marks are evaluated, and variable and command substitutions are performed as needed.
Command substitution, variable substitution, and backslash substitution are performed on
the characters between quotes.
Notice in the example above, that the [version -short] command is substituted for the
returned value when enclosed within quotation marks, but is not substituted when enclosed
within braces. Keep substitution in mind when choosing to use either "" or {} to enclose a
string of words.
Variable assignment is performed using the set command. You can access a previously
assigned variable by specifying the name of the variable with a leading dollar sign, ‘$’. If a
word starts with a dollar sign the Tcl interpreter performs variable substitution, replacing
the variable with the value currently stored by the variable. The ‘$’ is a reserved character in
Tcl.
Commands can also be nested inside other commands within brackets, [], which are
evaluated from left to right in a bottom-up manner. The Tcl interpreter recursively processes
the strings within the brackets as a new Tcl script. A nested command can also contain other
nested commands. The result of a nested command is passed up into the higher-level
command, which is then processed.
The preceding example assigns the sorted list of cell objects existing at the top-level of the
current design to the listCells variable. The get_cells command is executed first, the
returned objects are sorted by the lsort command, and the sorted list is assigned to the
specified variable.
However, the Vivado Design Suite handles square brackets slightly differently than standard
Tcl. Square brackets are treated as standard characters in Verilog and VHDL names (net,
instances, etc.), and usually identify one or more elements of vectors, such as buses or
arrays of instances. In the Vivado tools the square brackets are not evaluated in a
bottom-up manner when they are expected to be part of a netlist object name.
In line 1, the outer pair of brackets indicate a nested command, [get_pins], as is standard
in Tcl. However, the subsequent square brackets are interpreted by the Vivado tools as part
of the specified object name transformLoop[0]. This is handled automatically by the
Vivado Design Suite, but is limited to certain characters. These characters must be in one of
the following forms, or the brackets will be interpreted as they would be in normal Tcl
syntax:
In line 2 the use of the braces, {}, will prevent command substitution of the string inside the
braces. In this case the square brackets would be evaluated as part of the object name,
transformLoop[0].
In line 3, the backslash indicates that the bracket should be interpreted as a standard
character rather than a special character, and this will prevent nested command
substitution.
While lines 2 and 3 prevent the square brackets from being misinterpreted, those lines
require you to manually apply the braces or backslash as needed by standard Tcl. Line 1
shows how the Vivado Design Suite automatically handles this for you.
Finally, to add comments to a Tcl script, simply start a new-line with the number sign, or
hash character, ‘#’. Characters that follow a hash character are ignored, up to the next
new-line. To add a comment to the end of a line, simply end the command with a semicolon,
‘;’, and then begin the comment with a hash character as shown below:
# This is a comment
puts "This is a command"; # followed by a comment
Getting Help
You can get help directly from the Tcl console. Every Vivado command supports the -help
command line argument that can be used anywhere in the line.
For example:
The help command can also just return a short description of the arguments using the
-args option:
create_clock
Description:
Create a clock object
Syntax:
create_clock -period <arg> [-name <arg>] [-waveform <args>] [-add] [-quiet]
[-verbose] [<objects>]
Returns:
new clock object
Usage:
Name Description
------------------------
-period Clock period: Value > 0
[-name] Clock name
[-waveform] Clock edge specification
[-add] Add to the existing clock in source_objects
[-quiet] Ignore command errors
[-verbose] Suspend message limits during command execution
[<objects>] List of clock source ports, pins or nets
A short summary of the syntax of a command is also available with the -syntax option:
create_clock
Syntax:
create_clock -period <arg> [-name <arg>] [-waveform <args>] [-add]
[-quiet][-verbose] [<objects>]
In addition to providing help for the specific commands, the help command can also
provide information on categories of commands or classes of objects. A list of categories
can be obtained by executing the help command without any argument or option. A
non-exhaustive list of categories is:
Vivado% help
ChipScope
DRC
FileIO
Floorplan
GUIControl
IPFlow
Object
PinPlanning
Power
Project
PropertyAndParameter
Report
SDC
Simulation
TclBuiltIn
Timing
ToolLaunch
Tools
XDC
The list of commands available under each category can be also reported with the
-category option. For example, the following command reports all the commands under
the Tools category:
Topic Description
link_design Open a netlist design
list_features List available features.
load_features Load Tcl commands for a specified feature.
opt_design Optimize the current netlist. This will perform the retarget,
propconst, and sweep optimizations by default.
phys_opt_design Optimize the current placed netlist.
place_design Automatically place ports and leaf-level instances
route_design Route the current design
synth_design Synthesize a design using Vivado Synthesis and open that design
For example, if you have a list of large integers that you want to sort, you might use the
following command:
This command behaves differently when the script is running on a 32-bit machine than on
a 64-bit machine. The reason is that integers are coded differently on a 32-bit platform
versus 64-bit platform:
A workaround for that particular example would be to use the command line option
-command of lsort and provide a custom proc to do the sorting.
#
# STEP#5: run the router, write the post-route design checkpoint, report the routing
# status, report timing, power, and DRC, and finally save the Verilog netlist.
#
route_design
write_checkpoint -force $outputDir/post_route.dcp
report_route_status -file $outputDir/post_route_status.rpt
report_timing_summary -file $outputDir/post_route_timing_summary.rpt
report_power -file $outputDir/post_route_power.rpt
report_drc -file $outputDir/post_imp_drc.rpt
write_verilog -force $outputDir/cpu_impl_netlist.v -mode timesim -sdf_anno true
#
# STEP#6: generate a bitstream
#
write_bitstream -force $outputDir/cpu.bit
• Step 1: Defines a variable, $outputDir, that points to an output directory and also
physically creates the directory. The $outputDir variable is referenced as needed at
other points in the script.
• Step 2: Reads the VHDL and Verilog files that contain the design description, and the
XDC file that contains the physical and/or timing constraints for the design. You can
also read synthesized netlists (EDIF or NGC) using the read_edif command.
The Vivado Design Suite uses design constraints to define requirements for both the
physical and timing characteristics of the design. The read_xdc command reads an
XDC constraints file which will be used during synthesis and implementation.
IMPORTANT: The Vivado Design Suite does not support the UCF format. For information on migrating
UCF constraints to XDC commands refer to the ISE to Vivado Design Suite Migration Guide (UG911)
[Ref 4] for more information.
The read_* Tcl commands are designed for use in Non-Project mode, as it allows a file
on the disk to be read by the Vivado Design Suite to build an in-memory design
database, without copying the file or creating a dependency on the file in any way, as it
would in Project mode. All actions taken in the Non-Project mode are directed at the
in-memory database within the Vivado tools. The advantages of this approach make the
Non-Project mode extremely flexible with regard to the design. However, a limitation of
the Non-Project mode is that you must monitor any changes to the source design files,
and update the design as needed. For more information on running the Vivado Design
Suite using either Project mode or Non-Project mode, refer to the Vivado Design Suite
User Guide: Design Flows Overview (UG892) [Ref 5].
This step compiles the HDL design files, applies the timing constraints located in the
XDC file, and maps the logic onto Xilinx primitives to create a design database in
memory. The in-memory design resides in the Vivado tools, whether running in batch
mode, Tcl shell mode for interactive Tcl commands, or in the Vivado Integrated Design
Environment (IDE) for interaction with the design data in a graphical form.
Once synthesis completes, a checkpoint is saved for reference. At this point the design
is an unplaced synthesized netlist with timing and physical constraints. Various reports
like timing and utilization can provide a useful resource to better understand the
challenges of the design.
Any additional XDC file read in after synthesis by the read_xdc or source commands
is used during the implementation steps only. They will be stored in any subsequent
design checkpoints, along with the netlist.
Once the placement is done, the script uses the get_timing_paths command to
examine the SLACK property of the worst timing path in the placed design. While the
report_timing command returns a detailed text report of the timing path with the
worst slack, the get_timing_paths command returns the same timing path as a Tcl
object with properties that correspond to the main timing characteristics of the path.
The SLACK property returns the slack of the specified timing path, or worst path in this
case. If the slack is negative then the script runs physical optimization to resolve the
placement timing violations whenever possible.
At the end of Step 4, another checkpoint is saved and the device utilization is reported
along with a timing summary of the design. This will let you compare pre-routed and
post-routed timing to assess the impact that routing has on the design timing.
• Step 5: The Vivado router performs timing-driven routing, and a checkpoint is saved
for reference. Now that the in-memory design is routed, additional reports provide
critical information regarding power consumption, design rule violations, and final
timing. You can output reports to files, for later review, or you can direct the reports to
the Vivado IDE for more interactive examination. A Verilog netlist is exported, for use in
timing simulation.
• Step 6: Writes a bitstream to test and program the design onto the Xilinx FPGA.
#
# STEP#1: define the output directory area.
#
set outputDir ./Tutorial_Created_Data/cpu_project
file mkdir $outputDir
create_project project_cpu_project ./Tutorial_Created_Data/cpu_project \
-part xc7k70tfbg676-2 -force
#
# STEP#2: setup design sources and constraints
#
add_files -fileset sim_1 ./Sources/hdl/cpu_tb.v
add_files [ glob ./Sources/hdl/bftLib/*.vhdl ]
add_files ./Sources/hdl/bft.vhdl
add_files [ glob ./Sources/hdl/*.v ]
add_files [ glob ./Sources/hdl/mgt/*.v ]
add_files [ glob ./Sources/hdl/or1200/*.v ]
add_files [ glob ./Sources/hdl/usbf/*.v ]
add_files [ glob ./Sources/hdl/wb_conmax/*.v ]
add_files -fileset constrs_1 ./Sources/top_full.xdc
set_property library bftLib [ get_files [ glob ./Sources/hdl/bftLib/*.vhdl ]]
#
# Physically import the files under project_cpu.srcs/sources_1/imports directory
import_files -force -norecurse
#
# Physically import bft_full.xdc under project_cpu.srcs/constrs_1/imports directory
import_files -fileset constrs_1 -force -norecurse ./Sources/top_full.xdc
# Update compile order for the fileset 'sources_1'
set_property top top [current_fileset]
update_compile_order -fileset sources_1
update_compile_order -fileset sim_1
#
# STEP#3: run synthesis and the default utilization report.
#
launch_runs synth_1
wait_on_run synth_1
#
# STEP#4: run logic optimization, placement, physical logic optimization, route and
# bitstream generation. Generates design checkpoints, utilization and timing
# reports, plus custom reports.
set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1]
set_property STEPS.OPT_DESIGN.TCL.PRE [pwd]/pre_opt_design.tcl [get_runs impl_1]
set_property STEPS.OPT_DESIGN.TCL.POST [pwd]/post_opt_design.tcl [get_runs impl_1]
set_property STEPS.PLACE_DESIGN.TCL.POST [pwd]/post_place_design.tcl [get_runs impl_1]
set_property STEPS.PHYS_OPT_DESIGN.TCL.POST [pwd]/post_phys_opt_design.tcl [get_runs impl_1]
set_property STEPS.ROUTE_DESIGN.TCL.POST [pwd]/post_route_design.tcl [get_runs impl_1]
launch_runs impl_1 -to_step write_bitstream
wait_on_run impl_1
puts "Implementation done!"
In this example, the output directory where the various reports are saved is the same as
the project directory.
• Step 2: All the files that are used in a project need to be explicitly declared and added
to the project. This is done with the add_files command. When a file is added to the
project, it is added to a specific fileset. A fileset is a container that groups files together
for a purpose. In this example script, most of the files are added to the default fileset
(sources_1). Only the Verilog test bench cpu_tb.v is added to the default
simulation fileset sim_1.
The files are also copied inside the project directories with the import_files
command. By doing this, the project points to the local copy of the source files and does
not track the original source files anymore.
Once the synthesis run is completed, the results can be loaded in memory with the
open_run synth_1 command. A checkpoint without constraints is saved in the
project directories, where synthesis was run. In this example, it can be found under:
./Tutorial_Created_Data/cpu_project/project_cpu.runs/synth_1/top.dcp
Note: The names synth_1 and impl_1 are default names for the synthesis and
implementation runs. Additional runs can be created with create_run command.
• Step 4: The implementation is done by using the launch_run command. The
complete P&R flow from pre-place optimization to writing the bitstream can be
performed in a single command. In this example script, the implementation is done up
to the bitstream generation (launch_run impl_1 -to_step write_bitstream).
The optional step phys_opt_design is enabled in the script through the property
STEPS.PHYS_OPT_DESIGN.IS_ENABLED. Unlike with the Non-Project flow which allows
dynamically calling the implementation commands based on conditions defined by the
user, the run of a project flow must be configured statically before it is launched. This is
why, in this example, the physical logic optimization step is enabled without checking the
timing slack value after placement, unlike in the Compilation with a Non-Project flow
example.
The various reports are generated before or after each implementation step by using the
run Tcl hook properties STEPS.<STEPNAME>.TCL.PRE and
STEPS.<STEPNAME>.TCL.POST. These properties allow the user to specify where a Tcl
script is executed in the flow when using the run infrastructure. See Defining Tcl Hook
Scripts for additional information.
Because the implementation run is executed in a separate Vivado session, all the Tcl
variables and procs need to be initialized in that session in order to be used by the scripts.
This can be done in several ways:
• Method 1: Define the Tcl variables and procs in your Vivado_init.tcl (see
Initializing Tcl Scripts). This is sticky to all your Vivado projects and sessions.
• Method 2: Add a Tcl script which contains the variables and procs to the constraints set
used by the run. It will always be sourced as part of your constraints when opening the
design in memory.
• Method 3: Set STEPS.OPT_DESIGN.TCL.PRE to a Tcl script which contains the
variables and proc. This script will only be sourced if the OPT_DESIGN step is enabled,
which is true by default.
The current example uses the Method 3. The Tcl scripts are associated with the
implementation steps as follows:
The absolute Tcl script path must be specified because the implementation run is executed
in a sub-directory of the project tree, which is different from the one where the full
compilation Tcl script is executed.
• pre_opt_design.tcl
############## pre_opt_design.tcl ##################
set outputDir [file dirname [info script]]/Tutorial_Created_Data/cpu_project
source [file dirname [info script]]/reportCriticalPaths.tcl
#
report_timing_summary -file $outputDir/post_synth_timing_summary.rpt
report_utilization -file $outputDir/post_synth_util.rpt
reportCriticalPaths $outputDir/post_synth_critpath_report.csv
The two first lines correspond to the initialization of the variable and proc used by
several scripts later in the implementation run. The next three lines run some utilization
and timing reports. It is generally recommended to run timing analysis at the beginning
of implementation to validate the timing constraints used during place and route, and
ensure there is no large violation. The reportCriticalPaths report provides more
information on the worst paths of the design. This Tcl proc is described further in
Defining Tcl Procedures.
• post_opt_design.tcl
############## post_opt_design.tcl ##################
# Run custom script to report critical timing paths
reportCriticalPaths $outputDir/post_opt_critpath_report.csv
This script does not need to define the outputDir variable and
reportCriticalPaths proc because they are already defined in
pre_opt_design.tcl which is sourced earlier in the run in the same Vivado session.
• post_place_design.tcl
############## post_place_design.tcl ##################
report_clock_utilization -file $outputDir/clock_util.rpt
After placement, you can review the utilization of the clock resources and where they are
located in the device. It is recommended to run timing analysis to identify large timing
violations that cannot be resolved later in the flow.
• post_phys_opt_design.tcl
############## post_phys_opt_design.tcl ##################
report_utilization -file $outputDir/post_phys_opt_util.rpt
report_timing_summary -file $outputDir/post_phys_opt_timing_summary.rpt
Like after placement, it is important to review the timing report at this point of the flow.
• post_route_design.tcl
############## post_route_design.tcl ##################
report_route_status -file $outputDir/post_route_status.rpt
report_timing_summary -file $outputDir/post_route_timing_summary.rpt
report_power -file $outputDir/post_route_power.rpt
report_drc -file $outputDir/post_imp_drc.rpt
write_verilog -force $outputDir/cpu_impl_netlist.v -mode timesim -sdf_anno true
After route, the timing analysis uses actual routed net delays and must be reviewed for
timing sign-off. The route status report summarizes the number of unresolved routing
issues. If there are any, the DRC report often helps identify what the routing issues are.
Note: When running an implementation step inside the hook script, you can use the Tcl variable
ACTIVE_STEP to, for instance, make the report file names unique. The variable ACTIVE_STEP
is automatically updated by Vivado when using the run infrastructure. See Sharing Hook Scripts
Between Steps for more information.
Note: Most of the Tcl reports generated during post-route above are also automatically created
by the run infrastructure. Similarly, a design checkpoint is generated after each step of the flow,
so there is usually no need to call the write_checkpoint command in your scripts when using
a project flow. You can find all the checkpoints and default reports in the implementation run
directory:
./Tutorial_Created_Data/cpu_project/project_cpu.runs/impl_1/
top_opt.dcp
top_placed.dcp
top_physopt.dcp
top_routed.dcp
top_clock_utilization_placed.rpt
top_control_sets_placed.rpt
top_utilization_placed.rpt
top_io_placed.rpt
top_drc_routed.rpt
top_power_routed.rpt
top_route_status.rpt
top_timing_summary_routed.rpt
After the implementation run is complete, the implemented design can be loaded in
memory with the open_run impl_1 command.
Note: Starting with 2017.1 the startup script for the Vivado Design Suite has been renamed
Vivado_init.tcl. In the earlier versions it was called init.tcl. If Vivado_init.tcl does not
exist but init.tcl is present, the Vivado tools source the init.tcl and issue a deprecation
message.
When you start the Vivado tools, it looks for a Tcl initialization script in several locations
with the following precedence:
Where < installdir> is the installation directory where the Vivado Design Suite is
installed.
° For Windows 7:
%APPDATA%/Xilinx/Vivado/<VivadoVersion>/Vivado_init.tcl
If Vivado_init.tcl exists in several locations, the Vivado tool sources the file following
the precedence explained above.
The Vivado_init.tcl file in the installation directory allows a company or design group
to support a common initialization script for all users. Anyone starting the Vivado tools
from that software installation sources the enterprise Vivado_init.tcl script.
The Vivado_init.tcl file in the home directory allows each user to specify additional
commands, or to override commands from the software installation to meet their specific
design requirements.
The Vivado_init.tcl file is a standard Tcl script file that can contain any valid Tcl
command supported by the Vivado tools. You can even source another Tcl script file from
within Vivado_init.tcl by adding the source command.
source <filename>
Where <filename > specifies both the name of the file, as well as the relative or absolute
path to the file. If no path is specified as part of the file name, then the Vivado tools look
for the file in the working directory, or the directory from which the Vivado Design Suite
was launched.
Within the Vivado IDE you can also source a Tcl script from the Tools >Run Tcl Script menu
command.
By default, the source command echoes each line of the file to the Tcl console. This can be
prevented by using the -notrace option, which is specific to the Vivado Tcl interpreter:
The following is equivalent to manually sourcing the script after first starting Vivado tools:
source myscript.tcl
A checkpoint can also be specified on the command line along with a Tcl script:
The above command line is equivalent to manually opening the checkpoint and then
sourcing the script:
open_checkpoint design.dcp
source myscript.tcl
The combination of a checkpoint and script provides the flexibility to write a Tcl script
independent of any design and then easily associate a checkpoint with the script:
For more information, see the Vivado Design Suite User Guide: Using Constraints (UG903)
[Ref 3].
Whenever you launch a synthesis or implementation run, the Vivado tools use a predefined
Tcl script to process a standard design flow based on the selected strategy. Tcl hook scripts
let you customize the standard flow, with pre-processors or post-processors. Being able to
add Tcl script processing anywhere in a run can be useful. Every step in the design flow has
a pre-hook and post-hook capability. Common uses are:
In the GUI you can specify the Tcl hook scripts to be sourced by using the Change Run
Settings command for the design run. Right-click a run in the Design Runs window and
select the Change Run Settings from the pop-up menu to open the Design Run Settings
dialog box. The tcl.pre and tcl.post options can be used to specify a Tcl hook script.
The Vivado IDE sets a property on the synthesis or implementation run to specify the
tcl.pre or tcl.post script to apply before or after the run, as shown in Figure 1. You can
also set this property directly on a synthesis or implementation run, either in the Tcl Console
or as part of a Tcl script.
STEPS.SYNTH_DESIGN.TCL.PRE
STEPS.SYNTH_DESIGN.TCL.POST
For instance, set the following property to have the report.tcl script launched before
synthesis is complete:
For an implementation run you can define Tcl scripts before and after each step of the
implementation process: Opt Design, Power Opt Design, Place Design, Post-Place Power
Opt Design, Phys Opt Design, Route Design and Bitstream generation. The properties for
each of these are:
STEPS.OPT_DESIGN.TCL.PRE
STEPS.OPT_DESIGN.TCL.POST
STEPS.POWER_OPT_DESIGN.TCL.PRE
STEPS.POWER_OPT_DESIGN.TCL.POST
STEPS.PLACE_DESIGN.TCL.PRE
STEPS.PLACE_DESIGN.TCL.POST
STEPS.POST_PLACE_POWER_OPT_DESIGN.TCL.PRE
STEPS.POST_PLACE_POWER_OPT_DESIGN.TCL.POST
STEPS.PHYS_OPT_DESIGN.TCL.PRE
STEPS.PHYS_OPT_DESIGN.TCL.POST
STEPS.ROUTE_DESIGN.TCL.PRE
STEPS.ROUTE_DESIGN.TCL.POST
STEPS.WRITE_BITSTREAM.TCL.PRE
STEPS.WRITE_BITSTREAM.TCL.POST
IMPORTANT: Relative paths within the tcl.pre and tcl.post scripts are relative to the appropriate
run directory of the project they are applied to: <project>/<project.runs>/<run_name> . You
can use the DIRECTORY property of the current project or current run to define the relative paths in
your Tcl hook scripts:
get_property DIRECTORY [current_project]
get_property DIRECTORY [current_run]
In Project mode, Vivado IDE automatically updates the Tcl variable ACTIVE_STEP when
submitting a run through the run infrastructure to match the implementation step being
run.
Note: The Tcl variable ACTIVE_STEP is only available in Project mode while using the run
infrastructure.
A Tcl procedure is defined with the proc command which takes three arguments: the
procedure name, the list of arguments, and the body of code to be executed. The following
code provides a simple example of a procedure definition:
TIP: Although the curly brackets are optional for the argument definition of this procedure, since
helloProc has only one argument, it makes the procedure definition easier to read by enclosing the
arguments in braces. The braces are required when the procedure accepts multiple arguments.
A procedure usually has predefined arguments. Each of them can optionally have a default
value. When an argument has a default value, it does not need to be specified when calling
the procedure if all the mandatory preceding arguments are specified. A procedure returns
an empty string unless the return command is used to return a different value.
When running the procedure, all the arguments must be specified as shown:
The next example is a different form of the same procedure, where the last two of the three
arguments have a default value. The default value for corner is Slow, and the default value
for delayType is Max. With default values specified in the definition of the procedure, the
corner and delayType arguments are optional when calling the procedure.
When running this procedure, all of the following calls of the command are valid:
%> reportWorstViolations 2
%> reportWorstViolations 10 Fast
%> reportWorstViolations 10 Slow Min
The following example is an illustration of a procedure that has one mandatory argument,
nbrPath, but that can also accept any number of additional arguments. This uses the Tcl
keyword args in the list of arguments when defining the procedure. The args keyword is
a Tcl list that can have any number of elements, including none.
When executing a Tcl command, you can use variable substitution to replace some of the
command line arguments accepted or required by the Tcl command. In this case, you must
use the Tcl eval command to evaluate the command line with the Tcl variable as part of the
command. In the preceding example, the variable list of arguments ($args) is passed to the
encapsulated report_timing command as a variable, and so requires the use of the eval
command.
When running this procedure, any of the following forms of the command will work:
%> reportWorstViolations 2
%> reportWorstViolations 1 -to [get_ports]
%> reportWorstViolations 10 -delay_type min_max -nworst 2
In the first example, the number 2 is passed to the $nbrPaths argument, and applied to
-max_paths. In the second and third examples, the numbers 1 and 10 respectively are
applied to -max_paths, and all the subsequent characters are assigned to $args.
The following example provides the procedure definition for the reportCriticalPaths
command that was previously used in the Non-Project mode example script. The procedure
takes a single argument, $filename, and has been commented to explain each section:
#------------------------------------------------------------------------
# reportCriticalPaths
#------------------------------------------------------------------------
# This function generates a CSV file that provides a summary of the first
# 50 violations for both Setup and Hold analysis. So a maximum number of
# 100 paths are reported.
#------------------------------------------------------------------------
proc reportCriticalPaths { fileName } {
# Open the specified output file in write mode
set FH [open $fileName w]
This is especially useful when the procedure is being used interactively. It is a lot friendlier
for the user to be able to specify some command line options like with any Vivado
commands.
Tcl provides an easy way to do this through the args variable. The keyword args used
inside the list of arguments of a procedure can match any number of elements, including
none. The args variable is a regular Tcl list that can be processed and analyzed like any Tcl
list.
There are multiple techniques to parse the command line arguments, and the example code
below shows just one of them:
Explanations:
1. Lines 1-6: Definition for the lshift procedure that removes the first element of a list.
2. Line 9: myproc is defined with a single argument, args, that can take any number of
elements. In this example code, myproc supports three command line options: -ports
< string >, -verbose, and -help.
3. Lines 19-44: Loop through all the command line arguments. When all the arguments
have been processed, the args variable is empty.
4. Line 20: The command line argument that needs to be processed is saved inside the
flag variable. Use the lshift proc to get the argument and remove it from the args
variable.
5. Lines 21-43: Check the content of the flag variable against all the valid arguments. The
switch statement uses the -exact option so that the full option name is checked
against the content of flag. For example, to define the ports, the user needs to specify
-p or -ports.
The -p/-ports option takes a command line argument that is being read and removed
from the list args with lshift args (line 24).
The -v/-verbose option is just a boolean and therefore does not need any additional
argument from args (line 28).
Lines 36-38: Check for any command line argument starting with "-" (without quotes). In
this sample proc, they are not supported.
Lines 39-40: Check for a command line argument that does not start with "-" (without
quotes). In this example proc, they are not supported.
6. Lines 46-64: Display the embedded Help if -h/-help has been specified. Those lines as
well as lines 30-33 can be removed if the proc does not need to provide any embedded
Help.
7. Lines 68-70: Check if any error has occurred. Typically, some additional code to check
the validity of the arguments should happen before line 68. If there would be any error
or, for example, incompatibility between the command line options provided by the
user, then the error variable could be incremented which would then trigger line 69.
8. Line 73 and beyond: Add your code here.
The above code parses the command line arguments and searches for an exact match with
the supported options (line 21). However, there are some cases when it might be better to
match the command line arguments against some expressions instead of searching for an
exact match. This is done by using the -glob switch instead of the -exact switch on line
21. See the following example.
37 incr error
38 } else {
39 puts "ERROR - option '$flag' is not a valid option."
40 incr error
41 }
42 }
43 }
Lines 22, 26 and 30 illustrate some expressions using the "*" as a wildcard. The above code
matches any string starting with -p as a valid command line option to define the ports, for
example -pfoo.
Although the example procedure, myproc, is acceptable for an interactive command, it has
some runtime overhead due to the parsing of the arguments. The runtime overhead might
not be acceptable for a low-level procedure that is called many times. A different technique
can be used to add some command line arguments to a procedure that needs very little
runtime overhead. This is done by assigning the list of commands line arguments to a Tcl
array. However, this implies that each command line option has one and only one argument.
See the following example.
Explanations:
1. Line 1: myproc2 is defined with a single argument, args, that can take any number of
elements. However, since args is used later to set a Tcl array, it must have an even
number of arguments.
2. Line 3: Default values for the various options. Each option has one and only one value.
3. The format of the list is:
<option1> <valueForOption1> <option2> <valueForOption2> … <optionN> <valueForOptionN>
4. Line 5: The Tcl array options is initialized with the default values.
Note: The command line options that are working as a flag and have no intrinsic value are easily
implemented by passing, for example, a value of 0 or 1 with the option. In the previous example
procedure, the flag -v is turned on with: myproc2 -v 1.
The parameters defined as the arguments of a procedure are, by default, local variables.
Whenever a procedure is called (for example reportCriticalPaths $myfilename),
the content of the calling variables (for example $myfilename) are copied inside the stack
of the procedure. If the calling variables are Tcl lists with a large number of elements, this
mechanism has a runtime and memory penalty. There are also some scenarios when it is
necessary to modify the content of the caller variables. Tcl provides a way to do that by
passing a variable name as a reference instead of passing the content of the variable. Once
a variable is passed as a reference, any modification of the variable inside the procedure
directly modifies the caller's variable inside the caller's space. The keyword upvar is used
inside the body of the procedure to define a parameter that is passed as reference. The
procedure lshift that has been introduced earlier uses this technique:
In the example proc myproc, lshift is called by passing the variable name args instead
of the content $args.
A global variable is a variable created outside of a procedure and that belongs to the global
namespace. To refer to a global variable inside a procedure, the keyword global is used
followed by the variable name:
proc printEnv {} {
global env
foreach var [lsort [array names env]] { puts " $var = $env($var)" }
}
The above example defines a procedure printEnv that prints the system environment
variables. The Tcl array, env is a global variable initialized when the Vivado tools start. The
printEnv procedure refers to the global env variable through the global env command.
After the global variable is declared, it is accessed like any local variable. The global variable
can be read and modified.
Another way to access a global variable is to specify the namespace qualifier with it. The
namespace qualifier for the global namespace is "::" (without any quotes) and therefore a
procedure can refer to the global variable env with ::env. The syntax is the same for any
global variable. For example:
proc printEnv {} {
foreach var [lsort [array names ::env]] { puts " $var = $::env($var)" }
}
Since printEnv specifies the full path to the env variable, the procedure does not need to
declare global env.
Note: Xilinx does not recommend that you use global variables as they rely on variable names
created outside the scope of the procedure. Global variables are sometimes used to avoid having to
pass large Tcl lists to a procedure. The upvar technique should always be considered before using a
global variable.
Note: When using the run infrastructure in Project mode, it is not possible to share global variables
defined inside the Vivado environment with the hook scripts. Refer to Getting User Input for
recommended methods to share information between scripts.
Note: The close_project and close_design commands do not change the state of the Tcl
interpreter. All the global variables and user created namespaces are persistent after running those
commands.
Instead of defining all the variables and procedures in the global namespace, Tcl supports
the concept of namespace that encompasses variables and procedures inside a more
private scope. Namespaces can also be nested, so a namespace can be defined inside
another namespace without restriction on the number of levels of scoping. Namespaces
add a new syntax to procedure and variable names. A double-colon, ::, separates the
namespace name from the variable or procedure name.
Below is an example that illustrates how a namespace is created and how procedures and
variables are assigned to the namespace. This example creates a namespace, foo that
reproduces the functionality of a small stack with two public procedures (push and pop):
Explanations:
2. Line 1 declares the namespace, foo and line 29 is the closing curly bracket of the
namespace definition.
3. Variables inside the namespace are created with the command variable (lines 2-4):
variable <varname> ?<varvalue>?
A Tcl array cannot be initialized with the variable command. It needs to be created
first (line 4) and initialized afterward (line 5).
Note: Do not use the set command to declare variables inside a namespace as it will confuse
the Tcl interpreter in the case the same variable name exists in the global namespace.
4. Procedures can be created directly inside the namespace definition or outside. When a
procedure is created within the command, namespace eval … { … }, it does not
need to have the namespace qualifier in the name (in this example foo::).
Lines 9 and 16: push and pop are created inside the namespace definition
5. Procedures can also be created outside of the namespace definition and added to the
namespace by using the full namespace qualifier prepended to the procedure name. In
the above example, the procedure dump (line 31) is created output of the namespace
definition but added to the namespace foo.
6. Lines 10-11, 17-18, 32-33: Procedures refer to variables created inside the namespace
using the keyword variable.
7. A procedure created inside a namespace can be accessed with the full namespace
qualifier, for example foo::push, foo::pop and foo::dump. From within the
namespace itself, the namespace qualifier is not needed when referring to procedures
from the same namespace. For instance, if the procedure dump needs to call push, it
does not need to specify foo::push, but just push.
8. Line 7: The namespace supports the concept of public and private procedures. Although
all the procedures within a namespace can be accessed with the full namespace
qualifier, a namespace can specify which of the procedures can be exported outside of
the namespace with the command, namespace export… . Once a procedure name is
exported, it can be imported into the global namespace with the command, namespace
import… (line 45). Doing that enables the procedure to be directly called without
having to specify the full namespace qualifier.
Template Script
Below is a template script based on the notions that been introduced earlier. It illustrates:
1. Usage of a private namespace to avoid polluting the global namespace (lshift is only
available inside the namespace foo).
2. Handling of command line arguments (including -help and -version to provide a
version of the script).
3. Usage of return -error (or error) command to generate Tcl errors when it is
needed.
namespace eval foo {
namespace export myproc
variable version 1.0
}
#-------------------------------------------------------
# Process command line arguments
#-------------------------------------------------------
set error 0
set help 0
set verbose 0
set ports {}
# if {[llength $args] == 0} { incr help }; # Uncomment if necessary
while {[llength $args]} {
set flag [lshift args]
switch -exact -- $flag {
-p -
-ports {
set ports [lshift args]
}
-v -
-verbose {
set verbose 1
}
-h -
-help {
incr help
}
-version {
variable version
return $version
}
default {
if {[string match "-*" $flag]} {
puts " ERROR - option '$flag' is not a valid option."
incr error
} else {
puts "ERROR - option '$flag' is not a valid option."
incr error
}
}
}
}
if {$help} {
set callerflag [lindex [info level [expr [info level] -1]] 0]
# <-- HELP
puts [format {
Usage: %s
[-ports|-p <listOfPorts>]
[-verbose|-v]
[-version]
[-help|-h]
Description: xxxxxxxxxxxxxxxxxxx.
xxxxxxxxxxxxxxxxxxx.
Example:
%s -port xxxxxxxxxxxxxxx
} $callerflag $callerflag ]
# HELP -->
return -code ok {}
}
if {$error} {
return -code error {Oops, something is not correct}
}
# Do something
return -code ok {}
}
The Vivado Design Suite Tcl interpreter provides access to many first class objects such as
project, device, nets, cells, and pins. The Vivado Design Suite updates these design objects
dynamically, as the design progresses, and loads them into the in-memory database in both
Project and Non-Project modes.
You can interactively query design objects, analyze the state of your project, write a script
to access the in-memory design, and run custom reports or execute optional design flow
steps. Each object comes with a number of properties that can always be read and
sometimes written. Most design objects are related to other design objects, allowing you to
traverse the design to find related objects or information.
You can query design objects using the get_* Tcl commands which return list of design
objects, that can be directly manipulated, or assigned to a Tcl variable. The complete list of
get_* commands can be returned with help get_*. Caching objects in variables can save
runtime by reducing the number of queries to the design database. Querying the list of nets
or pins can be a time consuming process, so saving the results can speed the design flow
when accessing the information repeatedly. See Caching Objects for more on this topic.
Each class of design object (net, pin, port, …) has a unique set of standard properties that
can be read and sometimes written to modify their value in the database. In addition, the
design attributes specified in the RTL source files, the Verilog parameters and VHDL
generics are stored with the associated netlist object as properties. For example, a port
object has a property that indicates its direction, while a net object has a property that
defines its fanout. The Vivado tools provides a number of commands for adding, changing,
and reporting these properties. Using the get_* -filter option lets you get a list of
design objects that is filtered, or reduced, to match specific property values, as described in
Filtering Results. We can get the list of properties on an object by using the
list_property command. When a property type is enum, it is possible to get the list of
all the valid values by using the list_property_value command.
There are two properties that are common to all objects: NAME and CLASS. When an object
is assigned to a Tcl variable, a pointer to the object is stored in the variable. Objects can be
passed by variable to Tcl commands or Tcl procs. When an object is passed as an argument
to a Tcl proc or command which expects a string, the object’s NAME property value is
passed instead of the object itself. The example below shows a cell object assigned to the
variable, $inst, and the results of the puts command and the report_property
command on the $inst variable. Notice that the puts command just prints the object
NAME because it only works with strings, while the report_property command returns
all of the object properties and their values:
puts $inst
cpuEngine
report_property $inst
Property Type Read-only Value
CLASS string true cell
FILE_NAME string true
C:/2014.1/cpu/project_1.srcs/sources_1/imports/netlist/top.edf
IS_BLACKBOX bool true 0
IS_PRIMITIVE bool true 0
IS_SEQUENTIAL bool true 0
LINE_NUMBER int true 812044
NAME string true cpuEngine
PRIMITIVE_COUNT int true 11720
REF_NAME string true or1200_top
You can also create custom properties for any class of design objects in the Vivado Design
Suite. This can be useful when you want to annotate some information from a script onto
the in-memory design objects. The following example creates a property, SELECTED, for a
cell object. The value of the property is defined as an integer.
Once a property has been created on a class of objects, it can be managed on a specific
object with set_property and get_property commands, and reported with
list_property and report_property commands. The following example sets the
SELECTED property to a value of 1 on all the cells that match the specified name pattern,
*aurora_64b66b*:
As an example, Figure 2 shows a hierarchical design where the modules A and B are
instantiated at the top-level. Module A includes the a1 and a2 hierarchical instances, and
module B includes the b1 and b2 hierarchical instances. Each of a1, a2, b1, and b2 has leaf
cells (unisim instances) inside, as indicated in the figure.
Although the get_* commands only search the top-level, or the level of the current
instance, you can specify a search pattern that includes a hierarchical instance name relative
to the current instance. By default, the current instance is set to the top-level of the design.
To query the instance b1 from the top-level, you can specify the following name pattern:
get_cells B/b1 ; # Search the top-level for an instance with a hierarchical name.
However, one important feature of the -hierarchical option is that the Vivado tools try
to match the specified name pattern at each level of the design hierarchy, and not against
the full hierarchical name of an object. In general, when -hierarchical is used, the
specified search pattern must not include the hierarchical separator otherwise no object
will be returned. There is an exception to this rule when the netlist has been partially
flattened during synthesis. That is when the hierarchy separator is also used to mark the
flattened netlist level. In this case, it is possible to use it in the search pattern as it only
represents a level of hierarchy in the name and not in the design loaded in memory.
The following example is based on Figure 2 which shows a purely hierarchical netlist.
set result {}
foreach hcell [list "" A B A/a1 A/a2 B/b1 B/b2] {
current_instance $hcell ;# Move scope to $hcell
set result [concat $result [get_cells <pattern>]]
current_instance ;# Return scope to design top-level
}
IMPORTANT: When -hierarchical is used with -regexp , the specified search string is matched
against the full hierarchical name, and B/.* will return all cell names that match this pattern. For
example, based on Figure 2, get_cells -hierarchical -regexp B/.* returns all the cells
below the block B. See the Vivado Design Suite Tcl Command Reference Guide (UG835) [Ref 1] for more
information on -regexp .
Note: The local name of an object refers to the part of the name that comes from the current
hierarchical level (current_instance). It does not include the part of the name inherited from the
parent.
Note: When some parts of the design have been flattened, the local name of objects that belonged
to the flattened levels includes the hierarchical separator. In such a case, the hierarchy separator in
this part of the name is not seen any more as a separator, but just as a literal character.
Note: The -filter option specifies a filtering expression where the pattern matching inside the
expression follows the global expression format. A filtering expression involves string matching
based on object properties and can be as complex as required. When the NAME property is used
inside a filtering expression, the full hierarchical name of the object is used for the string matching
and not its local name. However, only objects that belong to the current hierarchical level
(current_instance) are being considered. If -hierarchical is used with -filter, then all the
objects that belong to the current hierarchical level and below are considered for the filtering. If
-regexp is used with -filter, the pattern matching inside the expression follows the regular
expression format.
Note: The -regexp option implies that the pattern provided to the command is a regular
expression. Be careful as some characters, such as * . [ ] +, have a special meaning inside a
regular expression. Those characters need to be escaped when used as literal and not as special
characters in the context of the regular expression.
The string matching is case sensitive and always anchored to the start and end of the search
string. To match a sub-string of a search string, use the following syntax depending on
whether or not a regular expression is used:
Following are some examples based on the cpu_hdl project, which can be found under the
Open Example Project link on the Getting Started page of the Vivado IDE, that illustrate the
differences between the options.
• Get all the cells under the current instance: there is only one (hierarchical) cell:
vivado% get_cells
fftEngine/fftInst/ingressLoop[7].ingressFifo/buffer_fifo
vivado% get_cells -hier
fftEngine/fftInst/ingressLoop[7].ingressFifo/buffer_fifo
fftEngine/fftInst/ingressLoop[7].ingressFifo/buffer_fifo/infer_fifo.two_rd_addr_reg
[8]_i_1__29 … (154 other cells)
• The local name of the cells under the current instance and below does not include
ingressLoop. The string ingressLoop is inherited from the parent cell and is part of
the full hierarchical name:
vivado% get_cells *ingressLoop*
WARNING: [Vivado 12-180] No cells matched '*ingressLoop*'.
vivado% get_cells *ingressLoop* -hier
WARNING: [Vivado 12-180] No cells matched '*ingressLoop*'.
• With the -filter option, the NAME property matches the full hierarchical names:
vivado% get_cells -filter {NAME =~ *ingressLoop*}
fftEngine/fftInst/ingressLoop[7].ingressFifo/buffer_fifo
vivado% get_cells -filter {NAME =~ *ingressLoop*} -hier
fftEngine/fftInst/ingressLoop[7].ingressFifo/buffer_fifo
fftEngine/fftInst/ingressLoop[7].ingressFifo/buffer_fifo/infer_fifo.two_rd_addr_reg
[8]_i_1__29 … (154 other cells)
The last query, get_cells -hier -regexp {.*reg[.*].*} does not match any cell
since the square brackets, [] have not been escaped. As a result, they are processed as
special characters for the regular expression and not as literal square brackets in the cell
name.
When a range of values needs to be specified in the filtering expression, the -regexp
option should be used in addition to the -filter option. For example, the code below
only gets the cells from *reg[0]* to *reg[16]*. The regular expression is built around
matching .*reg\[[0-9]\].* or matching .*reg\[1[0-6]\].* as shown below:
In another example, both commands below return all the tiles matching CLB*X*Y*,
excluding the tiles from CLB*X1Y* to CLB*X16Y* with X between 1 and 16:
The names of pins are based on the instance they belong to. When searching for pins, you
must use the hierarchy separator character to separate the instance name and the pin name
patterns. The following examples are illustrated by Figure 3.
You can also use the -hierarchical option when searching for pins:
Note: -hierarchical and -hier refer to the same option. The Vivado Design Suite Tcl shell
completes option names automatically if enough characters are provided to identify a unique
option. Therefore, -of_object and -of can also refer to the same option.
Filtering Results
More often than not, when you use get_* to search for design objects, you are only
interested in a subset of the objects returned. You might not want all of the netlist objects
in the design, but for example, only cells of a certain type, or nets of a certain name. In some
cases, only a subset of elements are of interest and need to be returned.
X-Ref Target - Figure 4
You can limit the search results, by narrowly defining your search pattern, using wildcards ‘*’
and ‘?’, or using -regexp to build complex search patterns to evaluate. You can limit the
scope of hierarchy being searched, by setting the current_instance or by specifying
-hierarchy.
For example, using the design shown in Figure 4, the following expressions return different
results:
The -filter option lets you filter the results of the get_* commands, based on specific
properties of the objects being searched. For example, the following command returns all
the cells with a hierarchical name that begins with B/b*, and that have not been placed by
the user, so that IS_LOC_FIXED is FALSE, or 0:
IMPORTANT: The NAME property contains the full hierarchical name of the object. When filtering on
the NAME property, the pattern is evaluated against the complete NAME string, regardless of the other
options used in the command, including -hierarchical.
The -filter option causes Vivado to filter the results of a query before it is returned.
However, in some cases you may have assigned the results of a prior search to a variable,
that is now stored in memory. The filter command lets you filter the content of any list
of objects, including lists stored in a variable. Using the results of the prior example, stored
in $unLoced, you can further filter the list of objects as follows:
The preceding example filters the stored results of the prior search, filtering the list to
return only the objects that are primitive instances in the design.
IMPORTANT: The filter command does not modify the original Tcl variable and therefore the result
must be saved inside another Tcl variable.
TIP: Note the direct use of the boolean properties IS_LOC_FIXED and IS_PRIMITIVE in the example
above. Boolean (bool) type properties can be directly evaluated in filter expressions as true or false.
The specific operators that can be used in filter expressions are "equals" and "not-equals"
(== and !=), and "contains" and "not-contains" (=~ and !~). Numeric comparison operators
<, >, <=, and >= can also be used. Multiple filter expressions can be joined by AND and OR
( && and ||).
is accomplished through the use of the -of_objects option supported by many of the
get_* commands. Figure 5 illustrates the relationship of objects in the in-memory design.
X-Ref Target - Figure 5
NET
CELL
PORT
PIN
CLOCK
8
The Help message for each of the get_* commands that supports the -of_objects
option lists the related objects that can be traversed:
With the -of_objects option, getting the list of all pin objects attached to a list of net
objects becomes very simple:
To only get the list of drivers for those nets you just need to use the -filter option:
Note: If an empty list of objects is passed through -of_objects, then the get_* command
returns an empty Tcl list.
You can also get the list of pins from a list of cells, or a list of cells from a list of nets and so
on.
X-Ref Target - Figure 6
get_pins -of [get_nets -of [get_pins -of [get_nets -of [get_pins A/a1/clk]]]]
A/a2/clk A/clk A/a1/clk B/clk
Notice that the last get_pins command returns the clock pin of hierarchical module B,
B/clk, along with the other pins that have already been returned. However, to cross the
hierarchy, and return the primitive pins on the clock net object, you can use the -leaf
option of the get_pins command. The following example shows what is returned when
-leaf is used:
get_pins -leaf -of [get_nets -of [get_pins -of [get_nets -of [get_pins A/a1/clk]]]]
B/b1/data_reg/C A/a2/data_reg/C A/a1/data_reg/C B/b2/data_reg/C
get_nets Command
The get_nets command can return multiple representations of the same net as the net
traverses through the design hierarchy. Below are some examples using the options
provided with get_nets to ensure that the proper representation of the net is selected.
The following examples use the leaf pin of a LUT2 as defined below to query different
segments of the net connected to the leaf pin.
Simply getting the net connected to the leaf pin mypin returns the net segment within the
hierarchy directly connected to the leaf pin.
In order to select all segments of the net connected to leaf pin mypin, use the -segments
option.
Timing path objects can be very practical to perform advanced scripting related to static
timing analysis. The timing path object can also be used to generate the full text report of
the path using report_timing -of <timingPathObject>.
The commands get_nets, get_cells, or get_pins can be used on a timing path object
to query list of nets/cells/pins in the datapath section of the path. The design elements
inside the source and destination clock networks cannot be queried.
The list of objects returned from a timing path objects by get_nets, get_cells, or
get_pins is sorted based on the appearance of the design elements inside the datapath.
Persistency of Objects
A Vivado object persists as long as the element it points to exists in memory. For example,
if a Tcl variable points to a cell object and the cell is deleted afterward (either manually or
thought some optimization steps), the cell object becomes null. This could lead to
unexpected results or crash if you execute a command that relies on it.
In the same way, once a design or a project is closed, all the design objects and potentially
all the other Vivado objects are nullified, and any Tcl variable pointing to Vivado objects
that no longer exist is stalled.
CAUTION! If you execute a command that relies on an object that no longer exists in memory, the
command could produce unexpected results or cause a system crash.
close_project
Once the project is closed, all the objects (i.e., port objects in this example) are nullified and
therefore it is no longer possible to print the list of ports.
To be able to print the list of ports after the design is closed, the associative array 'dir'
should have been built using the property NAME of the 'port' object:
The built-in Tcl commands that handle lists in the Vivado Design Suite have been
overloaded and enhanced to fully support objects and containers of objects. For example,
lsort, lappend, lindex, and llength, have been enhanced to manage the container
based on the NAME property of the object. The result of these commands, when passed a
container of objects, returns a container of objects. For example, lsort will sort a container
of cells from the get_cells command based on the hierarchical names of the objects.
You can add new objects to the container (using lappend, for instance), but you can only
add the same type of object that is currently in the container. Adding a different type of
object, or string, to the list is not permitted and will result in a Tcl error.
The following example shows a Vivado container being sorted in a descending order, and
each object put onto a separate line, by using the puts command and a foreach loop:
Note: Although the lappend command is supported by the Tcl Console, it is not supported in a
XDC constraint file with the read_xdc command. However, it is possible to convert a list built with
the lappend command in a different way that is compatible with the read_xdc command. In the
following example:
set myClocks {}
lappend myClocks [get_clocks CLK1]
lappend myClocks [get_clocks CLK2]
lappend myClocks [get_clocks CLK3]
The Tcl variable myClocks can be built differently to be compatible with the read_xdc
command:
Vivado collections have been implemented in Tcl to improve runtime and reduce the
memory footprint when dealing with Vivado objects.
Now, when a Vivado collection is converted as a string, it is possible to limit the number of
objects to be converted. So, for example, if you print in the Tcl console a list of instances,
and that the list (a Vivado collection under the hood) has 100,000 instances, only the first
500 (default limit) instances will be exported. This avoids cluttering the Tcl console with a
string that could be extremely long.
The maximum number of elements can be displayed by any command that displays a
collection. You can make this unlimited by setting the limit to 0. (default: 500). For example:
set_param tcl.collectionResultDisplayLimit 0
set_param tcl.collectionResultDisplayLimit 1000
When a Vivado collection has more elements than the limit defined by the parameter
tcl.collectionResultDisplayLimit, only the first nth elements are converted as a
string, then '...' is added at the end of the string representation to indicate that more
elements in the original collection have not been included.
Note: The string representation does not alter the original collection in any way so there is never
any loss of elements in the original collection.
Note: The parameter tcl.collectionResultDisplayLimit only applies to string
representation of Vivado collections. It does not apply to string representation of regular Tcl lists.
Redirecting Output
Many of the Vivado Design Suite Tcl commands allow you to redirect the information
returned by the command to a file with the -file option, for printing or processing
outside of the tool; or as a string that can be saved in a variable with the -return_string
option for further processing within the Vivado tools.
All of the report commands support the -file option. File output is useful for report
commands that output a great deal of information, that may require further review, or
support the documentation of a design project, or to pass to downstream processes such as
other design disciplines, or other departments. Some of the commands supporting file
output include:
report_datasheet
report_drc
report_power
report_timing
report_timing_summary
report_utilization
A relative or absolute path can be specified as part of the file name. A relative path is
relative to the directory from which the Vivado tools have been started, or to the current
working directory which can be retrieved with the pwd command.
TIP: If the path is not specified as part of the file name, the file is written into the current working
directory, or the directory from which the Vivado tools were launched.
To append the content from a command to an existing file, use the -append option in
addition to -file. For example, the code below creates one file, all_violations.rpt,
that combines the output of two separate commands:
After the file has been created, you may have need to access the file from the file system,
opening the file to read from it, or to write to it. The Vivado Design Suite Tcl console offers
a number of commands for accessing files. See Accessing Files for more information.
All report_* commands also support the -return_string option. This option directs
the command to return its output as a string that can be assigned to a Tcl variable.
Assigning the command output to a variable is useful for further processing within the Tcl
script, to allow extraction of key information to enable flow control, branching, and to set
other variables for use in the script.
report_clocks
report_clock_interaction
report_disable_timing
report_environment
report_high_fanout_nets
report_operating_conditions
report_power
report_property
report_pulse_width
report_route_status
report_utilization
You can split the returned string from the report on the newline character, \n, to process
the string line by line as a list:
The Vivado Design Suite Tcl console also offers many tool for working with strings. See
Working with Strings for more information.
Accessing Files
After a file has been written to the file system, Tcl provides many useful commands for
working with the files. You can extract elements of a file, such as the file path, file name and
file extension. Some of the Tcl commands available to examine information about file
include:
• file exists filename - A boolean test that returns 1 if filename exists, and you
have permission to read its location; returns 0 otherwise. Use this to determine if the
file you are looking for already exists.
• file type filename - Returns the type of filename as a string with one of the
following values: file, directory, characterSpecial, blockSpecial, fifo,
link, or socket.
• file dirname filename - This returns the directory structure of the fileName, up
to but not including the last slash.
• file rootname filename - Returns all the characters in filename up to but not
including last dot.
• file tail filename - Return all characters in filename after the last slash.
• file extension filename - Returns all characters in filename after, and
including, the last dot.
After the Vivado tools have created a file, through a report_* command, or write_*
command, you can open the file from within a Tcl script to read its contents, or to write
additional content. To open, read from, write to, and close a file, you can use some of the
following Tcl commands:
• open <filename> [access] [ perms ] - Opens the filename and returns the file
handle, or fileID, used to access the file. It is a standard practice to capture the fileID in
a Tcl variable, so that you can refer to the file handle when needed. The file permissions
of a new file are set to the conjunction of perms and the process umask. The access
mode determines whether you can read to or write to the open file. Some common
access modes are:
° r - Read only. The file must exist; it will not be created. This is the default access
mode if one is not specified.
° w - Write only. This will create the specified file if it does not already exist. The data
is written to the front of the file, truncating or overwriting the content of an existing
file.
° a - Append only. This will create the specified file if it does not already exist. The
data is written at the end of the file, appending to any existing file content.
• read [-nonewline] fileId - Read all remaining bytes from fileId, optionally
discarding the last character if it is a newline, \n. When used in this form right after
opening the file, the read command will read the entire file at once.
• read fileId numBytes - Read the specified number of bytes, numBytes , from
fileId. Use this form of the command to read blocks of the file, up to the end of the
file.
• eof fileId - Returns 1 if an end-of-file (EOF) has occurred on fileId, 0 otherwise.
• gets fileId [varName ] - Read the next line from fileId, discarding the newline
character. Places the characters of line in $varName if given, otherwise returns them to
the command shell. The following are different forms of the gets commands:
gets $fileHandle
Append line 4 of file.
gets $fileHandle line
28
puts $line
Append line 5 of file.
set line [gets $fileHandle]
Append line 6 of file.
puts $line
Append line 6 of file.
In the preceding example, $fileHandle is the file handle returned when the file was
opened. The first line uses the simple form of gets, without specifying a Tcl variable to
capture the output. In this case the output is returned to stdout. The second form of
the command assigns the output to a variable called $line, and the gets command
returns the number of characters it has read, 28.
Note: You can assign the return of the gets command to a Tcl variable, but depending on which
form you are using you may capture the contents of the file, or the number of characters the gets
command has read.
• puts [-nonewline] [fileId] string - Write a string to the specified fileId,
optionally omitting the newline character, \n. The default fileId for the puts
command is stdout.
• close fileId - Close the open file channel fileId. It is very important to close any
files your Tcl scripts have opened, or you may develop memory leaks in the Vivado
application, or encounter other undesirable effects.
The following example opens a file in read access mode, storing the file handle as $FH,
reads the contents of the file in a single operation, assigning it to $content, and splits the
contents into a Tcl list. The file is closed upon completion.
Note: It is not recommended to read large files in a single operation due to performance and
memory considerations.
Rather than reading the entire file at once, and then parsing the results, the following
example reads the file line-by-line until the end of the file has been reached, and writes the
line number and line content to stdout. The file is closed upon completion:
The example below writes to a file, ports.rpt, saving all the I/O ports from the design,
with the port direction, sorted by name:
In the example above, the file is opened in write mode. Unlike read mode, the write mode
will create the file if it does not exist, or overwrite the file if it does exist. To write new
content to the end of an existing file, you should open the file in append mode instead.
After the string has been assigned to a variable, Tcl provides many useful commands for
processing the string in a number of ways:
• append string [arg1 arg2 ... argN] - Appends the specified args to the end
of string .
• format formatString [arg1 arg2 ... argN ] - Returns a formatted string
generated to match the format specified by the formatString template. The
template must be specified using % conversion specifiers as used in sprintf. The
additional arguments, args , provide values to be substituted into the formatted string.
• regexp [switches] exp string - Returns 1 if the regular expression, exp ,
matches all or part of string , 0 otherwise. The -nocase switch can be specified to
ignore character case when matching.
• string match pattern string - Returns 1 if the glob pattern matches
string, 0 otherwise.
• scan string formatString [ varName1 varName2 ...] - Extracts values from
the specified string into variables, varName, applying the formatString using %
conversion specifiers as in sscanf behavior. If no varNames are specified, scan
returns the list of values to stdout.
• string range string first last - Returns the range of characters from string
specified by character indices first through last inclusive.
• string compare string1 string2 - Performs a lexicographical comparison of
two strings, and returns -1 if string1 comes before string2 , 0 if they are the same,
and 1 if string1 comes after string2.
• string last string1 string2 - Return the character index in string2 of the
last occurrence of string1. Returns -1 if string1 is not found in string2 .
• string length string - Returns the number of characters in string.
The following example assigns the results of the report_timing command to the
$report Tcl variable, using -return_string. The string is processed to extract the start
point, end point, path group and path type of each path. After the path information is
extracted, a summary of that path is printed to the Tcl console.
# Split the return string into multiple lines to allow line by line processing
foreach line [split $report \n] {
if {[regexp -nocase -- {^\s*Source:\s*([^[:blank:]]+)((\s+\(?)|$)} $line - startPoint]} {
} elseif {[regexp -nocase -- {^\s*Destination:\s*([^[:blank:]]+)((\s+\(?)|$)} $line - endPoint]} {
} elseif {[regexp -nocase -- {^\s*Path Group:\s*([^[:blank:]]+)\s*$} $line - pathGroup]} {
} elseif {[regexp -nocase -- {^\s*Path Type:\s*([^[:blank:]]+)((\s+\(?)|$)} $line - pathType]} {
puts [format " %-12s %-12s %-20s -> %-20s" $pathType $pathGroup $startPoint $endPoint]
}
}
Controlling Loops
Tcl has few built-in commands such as for, foreach and while that are used to loop or
iterate through a section of code.
With all the above commands, the entire Tcl script body is executed at each iteration.
However, Tcl provides two commands to change the control flow of the loop: break and
continue.
The break statement is used to abort the looping command. The continue statement is
used to jump to the next iteration of the loop.
Note: When running inside a proc, the loop can also be aborted using the return command. In this
case, not only the loop is aborted but the control goes back to the caller of the proc.
For example, let us suppose that we have a file that contains a list of cell names with the
format of one instance name per line. The sample code below reads this file and build a Tcl
list that only includes the cell names that currently exist in the design. The code reuses the
procedure get_file_content that was introduced earlier. If too many cell names are not
found inside the current design then the code stops processing the content of the file:
puts " [llength $valid_cell_names] valid cells have been found "
Error Handling
Checking Validity of Variables
When developing Tcl scripts, it is recommended to always check for corner cases and for
conditions where the code could fail. By doing the proper checks, it is possible to inform the
user of issues and/or incorrect usage of the script. If the checks are not correctly performed,
then the script could stop without informing the user about what went wrong and therefore
what should be corrected.
Although the above script seems algorithmically correct, it would not work properly as the
open command generates a low-level Tcl error (TCL_ERROR) that would stop the execution
of the script in the event the file could not be opened. Later, in Example 3 we will see how
this script can be improved.
Example 2: Check that the Vivado objects are valid after using the get_* commands.
It is especially important to check that Vivado objects do exist after using the get_*
commands when those objects are used inside other commands (filter, get_*, …).
To do safe programming and catch the TCL_ERROR condition, Tcl has a built-in catch
command that returns 1 when an error is caught and otherwise returns 0. The catch
command can be used on a single command or a set of commands.
Where the script is a single or a set of Tcl commands and varname is a variable name in
which the message explaining the TCL_ERROR is saved.
Example 1 can be made safer using the catch command to cover the case where the file
cannot be opened:
A Tcl error can also be user generated using the error command. This can be used, for
example, to propagate a TCL_ERROR that is caught with the catch command to the upper
level (bubbling). However, the error command can be used as well to generate a
TCL_ERROR when, for example, a corner case is not supported by the script or an
unexpected condition has happened in the code.
For example, the proc below returns the file content or generates a TCL_ERROR when the
file cannot be opened:
The proc get_file_content can be called through a catch command to catch the
potential error:
Example 2 can also be improved to generate a TCL_ERROR when a wrong condition occurs
as shown in Example 4:
Example 4: Check that the Vivado objects are valid. Generate a TCL_ERROR otherwise
(revised).
Note: After initialization, any change to the env variable is not applied to the environment outside
of the Tcl interpreter. Similarly, any change to your environment variables done after starting the Tcl
interpreter will not be reflected by the env variable.
The keys of the env array are the environment variables at the time Vivado Design Suite
starts. The keys are case sensitive.
For example:
It is possible to check if an environment variable exists (i.e a key to env array exists) by
using the info command. For example to check for MYVARNAME:
The env array is a global variable and can therefore be referenced inside a proc after being
declared as global.
For example:
proc print_env {} {
global env
puts " UNIX Environment:"
foreach var [lsort [array names env]] {
puts " $var : $env($var)"
}
}
It is important to use the exec command for consistency of results, to make sure that the
script works under every host OS (Windows or Linux) and all Vivado modes (Tcl mode, GUI,
or batch mode).
The following example (Linux) gets the list of all files and directories under the run
directory by calling the ls command.
It is not recommended to call the ls command without exec as the script could fail in
some of the Vivado modes (see Vivado Integrated Design Environment (IDE)/Tcl Modes
Versus Batch Mode).
The next example executes a Perl script and sends the result to the Tcl environment. Note
that the exec command calls /bin/perl (assuming it matches your environment), which
in turn calls the Perl script itself:
This behavior is inherent to Tcl and is not related to the Vivado tool. Literature can be found
on the web that explains the underlying reasons.
But the consequence is that during an interactive session (Tcl or GUI modes), Vivado runs
under tclsh mode. However, in batch mode, Vivado runs in Tcl script mode.
Although in all three modes (Tcl, GUI and batch) the Tcl console behaves mostly the same,
the Tcl environment is slightly different. One difference is that in batch mode, the unknown
commands are not sent to the OS for execution. To make sure that a script will work under
all the three Vivado modes, it is recommended to explicitly use the exec command to
execute external programs.
• The basis of creating a custom DRC is a Tcl checker procedure that gets design objects
of interest, or attributes of those design objects, and a checking function that defines
the design rule. The Tcl checker procedure is defined in a separate Tcl script that must
be loaded into the Vivado Design Suite prior to running report_drc. Inside of the Tcl
checker procedure, the create_drc_violation command is used to identify and
flag violations when checking the rule against a design. The create_drc_violation
command creates a violation object within the in-memory design, with properties that
can be reported and further processed in the Vivado Design Suite.
• The Tcl checker procedure is associated to a user-defined DRC that is created using the
create_drc_check command. Call this rule by name when you run the report_drc
command.
• Optionally, you can elect to create a DRC rule deck by using the
create_drc_ruledeck command. A DRC rule deck is a collection of DRCs. A mix of
both user-created and predefined DRCs can be added to the user-created DRC rule
deck by using the add_drc_checks command.
• Checking the design against the design rules is performed by running the
report_drc command. When running report_drc, you can specify to run either a DRC
rule deck, user-defined design rule checks, or predefined DRCs.
The following Tcl script defines the dataWidthCheck Tcl checker procedure which checks
the width of the WRITE_B bus. This Tcl script file must be loaded into the Vivado tools prior
to running the report_drc command. Refer to Loading and Running Tcl Scripts for more
information on loading the Tcl checker procedure.
# This is a simplistic check -- report BRAM cells with WRITE_WIDTH_B wider than 36.
proc dataWidthCheck {} {
# list to hold violations
set vios {}
# iterate through the objects to be checked
foreach bram [get_cells -hier -filter {PRIMITIVE_SUBGROUP == bram}] {
set bwidth [get_property WRITE_WIDTH_B $bram]
if { $bwidth > 36} {
# define the message to report when violations are found
set msg "On cell %ELG, WRITE_WIDTH_B is $bwidth"
set vio [ create_drc_violation -name {RAMW-1} -msg $msg $bram ]
lappend vios $vio
}; # End IF
}; # End FOR
if {[llength $vios] > 0} {
return -code error $vios
} else {
return {}
}; # End IF
} ; # End PROC
As you can see from the proc definition, the dataWidthCheck procedure accepts no
arguments and can find everything it needs from the design. It creates an empty list
variable, $vios, to store the violation objects returned by the create_drc_violation
command.
The dataWidthCheck procedure iterates through all of the BRAMs in the design, and
performs an evaluation of the WRITE_WIDTH_B property on each of those cells. If the
WRITE_WIDTH_B of the block RAM cell exceeds a width of 36, a DRC violation is created
with a specific message, $msg. The message contains a placeholder for the cell %ELG and
the width of the bus found, $bwidth. In the dataWidthCheck procedure, the
create_drc_violation command only returns one object, $bram, that maps to the
%ELG placeholder defined in the message string. The create_drc_violation command
supports messaging placeholders for netlist objects, clock regions, device sites, and
package I/O banks by using their respective keys %ELG, %CRG, %SIG, and %PBG.
IMPORTANT: Both the order and the type of objects passed by create_drc_violation must match
the -msg specification in the create_drc_check command, or the expected substitution will not
occur.
A violation object is created using the create_drc_violation each time the tested
block RAM exceeds the allowable width of the WRITE_WIDTH_B property. The violation
object is given the same name as the associated DRC rule in the Vivado Design Suite. It
includes the previously defined messaging string, and identifies the specific object or
objects that are involved in violation of the rule. The standard object that the design rule
violation can return includes cells, ports, pins, nets, clock regions, device sites, and package
I/O banks. The message string from the violation can also pass other information, such as
the value of a specific property, in order to provide as much detail in the DRC report as
needed.
If any violations are found, the dataWidthCheck proc returns an error code to inform the
report_drc command of the results of that specific check:
In addition to the error code, the violation objects are returned with the $vios variable,
which stores a list of violation objects created by the procedure.
First, you must register the new design rule using the create_drc_check command. This
command requires you to provide a unique name for the user-defined rule check. This
name that must match the name given to the violation created by the Tcl checker
procedure. You will need to specify this unique name when adding the check to DRC rule
decks or when running report_drc. In the dataWidthCheck Tcl checker procedure
above, the create_drc_violation command uses the name RAMW-1. In addition, the
create_drc_check command requires you to provide the procedure name of the Tcl
checker procedure to be run when the rule is checked. In this case above, the Tcl checker
procedure dataWidthCheck is provided as the -rule_body argument and must be
loaded into the Vivado Design Suite prior to running the report_drc command.
You can optionally group the DRC into a special category, provide a description of the rule
for reporting purposes, and assign a severity.
You can define a message to add to the DRC report when violations are encountered. By
default, the message created by the create_drc_violation command in the Tcl checker
procedure is passed upward to the DRC object. In this case, any message defined by
create_drc_violation is simply passed through to the DRC report.
The DRC object features the is_enabled property that can be set to TRUE or FALSE using
the set_property command. When a new rule check is created, the is_enabled
property is set to TRUE as a default. Set the is_enabled property to FALSE to disable the
DRC from being used when report_drc is run.
create_drc_ruledeck myrules
add_drc_checks -ruledeck myrules {RAMW-1 RAMW-2 RAMW-3}
remove_drc_checks {RAMW-2} -ruledeck myrules
Note: If the is_enabled property of the DRC is set to FALSE, then the DRC will not be run as part
of the DRC rule deck when running report_drc. In some cases, it might be more desirable to
disable the DRC than to remove it from the DRC rule deck.
Remember that the is_enabled property of the rule check must be set to TRUE in order
for report_drc to run the check.
The example script below takes as input a pattern matching a set of DRC rule(s) and prints
some explanation (severity and description) for each rule. If the pattern does not match any
rule then an error message is issued.
There are a number of Tcl packages embedded inside Vivado and this example script uses
the struct::matrix package to format the summary table.
The following are some sample outputs from the explain_drc proc:
Manipulating DRCs
DRCs are just like other objects in Tcl and their properties can be changed. Use the
following command to list the properties of a DRC Object.
Note: There are two properties of the RAMW-1 DRC check that you can modify. Those are the
IS_ENABLED property and the SEVERITY property. Change the values of these properties on the DRC
Check object by using the set_property command, just like any other object.
To increase the severity of the RAMW-1 DRC Check, issue the Tcl command:
These properties can also be changed on built-in DRC rules. In order to reset the built-in
DRC rules to factor defaults, use the following Tcl command:
CAUTION! Although Vivado allows you to disable and downgrade the severity of the built-in DRC
Objects, this practice is highly discouraged as it can cause unpredictable results and could potentially
cause permanent damage to the device.
For more information on Running DRCs, see the Vivado Design Suite User Guide:
System-Level Design Entry (UG895) [Ref 7].
Any change to the custom buttons is automatically saved on-disk inside the user area for
the Vivado tools version that is modified. These changes are reflected in subsequent calls of
the same Vivado tools version. Custom buttons do not need to be re-defined every time
Vivado Design Suite is started.
• Through the GUI: Tools > Custom Commands > Customize Commands.
• Programmatically through a Tcl API.
The following table lists commands of the Tcl API to create or delete custom GUI buttons.
A custom button can be defined with or without one or more arguments. After the custom
button has been created using create_gui_custom_command, each argument must be
added with create_gui_custom_command_arg.
When a custom button is removed, Vivado Design Suite automatically removes all its
arguments. There is no need to manually remove the arguments.
Usage:
Name Description
-------------------------------
-name Unique name of the command to create.
[-menu_name] Menu name for the custom command.
[-description] Display this text for the description of the menu item
and optionally the toolbar button
[-show_on_toolbar] Add this command to the toolbar
[-run_proc] Needed when '-command' and 'tcl_file' options are both
specified.
If true, gui button will run command mentioned in
'-command' option otherwise source script mentioned in
'-tcl_file' option
[-toolbar_icon] The full path to the PNG or JPEG file to display on the
toolbar button
[-command] The command to execute
[-tcl_file] The full path to the Tcl file to source
[-quiet] Ignore command errors
[-verbose] Suspend message limits during command execution
The name specified using -name must be unique among all the custom buttons and should
not contain any spaces. This name is used to add arguments to the button.
Example 1
Example 2
Create a custom button to print inside the Tcl console the clock(s) propagating through the
selected object(s):
Usage:
Name Description
-----------------------
[-quiet] Ignore command errors
[-verbose] Suspend message limits during command execution
<names> name of one or more custom commands to remove
The custom buttons defined in Example 1 and Example 2 can be removed using the
following commands:
remove_gui_custom_command myButton
remove_gui_custom_command getClock
Usage:
Name Description
--------------------------
-command_name Unique name of the custom command for which an argument is
being created.
-arg_name Unique name of the custom command argument to create.
[-default] Default value of the custom command argument.
[-comment] Comment for the custom command argument.
[-optional] Make the custom command argument optional.
[-quiet] Ignore command errors
[-verbose] Suspend message limits during command execution
In the example below, three arguments are created for the button, myButton. The last two
arguments are optional.
Note: The first time you open the Xilinx Tcl Store GUI, a disclaimer window displays the terms of
usage of the Xilinx Tcl Store.
The left panel shows the available apps. The right panel provides information on the app
selected in the left panel. The detailed information for each app includes the following:
Installing an App
To install an app, click the Install button on the right side of the app name. Once installed,
the procs defined in the app become available for use. The procs are pulled to a specific
namespace (built from the app name and company name) and behave like native Vivado
built-in commands. The new Tcl commands are automatically registered to the Help
infrastructure.
Figure 14 shows the steps. Xilinx recommends that you refresh the catalog (Refresh button)
before installing an app to make sure that you install the latest version of the app (Step 1).
Click Install to install the app (Step 2).
After the app is installed, the proc names become hyperlinks and the Install button is
greyed-out. In Figure 15 the designutils app has been installed.
X-Ref Target - Figure 15
The same Help text can be printed from the Tcl console with:
Note: The full name qualifier for this proc is xilinx::designutils::write_template and not
just write_template.
For example, after the designutils app has been installed, the user proc, write_template,
can be accessed with:
vivado% ::xilinx::designutils::write_template
vivado% ::tclapp::xilinx::designutils::write_template
The benefit of calling the proc from the ::xilinx namespace over the
::tclapp::xilinx namespace is that the wrapper that is created by Vivado supports a
number of default command line arguments such as -help, -verbose, and -quiet, which
are common to all built-in Vivado commands.
For example:
Vivado% xilinx::designutils::write_template -help
xilinx::designutils::write_template
Description:
(User-written application)
Generates a Verilog/VHDL stub or instantiation template for the current design in
memory (current_instance)
Syntax:
xilinx::designutils::write_template [-type <arg>] [-stub] [-template]
[-language <arg>] [-verilog] [-vhdl]
[-cell <arg>] [-file <arg>] [-append]
[-return_string] [-usage] [-quiet]
[-verbose]
Returns:
template in the case of -return_string, otherwise 0 TCL_ERROR if error
Usage:
Name Description
-----------------------------
[-type] Type of template to create: stub or template
Default: stub
[-stub] Generate a stub (same as -type stub)
[-template] Generate a template (same as -type template)
[-language] Output language of the template: verilog or vhdl
Default: verilog
[-verilog] Verilog language (same as -language verilog)
[-vhdl] VHDL language (same as -language vhdl)
[-cell] Cell to generate template on. If not specified, runs on
current_instance
Default: current_instance
[-file] Output file name
Default: <module>.v or <module>.vhd
[-append] Append to file
[-return_string] Return template as string
[-usage] Usage information
[-quiet] Ignore command errors
[-verbose] Suspend message limits during command execution
Categories:
Description:
Example:
After an app has been installed, the proc names become hyperlinks. To view the source
code, click the proc name, and select View Source Code.
Note: The Tcl Store does not track the procs dependencies. Only the content of the selected proc is
displayed in the source window, not dependent procs. The full app code can be browsed from
GitHub by following the app's URL.
X-Ref Target - Figure 18
Refresh the catalog by selecting the Refresh button at bottom left of the Xilinx Tcl Store
window (Step 1). This action queries the online git repository for the latest information of all
the apps and opens a dialog (Step 2). If an app is then installed, the Tcl Store mechanism
automatically downloads any newer content from the online repository.
X-Ref Target - Figure 21
Updating an App
After the catalog has been refreshed, the GUI notifies the user of any available updates for
the apps from the online repository. In the previous steps, the projutils app version 3.228 is
installed. After refreshing the catalog, a What's New hyperlink appears to notify you that a
newer version is available. If you select the What's New hyperlink, a notification dialog
opens to confirm the newest version available for the app, which is 3.230 in Figure 22.
X-Ref Target - Figure 22
This is a notification that the app is not updated yet. The version of the projutils app
remains 3.228 until you click the Update button.
To update the app to the newest version, click the Update button (Step 1) and a dialog
window opens to confirm the update (Step 2) as shown in Figure 23.
X-Ref Target - Figure 23
After the update is completed, the installed version of projutils is upgraded to the latest
version.
X-Ref Target - Figure 24
Uninstalling an App
To uninstall an app, select the app in the left panel of the GUI. Then in the right panel, at the
bottom of the Details section, click the Uninstall Application hyperlink (Step 1). A dialog
window opens to confirm the uninstall (Step 2).
X-Ref Target - Figure 25
After an app is uninstalled, the procs provided by the app are no longer available inside the
Tcl console.
After the catalog refresh is disabled, the Refresh button is replaced by the message shown
in Figure 26: Internet access is not available.
X-Ref Target - Figure 26
Coding Guidelines
The Xilinx Tcl Store is an open source repository that allows internal and external users to
contribute Tcl scripts for use by the Xilinx community. To prevent redundant efforts and
ensure consistency, a gatekeeping committee reviews requests from contributors. Refer to
the online wiki for further information on this process
(https://github.com/Xilinx/XilinxTclStore/wiki/Xilinx-Tcl-Store-Home).
This section reviews the various coding guidelines that a Tcl script must follow before being
added to the Xilinx Tcl Store. Those guidelines ensure, for instance, that the script is
compliant with the underlying Xilinx Tcl Store mechanism or that there is no name collision
between proc names and variables across all the apps and Tcl scripts. However, this section
does not cover the process you must follow to contribute to the Tcl Store. The online Wiki
covers that aspect.
The Xilinx Tcl Store includes many Tcl scripts that can be used as reference and as example
code. In addition, a template app that can be found under:
<VIVADO_INSTALL>/data/XilinxTclStore/tclapp/mycompany/template/*
This template illustrates the directory structure that a new app must follow along with
sample scripts. This section uses the following script as example code and reference:
<VIVADO_INSTALL>/data/XilinxTclStore/tclapp/mycompany/template/myscript1.tcl
The example code in this section assumes that the app name is template and that the app
is provided and maintained by a company named mycompany.
Terminology:
• A user proc is referred to in this guide as a proc that is expected to be executed by the
user.
• A helper proc is a proc that can be used behind the scenes by a user proc to perform a
task. However, a helper proc is not expected to be directly executed by the user. Helper
procs are not included in the Help system.
Vivado Package
Each app requires a minimum Vivado version to work. The app can check this by requiring
a minimum Vivado package version number inside the Tcl code. The Vivado package name
follows the format 1.<release>. For example: 1.2018.1, 1.2018.2, 1.2018.3, and so
forth.
If the app requires, for instance, Vivado 2018.1 to work, the following code should be added
at the very top of the script:
If the app depends on some functionalities added, for instance, to Vivado 2018.3, then the
following code should be used instead:
The required Vivado package should be the minimum Vivado release that works with the
app. This means that the Tcl scripts should not update the Vivado package that is required
unless this is necessary, for instance, if the app would be enhanced to support
functionalities that are delivered with the new release of Vivado.
App Namespace
Inside the Xilinx Tcl Store, a Tcl script belongs to an app, and an app (for example,
template) is provided by a company (for example, mycompany). An app is an
organizational container that offers some type of functionality. To avoid naming collision,
each app has its own namespace. The full namespace qualifier for an app is:
::tclapp::<company>::<app>
or
::tclapp::mycompany::template
The above code creates the proc my_command1 under the namespace
::tclapp::mycompany::template. Since my_command1 is expected to be executed by
the user, it needs to be exported out of the app namespace. That is done with namespace
export my_command1.
In addition to user procs, a Tcl script can define some helper procs. Helper procs are only
used by the user procs and should not be exposed to the user. As a result, helper procs
should not be exported from the namespace. Exporting a proc from the namespace is the
only way to specify to the system which of the procs should be exposed to the user through
the command line interface (scripting and/or Tcl console).
When a user proc uses helper procs, Xilinx recommends that you create a sub-namespace
under the app and move the user proc and helper procs below it. Doing this ensures that
there will be no name collision between all the helper procs within the app. It is especially
important as the app grows in size and more scripts are added along with their own helper
procs.
The code below illustrates the recommended structure for the Tcl code. The user proc still
exists directly under the app's namespace, but it is just a wrapper used to call the original
proc that has been moved under the sub-namespace,
::tclapp::mycompany::template::my_command1.
• The install proc is automatically called when the app is installed. This is the first
proc called by the Tcl Store during the install process. After the app has been installed,
the install proc is no longer called. During the subsequent start of Vivado tools, the
install proc is not called because the app is only loaded.
• The uninstall proc is automatically called when the app is uninstalled. This is the last
proc called by the Tcl Store during the uninstall process.
For example:
::tclapp::mycompany::template::install
::tclapp::mycompany::template::uninstall
The install and uninstall procs can be used to handle, for example, a custom GUI
button. The button can be installed by the install proc and removed by the uninstall
proc. Multiple custom GUI buttons can be associated with an app. After a button is installed,
it is available through all subsequent calls of the same Vivado tools version, until the app is
uninstalled. The install and uninstall procs are optional. If the app does not use the
install and uninstall procs, these procs can either be left undefined or defined with
an empty body.
return -code ok
}
return -code ok
}
Sharing Variables
The golden rule regarding variables is that global variables are forbidden. The Xilinx Tcl
Store linter checks for global variables inside the scripts and generates an error message if
any global variable is defined.
If some variables need to be shared within procs of an app, then they should be declared
inside the namespace. This is done by creating the variables with the keyword variable
inside the namespace. Such variables can be used like global variables, but only within the
namespace.
The code below creates the variable verbose that can be shared within all the procs that
belong to the same namespace. The variable is initialized to 0:
To access the variable inside a proc, the variable should be declared with the keyword
variable inside the proc.
For example:
Note: The variable verbose can also be accessed from any namespace (including the global
namespace) by using the full namespace qualifier. For example:
set ::tclapp::mycompany::template::verbose 1
Meta-Comments
All the procs inside the Tcl scripts must include some mandatory meta-comments. This
applies to user procs (exported out of the namespace) as well as helper procs. The Xilinx Tcl
Store linter generates error messages if the meta-comments are missing. The
meta-comments for all the exported procs must have complete information. The helper
procs however can have empty meta-comments, but the meta-comments must be declared.
The meta-comments provide information to the system such as a short description of what
the procs are doing, some category information as well as the list of the command line
options supported by the procs. The meta-comments must be included between the proc
definition and before the first line of code. All of the meta-comments are mandatory.
• Summary: Summary of what the proc is doing. This can be a multi-line summary. The
summary is displayed inside the GUI as the proc short description.
• Argument Usage: List of command line arguments in the proc. This meta-comment is
used to build the Help system. Another section in this document describes the
supported format.
• Return Value: Use this meta-comment to specify the possible return values for the
proc. This meta-comment is used to build the Help system.
• Categories: List of categories the app belongs to. Use this meta-comment to specify
which categories in the Vivado Help system your app should be listed under. In this
meta-comment, "Categories:" should be followed by a comma-separated list. By
convention, the first category listed should always be xilinxtclstore followed by
the app name.
# Argument Usage:
# [-verbose]: Verbose mode
# [-file <arg>]: Report file name
# [-append]: Append to file
# [-return_string]: Return report as string
# [-usage]: Usage information
# Return Value:
# return report if -return_string is used, otherwise 0. If any error occur TCL_ERROR
is returned
Note: The detailed meta-comments must be included in the user proc being exported out of the
namespace, not the proc my_command1 that was created in the sub-namespace with its helper proc.
Below is an example of meta-comment for a helper proc. All the meta-comments are
defined although they are empty:
To summarize, the rule is that all Tcl procs inside the scripts must include all the
meta-comments. However, on the user procs exported from the namespace need to have
detailed information.
# Argument Usage:
# [-verbose]: Verbose mode
# [-file <arg>]: Report file name
# [-append]: Append to file
# [-return_string]: Return report as string
# [-usage]: Usage information
The above meta-comment Argument Usage generates the following message from the
Help system:
Syntax:
xilinx::designutils::write_template [-verbose] [-file <arg>] [-append]
[-return_string] [-usage] [-quiet]
Usage:
Name Description
-----------------------------
[-verbose] Verbose mode
Default: 0
[-file] Report file name
Default: None
[-append] Append to file
Default: 0
[-return_string] Return report as string
Default: 0
[-usage] Usage information
Default: 0
[-quiet] Ignore command errors
proc ::tclapp::mycompany::template::my_command2 {} {
# Summary : A one line summary of what this proc does
# Argument Usage:
# Return Value:
# TCL_OK is returned with result set to a string
…
}
or,
Because the meta-comment Argument Usage is used to build the Help message, whatever
above form is used for the proc to pass argument, the meta-comment must be updated
accordingly. For example:
# Argument Usage:
# arg1 : A one line summary of this argument
# [optional1=,] : A one line summary of this argument
# Return Value:
# TCL_OK is returned with result set to a string
or,
# Argument Usage:
# arg1 : A one line summary of this argument
# [optional1=,] : A one line summary of this argument
# Return Value:
# TCL_OK is returned with result set to a string
Note: Using args should always be preferred whenever possible over using position-based
arguments. The args method provides the best user experience as the list and order of the
command line arguments has no restriction. If the proc supports only one or two command
arguments then the position-based can be still used, but is not as user-friendly since the arguments
are ordered and the user does not know in which order the arguments should be passed to the proc
(information not provided by the Help system).
You can also specify positional arguments. A positional argument is one for which just a
value is specified and that has no corresponding flag (for example, -arg1).
# Argument Usage:
# timingPath : mandatory name
# [-append]: optional flag
# -cell <arg>: mandatory argument with no default value
# [-template <arg> = stub]: optional argument with a default value. The default
value is: stub
Syntax:
mycompany::template::mycommand [-append] -cell <arg> [-template <arg>]
[-quiet] [-verbose] <timingPath> <-name>
Returns:
template in the case of -return_string, otherwise 0 TCL_ERROR if error
Usage:
Name Description
-------------------------
[-append] optional flag
Default: 0
-cell mandatory argument with no default value
[-template] optional argument with a default value. The default value is:
stub
Default: stub
[-quiet] Ignore command errors
[-verbose] Suspend message limits during command execution
<timingPath> mandatory
The actual processing of the command line arguments has to be programmatically done
inside the proc.
Note: The -append argument is optional and has a default value of 0. After the -append argument
is specified on the command line, the system returns 1.
Example Script
The complete script used as example in this section can be found under:
<XilinxTclStore>/tclapp/mycompany/template/myscript1.tcl
# Argument Usage:
# [-verbose]: Verbose mode
# [-file <arg>]: Report file name
# [-append]: Append to file
# [-return_string]: Return report as string
# [-usage]: Usage information
# Return Value:
# return report if -return_string is used, otherwise 0. If any error occur TCL_ERROR
is returned
if {$help} {
puts [format {
Usage: my_command1
[-cell <arg>] - Cell to generate template on. If not specified,
runs on current_instance
[-file <arg>] - Output file name
Default: <module>.v or <module>.vhd
[-append] - Append to file
[-return_string] - Return template as string
[-usage|-u] - This help message
Example:
tclapp::mycompany::template::my_command1
tclapp::mycompany::template::my_command1 -cell ila_v2_1_0 -return_string
} ]
# HELP -->
return {}
}
if {$error} {
error " -E- some error(s) happened. Cannot continue"
}
You can run the Xilinx Tcl Store linter on your Tcl script using the Vivado command linter.
The arguments are a list of Tcl script(s). For example:
Every error generated by the linter should be fixed. To be submitted, all the Tcl scripts of the
app must pass the linter.
https://github.com/Xilinx/XilinxTclStore/wiki/Xilinx-Tcl-Store-Home
The Wiki includes detailed information about the various steps and workflow.
This is because the first code sample creates an intermediate Tcl variable, nets.
However, it might sometimes be preferable to create intermediate Tcl variables if the results
of these variables can be reused in other parts of the code.
Caching Objects
Objects or lists of objects should be cached in Tcl variables so they can be reused later.
For example, if the same list of nets is going to be reused multiple times in the script, it does
not make sense to do the same query over and over. Although the Tcl commands in the
Vivado tools have been implemented efficiently, every Tcl query goes back and forth
between the Tcl interpreter and the lower level C++ code of the application. This C++/Tcl
interface consumes runtime that should be avoided when possible.
Use the different filtering capabilities of the Vivado tools as often as possible. Tools such as
effective search pattern definition, -of_objects option, the -filter option, and the
filter command can reduce run-time. Those features have been implemented at a very
low level in the application, and are very efficient in terms of runtime and memory.
By caching the results of a general query, a list of objects can be post-processed using the
filter command to create a sub-list of objects. You can also use standard Tcl list
commands to parse the results assigned to the Tcl variable without accessing the
in-memory design unless necessary.
For example in the following regexp command, both IF statements are equivalent, since in
both cases the Tcl interpreter is passed the name of the object:
In this example, the first expression is not only easier to read than the second expression,
it will also run much faster than the second, since it does not have to access and return the
properties on the object. The get_property command in the second statement will cause
the Vivado tools to iterate between the Tcl interpreter and the underlying C++ application
code to access and return the object properties. If this is done in a looping construct, for
multiple objects, it can significantly increase the run time for your Tcl script.
Inefficient Code:
In the code above, the command get_property LOC $cell is executed for each cell
inside the collection $cells.
Efficient Code:
In the code above, the command get_property LOC $cells is executed only once
which improves the runtime significantly when a long list of objects is processed. This is
possible because the list returned by get_property has the same number of elements as
the Tcl list $cells and the returned elements are in the same order as the input list.
get_cells
A B clk_IBUF_inst rst_IBUF_inst din0_IBUF_inst din1_IBUF_inst dout0_OBUF_inst
dout1_OBUF_inst dout2_OBUF_inst dout3_OBUF_inst clk_IBUF_BUFG_inst
This un-formatted return makes it difficult to see what has been returned in the Tcl Console
and the Vivado IDE. To have each item in the list returned on a separate line, simply execute
the command nested in a join command, with the newline character, ‘\n’, as follows:
join [get_cells] \n
A
B
clk_IBUF_inst
rst_IBUF_inst
din0_IBUF_inst
din1_IBUF_inst
dout0_OBUF_inst
dout1_OBUF_inst
dout2_OBUF_inst
dout3_OBUF_inst
clk_IBUF_BUFG_inst
The list returned by the get_* command is unaffected by the join command.
Note: When converting a Vivado collection of objects into a string representation, not all the
objects have to be included in the string representation. The number of objects to be included in the
string representation is defined with the parameter tcl.collectionResultDisplayLimit
(default: 500). Refer to section Collection versus String Representation for more information.
To find the Vivado tools commands that support the -return_string option use:
findCmd return_string
Inefficient Code:
Efficient Code:
An even more compact and efficient way to code this is to apply the filter as part of the
get_cells command. This removes the need to perform a foreach loop with
individualized checking at the expense of a slightly more complicated filter.
In Vivado IDE, the Tcl code can be executed in different environments that are most of the
time incompatible with the stdin channel. Unless you know that the script will only be
executed in Vivado Tcl mode on a local shell, stdin cannot be used to get user's input.
User's input is typically used to alter the behavior of a script or set values for parameters. In
this regard, getting some information through stdin is unreliable and prone to errors
(typos, wrong value, etc.).
Xilinx recommends that you provide custom values to a script through a configuration file
that can be easily read by the Tcl script. A configuration file can be as simple as a list of Tcl
variables in a file that can be imported in a script using the command:
source <configuration_file>
Such a configuration file can be used whether Vivado IDE is run in batch mode or using a
remote machine (LSF, etc.).
Xilinx Resources
For support resources such as Answers, Documentation, Downloads, and Forums, see Xilinx
Support.
Solution Centers
See the Xilinx Solution Centers for support on devices, software tools, and intellectual
property at all stages of the design cycle. Topics include design assistance, advisories, and
troubleshooting tips.
• From the Vivado IDE, select Help > Documentation and Tutorials.
• On Windows, select Start > All Programs > Xilinx Design Tools > DocNav.
• At the Linux command prompt, enter docnav.
Xilinx Design Hubs provide links to documentation organized by design tasks and other
topics, which you can use to learn key concepts and address frequently asked questions. To
access the Design Hubs:
• In the Xilinx Documentation Navigator, click the Design Hubs View tab.
• On the Xilinx website, see the Design Hubs page.
Note: For more information on Documentation Navigator, see the Documentation Navigator page
on the Xilinx website.
References
1. Vivado Design Suite Tcl Command Reference Guide (UG835)
2. Vivado Design Suite User Guide: Getting Started (UG910)
3. Vivado Design Suite User Guide: Using Constraints (UG903)
4. ISE to Vivado Design Suite Migration Guide (UG911)
5. Vivado Design Suite User Guide: Design Flows Overview (UG892)
6. Vivado Design Suite User Guide: Using the Vivado IDE (UG893)
7. Vivado Design Suite User Guide: System-Level Design Entry (UG895)
8. Tcl Developer Xchange
9. Vivado Design Suite Documentation
Training Resources
Xilinx provides a variety of training courses and QuickTake videos to help you learn more
about the concepts presented in this document. Use these links to explore related training
resources: