在vivado中使用tcl脚本(UG894)

这篇具有很好参考价值的文章主要介绍了在vivado中使用tcl脚本(UG894)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文源自UG894,主要介绍如何在vivado中使用tcl脚本

1.vivado中如何获取tcl help

vivado中任何自带的命令都可以通过“-help”获取帮助信息。
也可以直接输入“help”取得vivado命令合集,并通过“help -category (tools)”来获取某类操作的所有命令简介。

2.工程模式下编译和报告示例脚本

该过程可以通过运行GUI vivado自动产生的记录文件vivado.jou查看,该文件中记录了自打开vivado后运行的所有命令。
1.通过create_project命令建立工程。
2.通过add_files或import_files添加工程文件。
3.通过launch_runs和wait_on_run依次进行综合实现。

3.在vivado中加载并运行自己的tcl脚本

3.1 vivado启动时自动初始化脚本

vivado会在启动时自动加载Vivado_init.tcl文件中定义的脚本。可将自己写的proc写入该文件中,或者直接source自己的tcl脚本。
Vivado_inti.tcl路径为%APPDATA%/Xilinx/Vivado//Vivado_init.tcl

3.2 通过source运行tcl脚本

可以通过source将tcl脚本加载进入vivado中

source <filename>

使用source会默认打印脚本代码内容,可通过“-notrace”隐藏代码内容

source <filename> -notrace

3.3 在vivado编译流程中添加脚本

在Setting中,找到综合、实现、生成比特流设置,都可以添加tcl.pre和tcl.post的路径,即可在该流程之前或者之后插入自己的tcl脚本。

4.tcl脚本编写方法

原文档这部分主要简介tcl脚本语法及经典问题,此处只挑出其中的经典问题进行记录

4.1 proc参数数量不定时的解决方法

当proc参数数量不定时,即proc有0-n个参数都可以正常运行时,参数可以以链表形式给出,在proc中,依次对输入参数列表元素进行分析处理,每处理一个就删除一个,直至所有参数处理完毕。

# 将第一个元素从列表中移除
proc lshift listVar {
      upvar 1 $listVar L
      set r [lindex $L 0]
      set L [lreplace $L [set L 0] 0]
      return $r
  }
  
  
  proc myproc { args } {
  
    #-------------------------------------------------------
    # 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
        }
        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]
                [-help|-h]
  
    Description: xxxxxxxxxxxxxxxxxxx.
                 xxxxxxxxxxxxxxxxxxx.
  
    Example:
       %s -port xxxxxxxxxxxxxxx
  
  } $callerflag $callerflag ]
      # HELP -->
      return -code ok {} 
    }
  
    # Check validity of arguments. Increment $error to generate an error
  
    if {$error} {
      return -code error {Oops, something is not correct}
    }
  
    # Do something
  
    return -code ok {}
  }

【注意】原文档中还给出了另一种用switch分析列表的方法,但是没有看懂,这里先不写了

4.2 局部变量和全局变量

局部变量是proc内部变量,该变量只在proc内使用,与外部变量相互独立(当与外部变量名字相同时,他们相互独立互不影响)。
全局变量是在proc外部定义的变量,属于全局命名空间变量。如果要在proc内部调用全局变量,需要在变量名前用global关键词;或者在变量名前加“::”。

proc printEnv {} {
  global env
  foreach var [lsort [array names env]] { puts "  $var = $env($var)" }
}
proc printEnv {} {
  foreach var [lsort [array names ::env]] { puts "  $var = $::env($var)" }
}

【注意】通常不建议用在proc内用global调用全局变量,global通常用于避免向proc传递太大的列表。通常优先考虑用upvar。

4.3 namespace的使用

为了避免变量和函数名重复,可以将函数和变量定义在更独立的空间。命名空间可以嵌套,通过::来调用命名空间中的变量和函数。

01  namespace eval foo {
02    variable stack [list]
03    variable count 0
04    variable params
05    array set params [list var1 value1 var2 value2 var3 value3]
06    
07    namespace export push pop
08    
09    proc push { args } {
10      variable stack
11      variable count
12      lappend stack $args
13      incr count
14    }
15  
16    proc pop {} {
17      variable stack
18      variable count
19      if {[llength $stack] > 0} {
20        set value [lindex $stack end]
21        set stack [lrange $stack 0 end-1]
22        incr count -1
23        return $value
24      } else {
25        error " no more element in the stack"
26      }
27    }
28    
29  }
30  
31  proc foo::dump {} {
32    variable stack
33    variable count
34    if {[llength $stack] > 0} {
35      puts " There are $count element(s) in the stack:"
36      foreach element $stack {
37        puts "    $element"
38      }
39      return 0
40    } else {
41      error " no element in the stack"
42    }
43  }
44  
45  namespace import foo::*

5.访问设计对象

vivado提供了非常丰富的get_*命令用于访问设计对象,这些命令会以列表形式返回所需内容。

5.1 对象特性

每种设计对象(net,pin,port……)都有不同种类的特性参数,可以通过get_* filter来找到某种特性的对象,可以通过report_property来展示某个对象的所有特性。特性也可以增加和删除。

5.2 对象检索

通过get_*、-hierarchical、filter、-regxp、-of_objects等来检索相关对象,此处不在赘述。

6.处理对象列表

通过get_*都以tcl链表形式返回对象,因此可以通过tcl内置的列表命令进行处理。

foreach X [lsort -decreasing [get_cells]] {puts $X}
wbArbEngine
usb_vbus_pad_1_i_IBUF_inst
usb_vbus_pad_0_i_IBUF_inst
usbEngine1
usbEngine0
...

7.保存命令输出

很多vivado命令都支持将输出保存至指定文件中,通过-file选项;或将输出结果以string形式保存,通过-return_string,以便后面的函数调用。

# 新建文件并写入内容
report_timing -delay_type max -file setup_violations.rpt
report_timing -delay_type min -file hold_violations.rpt

# 通过-append在原有文件中新增内容
report_timing -delay_type max -file all_violations.rpt
report_timing -delay_type min -file -append all_violations.rpt

文件的绝对或者相对路径可以当作文件名的一部分。

report_*命令也可以通过-return_string将结果以字符串形式输出,并可以赋给tcl变量。

set timeLines [split [report_timing -return_string -max_paths 10] \n ]

7.1 对文件进行操作

tcl提供了一系列命令对文件进行操作,这些都是tcl基本语法,此处不再赘述。

7.2 对字符串进行操作

tcl提供了一系列命令对字符串进行处理,此处不再赘述。

8.error处理

写脚本时,一个好的习惯:使用某个参数前先检查参数状态,比如打开文件前检查文件是否存在,使用报告列表时先检查是否有元素存在,这样会避免很多脚本运行错误。

8.1 检查变量状态

# 打开文件前检查文件是否存在
if {[file exists $filename]} {
  set FH [open $filename r]
  if {$FH != {}} {
    # The file is opened, do something
    # …
    close $FH
  } else {
    puts " File $filename could not be opened"
  }
} else {
  puts " File $filename does not exist"
}


# 在使用get_*之后,检查对象是否存在
proc get_pin_dir { pinName } {
 if {$pinName == {}} {
   puts " Error - no pin name provided"
   return {}
 }
 set pin [get_pins $pinName]
 if {$pin == {}} {
   puts " Error - pin $pinName does not exist"
   return {}
 }
 set direction [get_property DIRECTION $pin]
 return $direction
}

8.2 处理tcl错误

一些内置tcl命令出错时,如果没有对错误进行处理,可能会中断命令执行。例如当执行file命令时发现文件无法打开。
为了处理命令出错的情况,tcl内置了catch命令,当发现错误时返回1,否则返回0。

# catch语法
catch script [varname]
# script为一个或一个命令集,varname为报错内容存储变量名。示例如下:
If {[catch script errorstring]} {
  # A low-level TCL_ERROR happened
  puts " Error - $errorstring "
} else {
  # No TCL_ERROR was generated
  puts " The code completed successfully "
}
# 当使用file命令时发现文件无法开始时,通过cathc处理
if {[file exists $filename]} {
  if {[catch { set FH [open $filename r] } errorstring]} {
    puts " File $filename could not be opened : $errorstring"
  } else {
    # The file is opened, do something
    # …
    close $FH
  }
} else {
  puts " File $filename does not exist"
}

error命令可用于产生TCL_ERROR。(这里没看懂,error是用于增加报错内容的吗?)

proc get_file_content { filename } {
  if {[catch {
    set FH [open $filename r]
    set content [read $FH]
    close $FH
  } errorstring]} {
    error " File $filename could not be opened : $errorstring "
  }
  return $content
}

9.调用外部程序

使用exec调用外部程序,使用时要确保外部程序可以适配当前操作系统。

set result [exec /bin/perl <path_to>/my_perl_script.pl]

10.自定义设计规则检查(DRC)

DRC定义了一系列设计规则,并检查当前设计是否符合这些规则,打印找到的错误和冲突部分。
可以通过report_drc执行DRC,检查并报告当前设计中的违例部分。
当发现设计违背设计规则时,可以通过create_dec_violation定义且标识违例行为。
可以通过create_dec_check命令创建用户自定义DRC。
可以通过create_dec_ruledeck命令创建drc集合,集合中可以同时有自定义DRC和官方DRC,可以通过add_drc_checks在集合中新增DRC。

10.1 创建tcl检查函数

创建一个proc对设计中感兴趣的对象进行检查,最终以DRC违例报告形式返回一个明确定义的错误。新增的脚本必须在report_drc执行之前导入。

# 示例中dataWidthCheck检查WRITE_B总线宽度是否符合要求。
# 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

10.2 新建DRC检查

建立tcl检查函数之后,还需要在vivado中将其定义为DRC,并加入到系统DRC报告内容中。
首先需要通过create_drc_check声明建立新的检查规则,该命令需要用户自定义一个检查名字(向DRC集合中添加该检查,或在DRC报告中找到该检查,会用到名字),在上面的示例中,DRC名为RAMW-1。除此以外,create_drc_check还需要添加proc名字,作为-rule_body,上述例子中,proc名为dataWidthCheck。
DRC检查规则有is_enable特性,可以通过set_property进行配置,当其为fulse时,执行report_drc时不会检查这一条。

10.3 新建DRC检查集

可以手动将多个DRC检查加入DRC检查集,通过create_drc_ruledesk创建检查集,通过add_drc_checks新增检查,通过remove_drc_checks删除检查。

create_drc_ruledeck myrules
add_drc_checks -ruledeck myrules {RAMW-1 RAMW-2 RAMW-3}
remove_drc_checks {RAMW-2} -ruledeck myrules

DRC检查集也有is_enable属性。

10.4 单独运行自定义DRC

用户自定义的DRC、DRC集合可以单独运行。

report_drc -check {RAMW-1}
report_drc -check {RAMW-1 RAMW-2}
report_drc -ruledecks myrules

10.5 DRC属性设置

DRC就像其他对象一样可以通过get_property查看属性、set_property设置属性。

Vivado% report_property [get_drc_checks RAMW-1]
Property         Type     Read-only  Visible  Value
ARCHITECTURES    string*  true       true
CLASS            string   true       true     drc_check
DESCRIPTION      string   true       true     Block RAM Data Width Check
GROUP            string   true       true     RAMW
HIERNAME         string   true       true     RAMB Checks
IS_ENABLED       bool     false      true     1
IS_USER_DEFINED  bool     true       true     1
MESSAGE          string   true       true
MSG_ID           int      true       true     1
NAME             string   true       true     RAMW-1
SEVERITY         enum     false      true     Advisory

DRC属性只有IS_ENABLE和SEVERITY可以设置。

set_property IS_ENABLED false [get_drc_checks RAMW-1]
set_property SEVERITY {Critical Warning} [get_drc_checks RAMW-1]
# 将设置属性初始化
reset_drc_check [get_drc_checks]

11.自定义GUI按钮

Tools > Custom Commands > Customize Commands.

12.提高tcl运行效率的方法

以下几种方法可以提高tcl脚本的运行效率。

12.1运用嵌套

一条命令在tcl控制台执行时,首先通过tcl编译器对命令进行解析,之后进入C++层继续执行这条命令,执行结束后返回正确的值给tcl编译器,之后执行下一条命令,tcl编译器到C++层会消耗一定时间,因此如果可以将两个命令通过嵌套变为一个命令,则系统只需在tcl编译器和C++层变化一次,节省了一定时间。举例来说:

set nets [get_nets -hier]
set pins [get_pins -of_objects $nets

这样执行时间将会长于

set pins [get_pins -of_objects [get_nets -hier]]

12.2 缓存对象

当有一些运行结果需要多次使用时,最好先将其设置为一个变量,避免每次使用时都要重新检索或计算一遍。

12.3 vivado的object可以直接当作string作为其他命令的参数

当一些命令需要输入字符串时,vivado的设计对象可以直接输入,而无需再调用设计对象的NAME属性。

if {[regexp {.*enable.*} $MyObject]} { ... }
if {[regexp {.*enable.*} [get_property NAME $MyObject]]} { ... }

第一种写法不仅比第二种易读,同时运行时间更短。

12.4 写更高效的代码

提高运行时间的一种方法是高效地编写代码,以便构建一个容器,并在整个容器上运行一个命令,而不是在一个循环中对作为容器一部分的每个项目运行命令。(即将循环中的数据整合成一个列表,之后对列表进行统一操作)。

# 低效写法
foreach bram [get_cells -hier -filter {PRIMITIVE_SUBGROUP == bram}] {
set bwidth [get_property WRITE_WIDTH_B $bram]
if { $bwidth > 36} {
highlight_object -color red [get_cells $bram]
}; # End IF
}; # End FOR

# 高效写法
foreach bram [get_cells -hier -filter {PRIMITIVE_SUBGROUP == bram}] {
set bwidth [get_property WRITE_WIDTH_B $bram]
if { $bwidth > 36} {
lappend bram_list $bram
}; # End IF
}; # End FOR
highlight_object -color red [get_cells $bram_list]

12.5 获取用户输入

在通常的tclsh环境下,通过stdin获取用户输入:

gets stdin answer

而在vivado环境下,tcl脚本会在不同系统环境下运行,stdin很难兼容所有情况。因此除非确定脚本只在某些情况下运行,并且stdin可以全部兼容时,才使用这个命令。
vivado环境下,通常建议将所有输入整合成一个tcl脚本文件,之后通过source来执行输入文件,即可完成参数输入。用户需要更改配置时,只需要更改文件中的数据即可。文章来源地址https://www.toymoban.com/news/detail-402042.html

到了这里,关于在vivado中使用tcl脚本(UG894)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • UG导出点集坐标到txt文本文档中

    将UG中的离散的点或者点集坐标导出到文本文档; 原文地址 俩文件链接如下,失效了可以私信我要; 第一个是个exe,运行后是段操作录屏,可以不用下载,操作详情可见下文;第二个文件是需要选择的.grx格式文件,使用详情见下文 https://pan.baidu.com/share/init?surl=5ctC5YbDJlMKqP6

    2023年04月19日
    浏览(29)
  • tcl学习之路(五)(Vivado时序约束)

      主时钟通常是FPGA器件外部的板机时钟或FPGA的高速收发器输出数据的同步恢复时钟信号等。下面这句语法大家一定不会陌生。该语句用于对主时钟的名称、周期、占空比以及对应物理引脚进行约束。   在设计中,未约束的时钟可以通过时钟网络报告和时钟确认报告查看

    2024年02月12日
    浏览(33)
  • tcl学习之路(二)(vivado设计流程管理)

    对于vivado的实现阶段有以下步骤 1.设计初始化阶段 init_design 2.设计优化 opt_design 默认执行 3.功耗优化 power_opt_design 4.布局 place_design 默认执行 5.布局后功耗优化 power_opt_design(post_place_power_opt_design) 6.布局后物理优化 phys_opt_design 默认执行 7.布线 route_design 默认执行 8.布线后物理

    2024年02月11日
    浏览(35)
  • 在Vivado下利用Tcl实现IP的高效管理

    在Vivado下利用Tcl实现IP的高效管理https://cloud.tencent.com/developer/article/1736645 在Vivado下,有两种方式管理IP。一种是创建FPGA工程之后,在当前工程中选中IP Catalog,生成所需IP,这时相应的IP会被自动添加到当前工程中;另一种是利用Manage IP,创建独立的IP工程,缺省情况下,IP工程

    2024年01月22日
    浏览(39)
  • Vivado block design 导出与导入(tcl文件的生成与载入)

    摘要:Vivado block design 导出与导入 主要步骤:open block design —— File —— Export —— Export block design open block design File —— Export —— Export block design 将block design 保存到自己想要的位置,然后在Tcl console中使用tcl命令,直接source   我在source的时候会遇到版本不一致的问题,这个

    2024年02月11日
    浏览(33)
  • (55)TCL脚本命令【eval】

    1.1 TCL简介 1.2 TCL的起源与发展 1.3 TCL语言与库介绍 1.4 TCL运行环境 1.5 TCL脚本命令【eval】 1.6 结束语 Tcl 语言的全称 Tool Command Language,即工具命令语言。这种需要在 EDA 工具中使用的相当之多,或者说几乎每个 EDA 工具都支持 Tcl 语言。所以对于 IC 专业的来说,学习Tcl也是很重

    2024年02月16日
    浏览(32)
  • (51)TCL脚本命令【foreach】

    1.1 TCL简介 1.2 TCL的起源与发展 1.3 TCL语言与库介绍 1.4 TCL运行环境 1.5 TCL脚本命令【foreach】 1.6 结束语 Tcl 语言的全称 Tool Command Language,即工具命令语言。这种需要在 EDA 工具中使用的相当之多,或者说几乎每个 EDA 工具都支持 Tcl 语言。所以对于 IC 专业的来说,学习Tcl也是很

    2024年02月11日
    浏览(27)
  • (65)TCL脚本命令【regexp】

    1.1 TCL简介 1.2 TCL的起源与发展 1.3 TCL语言与库介绍 1.4 TCL运行环境 1.5 TCL脚本命令【regexp】 1.6 结束语 Tcl 语言的全称 Tool Command Language,即工具命令语言。这种需要在 EDA 工具中使用的相当之多,或者说几乎每个 EDA 工具都支持 Tcl 语言。所以对于 IC 专业的来说,学习Tcl也是很

    2024年02月04日
    浏览(35)
  • (66)TCL脚本命令【regsub】

    1.1 TCL简介 1.2 TCL的起源与发展 1.3 TCL语言与库介绍 1.4 TCL运行环境 1.5 TCL脚本命令【regsub】 1.6 结束语 Tcl 语言的全称 Tool Command Language,即工具命令语言。这种需要在 EDA 工具中使用的相当之多,或者说几乎每个 EDA 工具都支持 Tcl 语言。所以对于 IC 专业的来说,学习Tcl也是很

    2024年02月14日
    浏览(25)
  • (56)TCL脚本命令【puts】

    1.1 TCL简介 1.2 TCL的起源与发展 1.3 TCL语言与库介绍 1.4 TCL运行环境 1.5 TCL脚本命令【puts】 1.6 结束语 Tcl 语言的全称 Tool Command Language,即工具命令语言。这种需要在 EDA 工具中使用的相当之多,或者说几乎每个 EDA 工具都支持 Tcl 语言。所以对于 IC 专业的来说,学习Tcl也是很重

    2024年02月14日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包