热度 7| ||
20230426
初步想法:用变量存储一系列需要跑LVS的Cell列表,然后便利所有Cell表通过strmout ,si,calibre,命令完成gds和netlist的产生和比对,通过读取所有对应report和err文件中的结果,再把所有结果统计到一个新的文件里面。
最终结果应该要产生两个文件:::lvs.result lvs.log
lvs.result 里面存储结果,格式:
cell1 pass/fali
cell2 pass/fail
cell3 pass/fail
lvs.log保存运行中的一系列过程信息,方便后续查看。
20230428
完成了大半部分的功能,包括利用strmout产生对应的gds,si 产生对应的netlist文件,calibre命令跑 LVS,剩余需要实现的功能为读取所有对应目录的.report .err.result文件综合分析,并将分析结果 存储成一个文件方便后续阅读, 最简单的方式为读取report文件中是CORRECT 还是 INCORRECT 可以最直接判断LVS通过与否,后续还可以读取.err.result文件查找是否有软链接等错误。
因为初学perl的原因,代码被分为五段实现,分别为创建对应目录,在目录中生成gds文件,在目录中生成netlist文件,进入对应目录 run calibre lvs,分析结果并创建报告(因时间原因还未实现)。
代码十分冗杂,怕出错所以把整体结构分成几段写,完成一段后跑几遍,能实现功能后再写下一段,后续需要很多的优化,且该脚本只是省略了手动点击的过程,以后要研究下怎么通过多线程的方式同时跑多个calibre lvs。
脚本运行逻辑::需要提前用gui跑一边lvs,把跑过后的runset文件复制到脚本所在目录下供运行读取,还需要si.env文件,获取方法为自己手动生成一次netlist文件,就会再工作目录下发现si.env,一样需要移动到脚本所在目录。脚本运行后会以这两个文件为模板不断创建对应的文件。
#####################################################################################
#####################################################################################
#####################################################################################
#####################################################################################
#####################################################################################
脚本使用方式::
修改personal setting内的变量,目前只有,$WorkSpace 和 @Cell_list
$WorkSpace ::工作目录,也就是项目所在路劲
@Cell_list ::需要跑的library 和 cell,library需要再前面加上#表示,不加#视为该library 的Cell
./batch_lvs 运行,会在所在路径创建一个跟当前时间有关的文件夹,所有的相关目录和文件都会在里面,目前自己测试跑了几遍能够正常运行并产生结果。
脚本:::::::::
#! /usr/bin/perl use strict; use feature 'state'; use autodie; #Created in 20230426 by david.z ################# #personal setting; ############################## my $WorkSpace='/home/myworkspace'; my @Cell_list=qw{ #Library1 cell1 cell2 cell3 cell4 cell5 #Library2 cell1 cell2 cell3 cell4 cell5 #Library3 cell1 cell2 cell3 cell4 cell5 #Library4 cell1 cell2 cell3 cell4 cell5 }; ##my $runset_file='runset'; #common setting; ############################################ my $runDir=$ENV{'PWD'}; my $date=mkdir_by_date(); my $current_library; ############################################ print "##run date is $date\n"; print "##runDir is : $runDir\n"; print "##WorkSpace is :$WorkSpace \n"; print "##Chdir to WorkSpace........\n"; chdir $WorkSpace or die "cannot chdir to $WorkSpace :$!"; chdir $runDir; ######### print the library and cell list . print "library and cell list :\n"; foreach my $Cell (@Cell_list){ my $current_library; if ($Cell=~/#.*/){ $current_library=$Cell; print "\n $current_library :"; next; } print " $Cell "; } print "\n"; ########################################### ####create directory mkdir $date ,0755 or die "cannot mkdir $date :$! \n"; unless($Cell_list[0]=~/#.*/){ die "Cell list format error\n";} print "##chdir to $date to create all directory\n"; chdir "$date" or die "cannot chdir to $date:$!\n"; foreach my $Cell (@Cell_list){ my $current_library; my $tmp_Cell=$Cell; if ($tmp_Cell=~/#.*/){ chdir "$runDir/$date"; $tmp_Cell=~s/#//; $current_library=$tmp_Cell; mkdir "$current_library",0755 or die "mkdir $date/$current_library error :$!\n"; chdir "$current_library" or die "cannot chdir to $current_library:$!\n";; next; } mkdir "$Cell",0755 or die "mkdir $date/$current_library/$Cell error :$!\n"; } print "##all directory have created\n"; chdir $runDir;###current dir ::runDir; ################################################## ####create gds file print "##chdir to $WorkSpace to strmout\n"; chdir "$WorkSpace" or die "cannot chdir to $WorkSpace:$!\n"; ###current dir ::WorkSpace; ###run all strmout;; print "##extract all gds file\n"; foreach my $Cell (@Cell_list){ my $tmp_Cell=$Cell; if ($tmp_Cell=~/#.*/){ $tmp_Cell=~s/#//; $current_library=$tmp_Cell; next; } print "##strmout:: current library is $current_library..\n"; !system 'strmout', '-library', "$current_library", '-strmFile', "$Cell.gds" , '-runDir', "$runDir/$date/$current_library/$Cell", '-topCell', "$Cell", '-view', "layout", '-logFile', "$Cell.log", '-summaryFile', "$Cell.sum" or die "cannot run strmout ::current_library is $current_library ,Cell is $Cell\n"; } print "##all gds file have extracted sucessfully\n"; #################################################################################################### chdir $runDir;###current dir ::runDir; #######extract netlist print "##extract all netlist file\n"; -e 'si.env' or die "###cannot find file si.env\n"; foreach my $Cell (@Cell_list){ my $tmp_Cell=$Cell; if ($tmp_Cell=~/#.*/){ $tmp_Cell=~s/#//; $current_library=$tmp_Cell; next; } print "##si :: current library is $current_library..\n"; open SIENV, '<','si.env' or die"Can't read file si.env: $!"; open SIENV_NEW ,'>',"$runDir/$date/$current_library/$Cell/si.env.new" or die"Can't read file si.env.new: $!"; ####replace the si.env while( <SIENV> ) { s/simLibName.*/simLibName = "$current_library"/g; s/simCellName.*/simCellName = "$Cell"/g; s/simViewName.*/simViewName = "schematic"/g ; s/hnlNetlistFileName.*/hnlNetlistFileName = "$Cell.cdl"/g; print SIENV_NEW $_; } close SIENV; close SIENV_NEW; rename "$runDir/$date/$current_library/$Cell/si.env.new" => "$runDir/$date/$current_library/$Cell/si.env" or die "rename si.env.new to si.env failed ::$!\n"; ####replace finished ###run si !system 'si', "$runDir/$date/$current_library/$Cell", '-batch', '-command', "netlist", '-cdslib', "$WorkSpace/cds.lib" or die "###cannot run si ::current_library is $current_library ,Cell is $Cell\n"; } print "##all netlist file have extracted sucessfully\n"; #################################################################################################### #######run calibre lvs print "###run calibre lvs\n"; chdir $runDir;###current dir ::runDir; foreach my $Cell (@Cell_list){ my $tmp_Cell=$Cell; if ($tmp_Cell=~/#.*/){ $tmp_Cell=~s/#//; $current_library=$tmp_Cell; next; } print "###calibre lvs :current library is $current_library..\n"; ##########change the runset file open RUNSET, '<','runset' or die"Can't read runset: $!"; open RUNSET_NEW ,'>',"$runDir/$date/$current_library/$Cell/runset_new" or die"Can't create file runset_new: $!"; while( <RUNSET> ) { s!\*lvsRunDir.*!\*lvsRunDir: $runDir/$date/$current_library/$Cell!g; s!\*lvsLayoutPaths.*!\*lvsLayoutPaths: $Cell.gds!g; s!\*lvsLayoutLibrary.*!\*lvsLayoutLibrary: $current_library!g; s!\*lvsLayoutPrimary.*!\*lvsLayoutPrimary: $Cell!g; s!\*lvsSourcePath.*!\*lvsSourcePath: $Cell.cdl!g; s!\*lvsSourcePrimary.*!\*lvsSourcePrimary: $Cell!g; s!\*lvsSourceLibrary.*!\*lvsSourceLibrary: $current_library!g; s!\*lvsSpiceFile.*!\*lvsSpiceFile: $Cell.sp!g; s!\*lvsERCDatabase.*!\*lvsERCDatabase: $Cell.erc.results!g; s!\*lvsERCSummaryFile.*!\*lvsERCSummaryFile: $Cell.erc.summary!g; s!\*lvsReportFile.*!\*lvsReportFile: $Cell.lvs.report!g; s!\*cmnFDIDEFLayoutPath.*!\*cmnFDIDEFLayoutPath: $Cell.def!g; print RUNSET_NEW $_; } close RUNSET; close RUNSET_NEW; rename "$runDir/$date/$current_library/$Cell/runset_new" => "$runDir/$date/$current_library/$Cell/runset" or die "###rename runset_new to runset failed ::$!\n"; print "###run calibre lvs in $runDir/$date/$current_library/$Cell\n"; ##################change finished !system 'calibre', '-gui', '-lvs', '-runset', "$runDir/$date/$current_library/$Cell/runset", '-batch' or die "###run calibre $runDir/$date/$current_library/$Cell error\n"; } print "###run calibre lvs all successfully\n"; #######calibre lvs finished chdir $runDir;###current dir ::runDir; #################################################################################################### ####create report open REPORT,'>','report' or die "cannot create report :$!\n"; my $result = ''; foreach my $Cell (@Cell_list){ my $tmp_Cell=$Cell; if ($tmp_Cell=~/#.*/){ $tmp_Cell=~s/#//; $current_library=$tmp_Cell; print REPORT "####$current_library#####\n"; next; } print "###report:current library is $current_library..\n"; check_report("$runDir/$date/$current_library/$Cell/$Cell.lvs.report"); unless($result eq 'error'){ print REPORT "$Cell-------------$result\n"; } } close REPORT; ##################get current datetime to mkdir sub mkdir_by_date{ my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time); my $mytime=sprintf("%04d%02d%02d_%02d%02d%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec); $mytime; } ###################sub check report sub check_report{ my $file = $_[0]; open CELLREPORT ,'<',$file or die "cannot open $file :$!\n"; while(my $line = <CELLREPORT>){ if($line =~/\s+INCORRECT\s+/){ $result = 'INCORRECT'; last;} elsif($line=~/\s+CORRECT\s+/){ $result ='CORRECT'; last;} else{ $result='error';} } close CELLREPORT; }
20230504
全部代码已上传,整体实现方式非常简单,代码被拆分成多个步骤实现,所以看着复杂,需要后期慢慢优化,运行效率也很地下,就是省略了人工去点击的步骤,需要研究怎么能够一次跑多个calibre,目前只能生成一个report的报告查看过没过LVS,没有erc的分析,后期慢慢加入,此外 ,还需要能够生成一个log文件,方便出错后翻看查找错误点的位置。
在windows下复制到Linux可能不能直接运行perl,出现bash:/usr/bin/perl^M:bad interpreter:No such file or directory类似的错误,需要运行一下命令替换掉文件中的\R
perl -p -i -e "s/\R/\n/g" filename