VERDVANA'S BLOG Verdvana

通过Tcl扩展SDC


1 前言

        Synopsys设计约束(Synopsys Design Constraints,SDC)用于描述时序、功率和面积的设计要求,SDC命令基于命令工具语言(Tool Command Language,Tcl),通过使SDC扩展到Tcl,特定于工具的命令可以与原生的Tcl结构,使其成为实现工具非常强大的语言。


2 Tcl基础知识

        Tcl遵循一些基本语义,每条Tcl语句以换行符或分号结束。如果一条语句跨越多行,然后在下一行继续执行,则应该在行尾加反斜杠。

        每条语句及其参数都被视为字符串,一个被双引号或大括号括住的包含多个单词的字符串认为是单个单元。

        以“#”开头的语句被认为是Tcl的注释。

puts  "Hello, World!"; #这是注释
puts  {Hello, World!}

        这里的每条语句都会向标准输出设备打印“Hello, World!”。用空格分隔的单词被视为是语句中的多个参数。

        Tcl中具有多种语言结构:

  • 变量;
  • 列表;
  • 表达式与运算符;
  • 控制流语句;
  • 过程。

2.1 变量

        Tcl变量是ASCII字符串,数字也用ASCII字符来表示。变量使用“set”命令来分配,例如:

set abc "1234";  #设置变量abc的值为1234

        如果需要对变量求值,则需要使用美元($)符号,例如:

puts $abc;      #打印出1234

        如果索引与变量名一起使用,则可将变量视为数组。索引不一定是整数,它也可以是一个字符串,例如:

set def(1) 4567;  #这里def是数组变量,索引被设置为1
set def(test) 89; #索引为test

        在Tcl中,“4567”和4567是相同的,因为它们都被视为字符串。要获取数组中使用的索引值,要使用命令“array names”,例如:

array names def;  #返回值1和test

        要对数组变量求值,可以使用相同的原理,但要指定索引:

puts $def(1);
puts $def(test);

        由于“$”在变量求值时有特殊含义,所以要打印此符号时,必须在其前面加上反斜杠。变量求值也不能放在大括号里。

        如果要尝试利用另一个命令设置变量,则应该讲命令括在方括号中。方括号中的任何内容都会在使用前求值。然而,大括号内的方括号中的内容不进行求值:

set x [set y 100];    #将x的值设置为100
set x {[set y 100]};  #将x的值设置为[set y 100]

4.2 列表

        Tcl中的列表是对象的集合。能够对列表进行添加、索引、搜索等操作:

#创建列表
set gates [list AND OR NOT NAND NOR]
set getes { {AND} {OR} {NOT} {NAND} {NOR} }
set gates [split "AND.OR.NOT.NAND.NOR" "."]
#将另一个项目添加到列表中,使用lappend
set gates [lappend gates XOR]
#要在列表中搜索,使用lsearch,它将返回列表中匹配的索引
puts [lsearch $gates NOT]   #返回2
puts [lsearch $gates XNOR]  #返回-1,因为找不到

4.3 表达式与运算符

        Tcl中使用expr命令来对表达式求值:

set   x 10;

expr  $x+20
expr  {$x+20}
# 两条命令返回相同的值

        Tcl中支持的运算符: | 运算符 | 描述 | | — | — | | - + ~ ! | 一元减、一元加、按位取反、逻辑非 | | + - * / | 加、减、乘、除 | | ** | 指数 | | < > <= >= == != | 关系运算符:小于、大于、小于等于、大于等于、等于、不等于 | | eq ne | 比较两个字符串:相等、不等 | | in ni | 检查列表中的字符串:包含、不包含 | | & | \^ | 按位与、或、异或 | | && || | 逻辑与、逻辑或 | | « » | 左移、右移 |

4.4 控制流语句

        控制流语句由以下种类的结构组成:

  • 列表遍历;
  • 决策;
  • 循环;
  • 子程序。

        为了遍历列表,Tcl提供了foreach结构:

set gates [list AND OR NOT NAND NOR XOR]
set index 1

foreach element $gates{
  puts "Gate $index in the list is $element"
  incr index;   # index自动加1
}

        产生的结果如下:

Gate 1 in the list is AND
Gate 2 in the list is OR
Gate 3 in the list is NOT
Gate 4 in the list is NAND
Gate 5 in the list is NOR
Gate 6 in the list is XOR

        Tcl的foreach为用户提供了同时遍历多个列表的独特功能:

set allgates {}
foreach gatelist1 {AND OR XOR}  gatelist2{NAND NOR XNOR} {
  lappend allgates $gatelist2 $gatelists1
}

        这段语句会在变量allgates中存储以下值“NAND AND NOR OR XNOR XOR”。可以看到,这个遍历程序可以让来自不同列表的项目混合在一起。

        Tcl提供if-elseif-else结构来提供决策:

if { $frequency < 330 } {
  puts "Chip will function well, but slower than expcted"
} elseif { $frequency > 330 } {
  puts "Chip will not function"
} else {
  puts "Cip will function optimally"
}

        当程序想在一个条件下循环和终止时,可以使用Tcl提供的for和while语句。它还提供了两个额外的结构break和continue。break用于提前结束循环,而continue则用于停止执行当前循环的代码,并重新评估循环条件。它们也可以与foreach一起使用。

while { ![eof $FD] } {
  gets $FD line
  puts $line
}

        Tcl过程使用proc来编写。使用return语句从过程中返回值:

proc sum {addend1 addend2} {
  set value [expr {$addend1 + $addend2}]
  return $value
}

# 调用过程
set x [sum 5 10]
puts $x         # 打印15

        还可以在定义过程时定义或设置参数的默认值,如:

proc sum { {addend1 10} {addend2 20} }

4.5 其他指令

命令 描述
open/close 文件句柄,用来打开和关闭文件

        告辞。