热度 10| ||
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
/2