#
#*******************************************************************************************************************************************
#
# vitisHelper procs
#
# See Doxygen produced documentation
#
#
#<copyright-disclaimer-start>
#  ************************************************************************************************************
#  * © Copyright 2019-2022 Xilinx, Inc. All rights reserved.                                                  *
#  * This file contains confidential and proprietary information of Xilinx, Inc. and                          *
#  * is protected under U.S. and international copyright and other intellectual property laws.                *
#  * DISCLAIMER                                                                                               *
#  * This disclaimer is not a license and does not grant any rights to the materials distributed              *
#  * herewith. Except as otherwise provided in a valid license issued to you by Xilinx, and to the            *
#  * maximum extent permitted by applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS"               *
#  * AND WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,                 *
#  * IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT,     *
#  * OR FITNESS FOR ANY PARTICULAR PURPOSE; and (2) Xilinx shall not be liable (whether in contract or tort,  *
#  * including negligence, or under any other theory of liability) for any loss or damage of any kind or      *
#  * nature related to, arising under or in connection with these materials, including for any direct, or     *
#  * any indirect, special, incidental, or consequential loss or damage (including loss of data, profits,     *
#  * goodwill, or any type of loss or damage suffered as a result of any action brought by a third party)     *
#  * even if such damage or loss was reasonably foreseeable or Xilinx had been advised of the possibility     *
#  * of the same.                                                                                             *
#  * CRITICAL APPLICATIONS                                                                                    *
#  * Xilinx products are not designed or intended to be fail-safe, or for use in any application requiring    *
#  * fail-safe performance, such as life-support or safety devices or systems, Class III medical devices,     *
#  * nuclear facilities, applications related to the deployment of airbags, or any other applications that    *
#  * could lead to death, personal injury, or severe property or environmental damage (individually and       *
#  * collectively, "Critical Applications"). Customer assumes the sole risk and liability of any use of       *
#  * Xilinx products in Critical Applications, subject only to applicable laws and regulations governing      *
#  * limitations on product liability.                                                                        *
#  * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES.                 *
#  *                                                                                                          *
#  ************************************************************************************************************
#<copyright-disclaimer-end>
#
# history
#    2022/01/20 - WK - 2021.2 - updated for Doxygen compatibility
#    2021.1     - RS - 2021.1 - updated the domBuild proc according to new format of lab builder scripts
#    2020.2     - WK - 2020.2 - added loadedProcs list, fixed some comments
#    2019.2     - WK - initial (early 2020)
#
#*******************************************************************************************************************************************
#

# if the badEnv variable has not been created by the script that called helper.tcl, create it and issue a warning
if {![info exists badEnv]} {
   set badEnv 0;
   puts "@@@ vitis_helper.tcl - WARNING! badEnv variable wasn't set by the calling script to helper.tcl - now set in helper.tcl";
   #set trace [strace]
   #set thisLevel [info level]
   # since trace is still sitting on the stack we have to go up two instead of one
   #set upTwoLevels [expr $thisLevel - 2]
   #set thisLevelName [lindex $trace $upTwoLevels]
   #puts "@@@ vitis_helper.tcl - This likely means that an absolute path was used in the calling script ($thisLevelName) which is a bad practice!";
}

# verify that the trainingPath (cleaned up version of the environment variable TRAINING_PATH) has been set
if {![info exists trainingPath]} {
   puts "@@@ vitis_helper.tcl - trainingPath variable not found. this needs to be defined before loading vitisHelper.";
   set badEnv 1;
}

# the vitisHelper script needs the helper.tcl script
# load the helper file if it hasn't yet been loaded
if {[info exists helper_loaded] != 1} {
   source $trainingPath/CustEdIP/helper.tcl;
   if {[info exists helper_loaded] != 1} {
      puts "@@@ vitis_helper.tcl - Helper.tcl failed to load!";
      set badEnv 1;
   }
} else {
   puts "@@@ vitis_helper.tcl - helper.tcl successfully loaded";
}

#
# if everything is OK, then continue, otherwise throw an error here and quit
if {$badEnv} {
   #puts -nonewline "Hit Enter to exit ==> "
   #flush stdout
   #gets stdin
   puts stderr "Environment not properly configured! Exiting in...";
   for {set i 10} {$i > 0} {incr i -1} {
      puts stderr $i;
      after 1000;
   }
   exit 1
}

# is verbose mode defined?
if {![info exists verbose]} {
   variable verbose 0;        # just define the verbose variable and keep it disabled
}


puts "@@@ vitis_helper.tcl - vitis_helper.tcl ver 2021-08-18";

#
# default platform and domain builder

#
# platform builder
proc platBuild {} {
   variable wsName;
   variable platName;
   variable hwSpec;
   variable hwName;
   variable processorName;
   variable bitWidth;
   variable opSys;
   variable verbose;
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper: platBuild"; }

   # check if the workspace is defined...
   set workspaceName [getws];
   if {[string length $workspaceName] == 0} { setws $wsName; set workspaceName [getws]; }
   puts "@@@ vitis_helper.tcl - workspace set to: $workspaceName";

   # does this platform project already exist?
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper.platBuild: looking to see if $platName already exists of if it needs to be created..."};
   set existingProjects [getprojects];
   set allProjects [lsearch -all -inline -not $existingProjects RemoteSystemsTempFiles];         # the RemoteSystemsTempFiles project must remain
   if {[lsearch $allProjects $platName] == -1} {
      if {$verbose} { puts "@@@ vitis_helper.tcl - building the platform project: based on $hwSpec"; }

      # build the platform based on which variables are defined or not
      set    platArgs "platform create";
      append platArgs " " -name " " $platName;
      if {[info exists processorName]} { append platArgs " " -proc " " $processorName; }
      set procType [string range $processorName 0 12];
      if {[strsame $procType psu_cortexa53]} {
         if {[info exists bitWidth]} {
            append platArgs -arch $bitWidth;
         }
      } else {
	     if {[strsame $procType versal_cips_0]} {
			 if {[info exists bitWidth]} {
				append platArgs -arch $bitWidth;
			 }
		 }
	  }
      if {[info exists opSys]} { append platArgs " " -os " " $opSys; }
      if {[info exists hwSpec]} {
         append platArgs " " -hw " " $hwSpec;
      } else {
         puts "@@@ vitis_helper.tcl - hwSpec must be present!";
         return;
      }
      if {$verbose} { puts "@@@ vitis_helper.tcl - will run: $platArgs"; }

      # build a Platform Project based on the defined variables
      #platform create $platArgs;
      eval $platArgs;

      if {$verbose} { puts "@@@ vitis_helper.tcl - platform project done!" }
   } else {
      if {$verbose} { puts "@@@ vitis_helper.tcl - platform project ($hwName) already built!"; }
   }
   if {$verbose} { puts "@@@ vitis_helper.tcl - exiting vitis_helper.platBuild"; }
}
lappend loadedProcs {platBuild "builds a platform based on the global variables"};
##
# domain builder for standalone domains
#
# libList is a list of libraries, parameters, and values in the following format:
#   { { libName parameterInThisLibrary valueForThisParameter }
#     { libName parameterInThisLibrary valueForThisParameter }
#        ...
#
#    }
#
# if the library needs to be added, but none of the parameters need modifying, use "NULL" as the values for the parameter and value
#
proc domBuild { libList } {
   variable platName;
   variable domName;
   variable processorName;
   variable opSys;
   if {![info exists opSys]} { set opSys standalone; }
   variable verbose;
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper: domBuild"; }

   # next build the Domain for this hardware
   if {$verbose} { puts "@@@ vitis_helper.tcl - Investigating whether Domain should be built..."; }

   # if the domain to build can't be found in the existing domains list, then ...
   set existingDomains [domain list];
   set selectedDomName "*";
   append selectedDomName $domName;
   if {([lsearch $existingDomains $domName] == -1) &&
       ([lsearch $existingDomains $selectedDomName] == -1)} {
      if {$verbose} { puts "@@@ vitis_helper.tcl - building the Domain ($domName)"; }
      domain create -name $domName -proc $processorName -os $opSys; # is support-app needed? -support-app {Empty Application}
   } else {
      if {$verbose} { puts "@@@ vitis_helper.tcl - Domain ($domName) already exists!"; }
   }

   # make sure the domain that we want to use is active - it may not be active even if it was just built
   set activeDomain [domain active];
   if {$verbose} {
      puts "@@@ vitis_helper.tcl - Active domain currently: $activeDomain";
   }
   #if {$verbose} { puts "@@@ vitis_helper.tcl - setting active domain to $domName"; }
   domain active $domName;

   # now that the domain exists, add in the libraries options
   # iterate through the list of libraries and parameters that need to added to the domain
   if {$verbose} {puts "@@@ vitis_helper.tcl - Starting to add libraries to $activeDomain"; }
   addLib $libList;
   # foreach libParamDescr $libList {
      # if ($verbose) { puts "@@@ vitis_helper.tcl - working on: $libParamDescr"; }
      # set libName   [lindex $libParamDescr 0];
      # set paramName [lindex $libParamDescr 1];
      # set valueName [lindex $libParamDescr 2];
       # bsp setlib -name $libName;         #Add the library without any parameters, this makes the libName the active library.
      # if {[string match $paramName NULL] == 0} {
         # if ($verbose) { puts "@@@ vitis_helper.tcl - setting parameters for $libName: $paramName = $valueName"; }
         # #bsp setlib -name $libName;
         # bsp config $paramName $valueName;    #Add this paramName and valueName to the active library
      # } else {
         # if ($verbose) { puts "@@@ vitis_helper.tcl - just adding $libName without parameters"; }
      # }
   # }
   if {$verbose} { puts "@@@ vitis_helper.tcl - exiting vitis_helper.domBuild"; }
}
lappend loadedProcs {domBuild "builds a domain based on the global variables and the passed list of libraries"};
##
# addLibs libList
#
# libList is a list of libraries, parameters, and values in the following format:
#   { { libName parameterInThisLibrary valueForThisParameter }
#     { libName parameterInThisLibrary valueForThisParameter }
#        ...
#
#    }
#
# adds the libraries to the active domain
#
# if the library needs to be added, but none of the parameters need modifying, use "NULL" as the values for the parameter and value
#
proc addLibs { libList } {
   variable platName;
   variable domName;
   variable processorName;
   variable opSys;
   if {![info exists opSys]} { set opSys standalone; }
   variable verbose;
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper: addLibs"; }


   # now that the domain exists, add in the libraries options
   # iterate through the list of libraries and parameters that need to added to the domain

   if {$verbose} {puts "@@@ vitis_helper.tcl - Starting to add libraries"; }
   foreach libParamDescr $libList {
      if ($verbose) { puts "@@@ vitis_helper.tcl - working on: $libParamDescr"; }
      set libName   [lindex $libParamDescr 0];
      bsp setlib -name $libName;

      set paramName [lindex $libParamDescr 1];
      set valueName [lindex $libParamDescr 2];
      if {[string match $paramName NULL] == 0} {
         if ($verbose) { puts "@@@ vitis_helper.tcl - setting parameters for $libName: $paramName = $valueName"; }
         bsp config $paramName $valueName;
      } else {
         if ($verbose) { puts "@@@ vitis_helper.tcl - just adding $libName without parameters"; }
      }
   }
   if {$verbose} { puts "@@@ vitis_helper.tcl - exiting vitis_helper.addLibs"; }
}
lappend loadedProcs {addLibs "adds and configures libraries based on the passed argument"};
##
# application build
#    creates an application project if it does not already exist. If the application template specified is an empty application
#    and there are files available in the argument srcFiles, then these source files are copied to the application project's source sub-directory
#
# todo: detect if there is a hierarchy provided and use and use that hierarchy instead of the support hierarchy
#
# @param  srcFiles - list of files from the support directory to be copied into the project.
# @return none
#
proc appBuild { srcFiles } {
   variable trainingPath;
   variable tcName;
   variable platName;
   variable domName;
   variable appName;
   variable sysName;
   variable appTemplate;
   variable verbose;
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper: appbuild"; }

   # if the project to build can't be found in the existing projects list, then ...
   set appProjects   [getproject -type app];
   if {[lsearch $appProjects $appName] == -1} {
      if {$verbose} { puts "@@@ vitis_helper.tcl - building the standalone application ($appName using domain: $domName)"; }
      #app create -name $appName  -proc $processorName -os standalone -domain $domName -lang C -template $appTemplate -platform $platName -sysproj $sysName
      app create -name $appName  -domain $domName -lang C -template $appTemplate -sysproj $sysName -platform $platName;

      if {$verbose} { puts "@@@ vitis_helper.tcl - Application project created!"; }
   } else {
      if {$verbose} { puts "@@@ vitis_helper.tcl - Application ($appName) already built!"; }
   }

   # if the application template was an empty one, then add any files in the srcFiles list
   if {[string match -nocase "{Empty Application(C)}" $appTemplate] == 0} {
      puts "@@@ vitis_helper.tcl - looks like an empty application...";
      if {[llength srcFiles] > 0} {
         if {$verbose} { puts "@@@ vitis_helper.tcl - and we have some files we can add..."; }
         set srcPath $trainingPath/$tcName/support;
         set dstPath $trainingPath/$tcName/lab/$appName/src;
         foreach thisFile $srcFiles {
            if {$verbose} { puts "@@@ vitis_helper.tcl - Copying $srcPath/$thisFile ==> $dstPath/$thisFile"; }
            file copy -force $srcPath/$thisFile $dstPath/$thisFile;
         }
         if {$verbose} { puts "@@@ vitis_helper.tcl - files added to the application project created!"; }
      } else {
         if {$verbose} { puts "@@@ vitis_helper.tcl - no files to add to the empty application"; }
      }
   }
   if {$verbose} { puts "@@@ vitis_helper.tcl - exiting vitis_helper.appBuild"; }
}
lappend loadedProcs {appBuild "builds an application based on the global variables and a list of sources"};
##
# add sources to an existing application
# typically performed after an application is built and is functionally identical to importing sources
# as this simply copies source files (with the full path provided) into the application's src directory
#
# @param appName - name of the application
# @param srcFiles - list of files to forcibly copy into the src directory of the application
#
proc sourcesAdd { appName srcFiles } {
   variable trainingPath;
   variable tcName;
   variable verbose;
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper: sourcesAdd"; }

   # if the project to build can't be found in the existing projects list, then ...
   set appProjects   [getproject -type app];
   if {[lsearch $appProjects $appName] == -1} {
      if {$verbose} { puts "@@@ vitis_helper.tcl - building the standalone application ($appName using domain: $domName)"; }
      #app create -name $appName  -proc $processorName -os standalone -domain $domName -lang C -template $appTemplate -platform $platName -sysproj $sysName
      app create -name $appName  -domain $domName -lang C -template $appTemplate -sysproj $sysName -platform $platName;

      if {$verbose} { puts "@@@ vitis_helper.tcl - Application project created!"; }
   } else {
      if {$verbose} { puts "@@@ vitis_helper.tcl - Application ($appName) already built!"; }
   }

   # if the application template was an empty one, then add any files in the srcFiles list
   if {[string match -nocase "{Empty Application(C)}" $appTemplate] == 0} {
      puts "@@@ vitis_helper.tcl - looks like an empty application...";
      if {[llength srcFiles] > 0} {
         if {$verbose} { puts "@@@ vitis_helper.tcl - and we have some files we can add..."; }
         set srcPath $trainingPath/$tcName/support;
         set dstPath $trainingPath/$tcName/lab/$appName/src;
         foreach thisFile $srcFiles {
            if {$verbose} { puts "@@@ vitis_helper.tcl - Copying $srcPath/$thisFile ==> $dstPath/$thisFile"; }
            file copy -force $srcPath/$thisFile $dstPath/$thisFile;
         }
         if {$verbose} { puts "@@@ vitis_helper.tcl - files added to the application project created!"; }
      } else {
         if {$verbose} { puts "@@@ vitis_helper.tcl - no files to add to the empty application"; }
      }
   }
   if {$verbose} { puts "@@@ vitis_helper.tcl - exiting vitis_helper.appBuild"; }
}
##
# compilerSymbolsAdd
#    adds the provided list of symbols to the compiler settings
#    usage:
#       set symbolList { {symbol1 value1} {symbol2 value2} ... {symbolN valueN}}
#       if the symbol is only a define and does not have a specific value, set "value" to ""
#
# @param  symbolList - list of symbols and values as desribed above
# @return none
# @history 
#    2022/02/09 - WK - fixed symbols with values - further testing is warrented
#
proc compilerSymbolsAdd {symbolList} {
   variable appName;
   variable verbose;
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper: compilerSymbolsAdd ... $symbolList"; }

   # verify that the application is valid and active
   set appProjects   [getproject -type app];
   if { [lsearch $appProjects $appName] > -1 } {
      if {$verbose} { puts "@@@ vitis_helper.tcl - $appName found in the projects list"; }
      # iterate through the list and add each symbol to the compiler symbol list
      foreach symbol $symbolList {
		 if {[lindex $symbol 1] == ""} {
		    # there is just a symbol name without a value
			set thisSymbol [lindex $symbol 0]
		 } else {
			# there is a symbol name and value
			set thisSymbol [lindex $symbol 0];
			append thisSymbol =;
			append thisSymbol [lindex $symbol 1]
		 }
         if {$verbose} { puts "@@@ vitis_helper.tcl - Adding $thisSymbol to the the symbol list for application: $appName"; }
         app config -name $appName define-compiler-symbols $thisSymbol
      }
   } else {
      puts "@@@ vitis_helper.tcl - could not find an application project named: $appName";
   }

   if {$verbose} { puts "@@@ vitis_helper.tcl - exiting vitis_helper.compilerSymbolsAdd"; }
}
lappend loadedProcs {compilerSymbolsAdd "adds the list of symbols and their values to the symbols list"};
##
# compilerSymbolsRemove
#    removes the provided list of symbols from the compiler settings
#    usage:
#       set symbolList { {symbol1 value1} {symbol2 value2} ... {symbolN valueN}}
#       if the symbol is only a define and does not have a specific value, set "value" to NULL
#
# @param  srcFiles - list of symbols and values as desribed above
# @return none
#
proc compilerSymbolsRemove {symbolList} {
   variable appName;
   variable verbose;
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper: compilerSymbolsRemove"; }

   # iterate through the list and add each symbol to the compiler symbol list
   foreach symbol $symbolList {
      if {$verbose} { puts "@@@ vitis_helper.tcl - Removing $symbol to the the symbol list for application: $appName"; }
      app config -name appName -remove define-compiler-symbols $symbol;
   }

   if {$verbose} { puts "@@@ vitis_helper.tcl - exiting vitis_helper.compilerSymbolsRemove"; }
}
lappend loadedProcs {compilerSymbolsRemove "removes the passed list of symbols from the compiler settings"};
##
# compilerMiscFlagsSet
#    sets the misc. compiler flags to the passed string. This completely REPLACES the existing compiler flags - it does not append or filter

# @param  compilerOptions - string representing the compiler flags
# @return none
#
proc compilerMiscFlagsSet {compilerOptions} {
   variable appName;
   variable verbose;
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper: compilerMiscFlagsSet ... $compilerOptions"; }

   # strip the double quotes around the compiler option if present
   if {[string first $compilerOptions "\""] == 0} {
      set compilerOptions [string range $compilerOptions 1 [expr [string length $compilerOptions] - 1]];
   }
   if {$verbose} { puts "@@@ vitis_helper.tcl - compiler options: $compilerOptions"; }

   # verify that the application is valid and active
   set appProjects   [getproject -type app];
   if { [lsearch $appProjects $appName] > -1 } {
      app config -name $appName -set compiler-misc {$compilerOptions};
   } else {
      puts "@@@ vitis_helper.tcl - could not find an application named $appName!";
   }

   if {$verbose} { puts "@@@ vitis_helper.tcl - exiting vitis_helper.compilerMiscFlagsSet"; }
}

##
# buildAll
#    builds all projects in the workspace
#
# @return none
#
proc buildAll {} {
   variable appName;
   variable verbose;
   if {$verbose} { puts "@@@ vitis_helper.tcl - vitisHelper: buildAll"; }

   platform generate;
   app build $appName;
   puts "@@@ vitis_helper.tcl - todo: write buildAll";

   if {$verbose} { puts "@@@ vitis_helper.tcl - exiting vitis_helper.buildAll"; }
}
lappend loadedProcs {buildAll "builds all projects"};
##
# projRemove
#    removes the one specific project pass as the parameter or
#    removes all projects in the workspace if "all" is passed as the parameter
#    removal is from both the workspace and the drive
#
# @param name of project to remove. if "all" is given, then all projects are removed.
# @return number of projects removed
proc projRemove {projName} {
   set existingProjects [getprojects];
   set allProjects [lsearch -all -inline -not $existingProjects RemoteSystemsTempFiles];         # the RemoteSystemsTempFiles project must remain
   set appProjects   [getproject -type app];
   set sysProjects   [getproject -type system];
   set platProjects  [getproject -type platform];
   set doAll         [string compare -nocase "all" $projName];

   # determine what to remove
   if {$doAll != 0} {                                                         # delete the specific project
       if {[lsearch $allProjects $projName] == -1} {                          # is the specified name in the master list?
          return 0;                                                           # return if the project name is not found
       }

       # figure out what kind of project it is...
       if {[lsearch $appProjects $projName] != -1} {                          # if the project name is of type application
          set response [app remove $projName];                                # remove this application
       } elseif {[lsearch $sysProjects $projName] != -1} {                    # if the project name is of type system
          set response [sysproj remove $projName];                            # remove the system
       } elseif {[lsearch $platProjects $projName] != -1} {                   # if the project name is of type platform
          set response [platform -remove $projName];                           # remove this platform
       } else {
          # unknown project type
          puts "@@@ vitis_helper.tcl - Unknwon project type!";
          return 0;
       }

       puts "@@@ vitis_helper.tcl - Response: $response";
       if {[string length $response] == 0} {                                  # no error messages were returned, assume success
          return 1;                                                           # if there was no response, assume that the removal was successful
       } else {
          return 0;
       }
       #set nProjRemoved [deleteprojects -name $projName];                     # get the number of projects removed
   } else {                                                                   # delete all projects by type
      puts "@@@ vitis_helper.tcl - Attempting to remove all projects";
      set nProjRemoved 0;

      # remove the application projects
      foreach projName $appProjects {
         puts "@@@ vitis_helper.tcl - Remove application project: $projName";
         set status [app remove -name $projName];
         if {[string length $status] == 0} {
            set nProjRemoved [expr $status + $nProjRemoved];
         }
      }

      # remove the application projects
      foreach projName $sysProjects {
         puts "@@@ vitis_helper.tcl - Removing system project: $projName";
         set status [sysproj remove -name $projName];
         if {[string length $status] == 0} {
            set nProjRemoved [expr $status + $nProjRemoved];
         }
      }

      # remove the domains from all projects
      foreach platName $platProjects {
         puts "@@@ vitis_helper.tcl - Removing platform project: $projName";
         platform active $platName; # make the platform active
         #todo: iterate through the domains
         set domains [domain list]; # get the domains in the active project - todo: there should be a "getdomains" command, but I can't find one
         set domains [lrange $domains 4 [llength $domains]]; # strip the 4 line header from the list
         # remove the domains
         foreach thisDomain $domains {
            puts "@@@ vitis_helper.tcl - apptempting to remove $thisDomain";
            if {[catch {domain remove $thisDomain} msg] } {
               puts "@@@ vitis_helper.tcl - domain removal of $thisDomain thre the following error: $msg";
            } else {
               puts "@@@ vitis_helper.tcl - success fromval of $thisDomain";
            }
         }
         # now, with all the domains stripped from the remove the platform
         set status [platform remove -name $projName;]
         if {[string length $status] == 0} {
            set nProjRemoved [expr $status + $nProjRemoved];
         }
      }
   }
   return $nProjRemoved;
}
lappend loadedProcs {projRemove "removes the specified projects including ALL - due to tool issues, platforms cannot be removed through this method"};

variable vitis_helper_loaded 1;



