Defining Tcl Procedures - 2021.2 English

Vivado Design Suite User Guide: Using Tcl Scripting (UG894)

Document ID
UG894
Release Date
2021-11-17
Version
2021.2 English

Because the Vivado Design Suite provides a full Tcl interpreter built into the tool, creating new custom commands and procedures is a simple task. You can write Tcl scripts that can be loaded and run from the Vivado IDE, or you can write procedures, to act like new Tcl commands, taking arguments, checking for errors, and returning results.

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:

proc helloProc { arg1 } {
  # This is a comment inside the body of the procedure
  puts "Hello World! Arg1 is $arg1"
}
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.

The following example defines a procedure, reportWorstViolations, with three arguments:

proc reportWorstViolations { nbrPaths corner delayType } {
  report_timing -max_paths $nbrPaths -corner $corner -delay_type $delayType -nworst 1
}

When running the procedure, all the arguments must be specified as shown:

%> reportWorstViolations 2 Slow max
%> reportWorstViolations 10 Fast min

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.

proc reportWorstViolations { nbrPaths { corner Slow } { delayType Max } } {
  report_timing -max_paths $nbrPaths -corner $corner -delay_type $delayType -nworst 1
}

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.

proc reportWorstViolations { nbrPaths args } {
      eval report_timing -max_paths $nbrPaths $args
}

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]
  # Write the current date and CSV format to a file header
  puts $FH "#\n# File created on [clock format [clock seconds]]\n#\n"
  puts $FH "Startpoint,Endpoint,DelayType,Slack,#Levels,#LUTs"
  # Iterate through both Min and Max delay types
  foreach delayType {max min} {
    # Collect details from the 50 worst timing paths for the current analysis 
    # (max = setup/recovery, min = hold/removal) 
    # The $path variable contains a Timing Path object.
    foreach path [get_timing_paths -delay_type $delayType -max_paths 50 -nworst 1] {
      # Get the LUT cells of the timing paths
      set luts [get_cells -filter {REF_NAME =~ LUT*} -of_object $path]
      # Get the startpoint of the Timing Path object
      set startpoint [get_property STARTPOINT_PIN $path]
      # Get the endpoint of the Timing Path object
      set endpoint [get_property ENDPOINT_PIN $path]
      # Get the slack on the Timing Path object
      set slack [get_property SLACK $path]
      # Get the number of logic levels between startpoint and endpoint
      set levels [get_property LOGIC_LEVELS $path]
      # Save the collected path details to the CSV file
      puts $FH "$startpoint,$endpoint,$delayType,$slack,$levels,[llength $luts]"
    }
  }
  # Close the output file
  close $FH
  puts "CSV file $fileName has been created.\n"
  return 0
}; # End PROC