David.Z的个人空间 https://blog.eetop.cn/zengwen [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

使用Perl编写脚本完成批量calibre lvs

热度 5已有 2308 次阅读| 2023-4-26 16:11 |个人分类:日常记录|系统分类:芯片设计

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


5

点赞

刚表态过的朋友 (5 人)

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 25

    粉丝
  • 7

    好友
  • 45

    获赞
  • 1000

    评论
  • 173

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-13 12:08 , Processed in 0.027215 second(s), 9 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部