Timing Analyzer 脚本中的实例和实体

author-image

作者

在为 Timing Analyzer 编写自定义脚本时,您应该了解不同的 Tcl API 函数如何处理和返回节点名称中的实体和实例名称。Quartus® II 软件中有一个名为“显示节点名称的实体名称”的设置,用于控制节点名称中是否显示实体名称。
无论“显示节点名称的实体名称”的设置如何,Tcl API 函数 get_registers 始终可以接受将包含实体的名称作为筛选器。get_registers 函数始终根据“显示节点名称的实体名称”的设置返回名称。
表 1 显示了命令 get_registers <filter> 返回的节点名称示例,示例中的设计包含名为 ram:my_ram|ctrl:ctrl_1|addr[0] 的寄存器。

Tcl API 函数 get_pinsget_cells 的行为与 get_registers 不同。get_pinsget_cells 函数仅接受和返回包含实例名称的名称。无论“显示节点名称的实体名称”的值是多少,它们都不接受或返回包含实体的名称。
表 2 显示了 get_pins <filter> 返回的节点名称示例,示例中的设计包含名为 ram:my_ram|ctrl:ctrl_1|addr[0] 的寄存器,此寄存器具有名为 clk 的时钟引脚。get_cells 函数的行为相同,但它可以接受和返回单元名称。

注:

  1. get_pins 函数会生成一个警告,指示指定筛选器无法与引脚匹配。

如果您了解 get_registersget_pins 和 get_cells 处理和返回包含实体的节点名称的方式差异,就可以避免将这两个函数配合使用时可能出现的细微问题。以下示例显示了“显示节点名称的实体名称”关闭时可以运行、开启时无法运行的代码。

foreach_in_collection reg_id [get_registers foo*] {
    set reg_name [get_node_info -name $reg_id]
    # ...
    set pin_id [get_pins ${reg_name}|clk]
    # 如果 reg_name 包含实体,将无法调用 get_pins
}

“显示节点名称的实体名称”关闭时,变量 reg_name 不包含实体名称,因此可以成功调用 get_pins“显示节点名称的实体名称”开启时,变量 reg_name 包含实体名称,因此无法调用 get_pins

解决方案

避免潜在问题最简单的方法是关闭“显示节点名称的实体名称”,并且仅使用实例名称引用节点。此解决方案可确保 get_registers 返回的名称是纯实例名称,并可与 get_pinsget_cells 配合使用。

如果不关闭“显示节点名称的实体名称”,并且将 get_registers 返回的名称传递到 get_pinsget_cells,那么必须确保已移除了所有实体名称。可以使用简单的 regsub 表达式移除大多数实体名称。只要实体名称仅包含字母、数字和下划线(\w 字符类中的字符),以下 Tcl 命令就可以移除节点名称中的所有实体名称。

regsub -all {\w*:} $reg_name {} reg_name

列出的正则表达式模式并不处理 HDL 标识符中的每个有效字符。它不处理生成的实体名称,包括反斜杠 (\)、简单 Verilog HDL 标识符中的美元符号字符 ($)、Verilog HDL 转义标识符或 VHDL 中的扩展标识符。可以通过构建更高级的正则表达式来处理包含这些字符的实体名称,但关闭“显示节点名称的实体名称”更简单。
以下示例展示了如何将 regsub 表达式与上面无法运行的示例整合在一起。在以下示例中,regsub 表达式从寄存器名称中移除了实体名称(受所述例外字符的限制),因此可以成功调用 get_pins。无论“显示节点名称的实体名称”的值是多少,此示例都可以运行。

foreach_in_collection reg_id [get_registers foo*] {
    set reg_name [get_node_info -name $reg_id]
    regsub -all {\w*:} $reg_name {} reg_name
    # reg_name 不再包含实体
    # ...
    set pin_id [get_pins ${reg_name}|clk]
    # reg_name 不再包含实体,因此可以成功调用 get_pins
}