2008年12月25日星期四

tcl在DC中的使用-----part1

1.计算target library中mux单元的个数(mux单元都是mx开头的形式)

proc mux_cnt{{lib_name typical.db}} {
redirect -variable libdata {report_lib $lib_name}
set mx_number [regexp -all mx $libdata]
echo "the count of mux in $lib_name is \t $mx_number\n"
}

说明:
redirect不仅可以将命令的输出送到文件中,也可以送到某个变量中,如果送到文件中,也可以用unix下glob -c mx $file来计算mx_number。
regexp不仅可以返回是否匹配的标志,也可以使用-all来返回匹配的个数。

2.计算一个timing group中TNS

proc rpt_TNV {} {
redirect -variable rptstring {report_constraint -all_violators -nosplit}
foreach line [split $rptstring \n] {
if {[string match *VIOLATED* $line]} {
incr TNV } else {
echo $line set TNV 0 }
}
}; # End proc

说明:
split函数可以用来将string分成list,然后使用foreach来遍历每个元素。

3.lsearch和string match的使用
lsearch有三个option,-exact,-glob,-regexp 后面紧跟这list,最后是patten。注意list和pattern的先后顺序,与glob命令和regexp是不一样的。返回的值是最先匹配到元素的indice值。可以结合lindex来使用,查看匹配的元素。
string match后面先跟着pattern,最后才是string。返回是否匹配的布尔值。

4.完善自定义proc的help功能。
使用define_proc_attribute来实现。
define_proc_attributes clean_log \
-info "Removing duplicating timing report" \
-command_group my_goup \
-define_args { {infile "log file to be cleaned" infile} {outfile "cleaned file" outfile}}

proc clean_log{infile outfile}{
set in_file_hd [open $infile r]
set out_file_hd [open $outfile w]
while {[gets $in_file_hd each_line] != -1} {
puts $out_file_hd $each_line}
close $in_file_hd
close $out_file_hd
}

说明:上面定义的proc有一个不足,就是infile和outfile位置都是固定的,不能颠倒,处于robust的考虑,可以采用clean_log -infile file_name -outfile file_name的方式就好了。可以使用parse_proc_arguments -args $args results,这样程序可以写成如下的形式:
proc clean_log {args} {
parse_proc_arguments -args $args results
set in_file_hd [open $results(-infile) r]
set out_file_hd [open $results(-outfile) w]
……
}
注意在使用这种不需要位置的参数,需要在defien_proc_attribute中来define_args。

5.关于collection的使用。
如果将collection赋给某个变量,比如下面的命令set allclock [all_clocks],然后试图在终端查看它,使用echo,你会得到一个_selxx的值,很郁闷把,DC在查看collection的时候,使用了两条专有的命令,一个是query_objects,一个是get_object_name,从名字上就可以看出来,query_objects可以看多具有多个对象的collection内容,而get_object_name只可以查看具有一个对象的collection内容。

2008年12月24日星期三

register retiming的逻辑综合

所谓的register retiming 指的是通过改变寄存器在组合逻辑的位置来达到优化时序和面积的优化技术。一般compile和compile_ultra里面的优化是通过布尔代数来优化组合逻辑,不会改变寄存器的位置。

register retiming有三个命令,optimize_registers,pipeline_registers,balance_registers。其中optimize_registers最常用,可以优化同步寄存器和异步寄存器位置来达到优化时序和面积的目的,而且默认情况下还执行一次增量编译。pipeline_registers主要是用来对纯组合逻辑按照指定的流水级数插入流水线。balance_registers只用来移动寄存器的位置来改善时序,而不会优化面积,也不会执行增量编译。

2008年12月22日星期一

复杂clock的综合约束总结

1.多clock的关系有三种,同步关系,异步关系和逻辑互斥关系。前两种很容易理解,关键是逻辑互斥关系(logic-exclusive)。这种时钟关系表示时钟之间没有逻辑上的timing path,最常见的例子就是mux结构的时钟。如下图:


对这种结构进行逻辑综合的时候,如何进行设置时钟?method :首先创建四个时钟,分别是ck1,ck2,ck3,ck4,由于时钟会穿过逻辑门进行分析,因此mux结构的输出并不需要定义时钟,老版本DC可能只会分析最近定义的一个时钟,DC2007则没有这个问题。如果想查看一下mux的输出管脚的时钟,可以用get_attribute [get_pins mux/Y] clocks来查看。然后就是设置false path的问题,除了ck1和ck3,ck2和ck4有逻辑上时钟路径需要分析外,其余均为逻辑互斥时钟,因此可以定义
set_clock_groups -logically_exclusive -group [get_clocks "clk1 clk3"] -group [get_clocks "clk2 clk4"]
来代替众多的set_false_path。

2.create_generated_clock中combinational选项的使用

该选项的意义有两个,一个是告诉DC,分频比为1,一个是告诉DC,在分析network latency的时候,只追溯组合逻辑。

3.时钟截断命令。

对于下面的电路:

clkin要求考虑到两个时钟,一个慢时钟,一个快时钟,在输入快时钟时,上半部分有效,在输入为慢时钟时,下半部分有效工作,对于这种电路,如何约束呢?(method:首先在clkin这个port上定义两个时钟,注意使用create_clock的add选项,然后针对每一个时钟设置input_delay。然后最重要的就是将某些时钟剔除,比如lsdin_reg只有在慢时钟才有效工作。那么就在在该寄存器的时钟输入端剔除快时钟,剔除的命令就是

set_clock_sense -stop_propagation -clock hclk [get_pins lsd*_reg/CP]set_clock_sense -stop_propagation -clock lclk [get_pins hsd*_reg/CP]

2008年12月19日星期五

the next two days plan

1.bist learning,especially mbist

2.linux study

全速测试(at speed test)

在工艺节点在130nm以下的时候,很多情形下的物理缺陷都是由于延时来引起的。因此在对这种类型的chip做dft的时候,需要建立一个新的故障模型,业内称之为延时故障模型(time delay model)。解决的方法就是全速测试,所谓的全速测试就是让芯片工作在自己高倍时钟频率上,这个频率往往是要高过ATE的时钟的。这样对扫描模型的建立就提出了新的要求。即至少要保证芯片的latch clock和capture clock为芯片内部的高倍时钟。synopsys对此种问题的解决方法就是OCC(on chip clocking)。DFT Compiler支持两种模式的带OCC的扫描链插入,一种是自身的设计已经带上OCC电路的,另一种是不带OCC电路的。
下面分别说说这两种插入的流程。
1.OCC的自动插入
  • 使能occ的插入,使用的命令是
set_dft_configuration -clock_controller enable

  • 定义时钟,包括参考时钟,ATE时钟,PLL产生的时钟。
参考时钟的定义:如果周期跟默认的测试周期相同,定义方法

set_dft_signal -view existing_dft -type MasterClock -port my_clock -timing {45 55}

set_dft_signal -view exsiting_dft -type refclock -port my_clock -period 100 -timing {45 55}

如果周期不同,就只需要定义refclock,不需要定义MasterClock

set_dft_signal -view exsiting_dft -type refclock -port my_clock -period 10 -timing {4 6}

ATE时钟的定义:

set_dft_signal -view exsiting_dft -type ScanClock -port ate_clock -timing {45 55}

set_dft_signal -view exsiting_dft -type Oscillator -port ate_clock

PLL产生时钟的定义:

set_dft_signal -view existing_dft -type Oscillator -hookup_pin pll/clk1

set_dft_signal -view existing_dft -type Oscillator -hookup_pin pll/clk2

  • 指定全局信号,包括pll_bypass,pll_reset,ScanEnble,TestMode

set_dft_signal -view spec -type pll_reset -port pll_rst

set_dft_signal -view spec -type pll_bypass -port pll_bp

set_dft_signal -view spec -type ScanEnable -port scan_en

set_dft_signal -view spec -type TestMode -port test_en

  • clock controller的设置

set_dft_clock_controller -cell_name u1 -design_name occ_clock_mux

-pllclocks [pll/clk1 pll/clk2] -ateclocks [ate_clock]

-cycles_per_clock 2


  • scan_configuration的设置

2.OCC已经存在

这种情况下由于OCC已经插入,因此命令set_dft_clock_controller在这里已经没有意义了,这里需要让DFT知道occ输出时钟信号的属性,使用的方法还是set_dft_signal。另外需要指定clock chains,使用set_scan_path来指定,将其complete化。另外如果使用到adaptive scan,注意test mode在两种模式下都必须指定啊。

2008年12月17日星期三

illinois扫描结构

一个芯片的测试成本主要受到三个因素的影响,第一个就是测试的时间,就是将所有的测试向量灌到芯片里面,并收集结果所花费的时间。第二个就是测试数据的数量,第三个就是测试的管脚。举一个IBM chip的例子,设计逻辑部分有7 百万个门,有25万个寄存器单元,采用full scan的结构,如下图:假设需要的测试向量为7000个,则移位寄存器需要消耗的测试时间为7000*250000=1.75G cycle。假设测试时钟周期是100M,则需要耗时17.5s。需要消耗的memory为1.75G bit。很庞大,是把。怎么解决呢,容易想到的就是将这个扫描链的长度减小,用多个扫描链来替代,结构如下图:
将这一个长的扫描链分解成1000个250个长度的扫描链,这样移位寄存器的load time就减少到以前的1/1000,但是付出的代价是测试管脚增加了太多,一方面芯片不可能提供这么多管脚做DFT,另外一般的ATE只有10到200个扫描信道,所以说上面的方案仍然需要改进。选取2500个寄存器做个一个扫描链的长度,这样就将扫描信道减小到100,就可以忍忍使用了。需要注意的是,这种并行的方法只是减少了数据的load的时间,数据量并没有减少。 能不能有一种方法能减少load time,同时又能减小pin和data volume的?illinois就是其中的一种方法。具体原理见下图:
上图的四个扫描链共享一个scan data输入,这样减小了pin的使用,但是这样会有问题,就是覆盖率的问题。见下图对于上面的与门,输入只会出现两种情况,一种就是000,一种就是111,不会出现其他的情况,这样就会减低故障覆盖率。这怎么办才好么?方法就是采用两种模式相结合的方式。下图:
下面的几个图是说明使用illinois扫描结构效果的示意图:














效果很好,但是有一个选择分组的问题,也就是说把哪些扫描链共享一个scan_in。分组的原则就是将对覆盖率的损害降到最低。

2008年12月16日星期二

DFT Compiler的学习------part8 tips and tricks

1.down-top的扫描链插入处理。

主要的考虑是在顶层直接处理会造成占用内存太大,容易溢出。采取的方法是层次化插入扫描链,先对底层的模块进行扫描链插入,插入完毕后,写出test model,并且释放内存。test model的形式有两种,一种是ddc形式,一种是ctl形式。ctl形式是可以查看内容的,是用ascii文件表示的。如果整个流程呢个都是galaxy流程的化,最好使用ddc的格式。释放内存remove_design就可以了。对底层模块都插入完毕后,在顶层首先是读入各个test model。使用的命令是read_ddc或者是read_test_model。注意这里read_ddc读入的不是底层模块的网表,而是test model。读入test model 之后,使用use_test_model -true [design]来指定,然后该干啥就干啥。