=head NAME: DESCRIPTION: PARAMETER: {items => [ { name=>'job', label=>'料号名', type=>'editable_enum', property=>{ tl_field=>[name=>'text'], tl_data=>[ {name=>'${JOB}',}, {name=>'TL_genesis_work_jobname',}, {name=>'TL_genesis_org_jobname',}, ] }, must_field=>1, value=>'${JOB}_chk', }, { name=>'send_mail', label=>'是否发邮件', type=>'editable_enum', property=>{ tl_field=>[name=>'text'], tl_data=>[ {name=>'yes',}, {name=>'no',}, ] }, must_field=>1, value=>'yes', }, { name=>'mail_group', label=>'Mail Group Name', type=>'string', must_field=>1, value => 'goldarea>2.5sqin', }, ]} VERSION_HISTORY: V1.00 2011-06-13 Janson Zhang 1.新版本 V1.01 2011-06-13 John Sun 1.INCAM 中没有ATS菜单下的功能,现在用另外一种方法来代替完成,保证INCAM和Genesis能同时运行。 V1.02 2016-10-26 mast pei 修改deleteLayer中的bug V1.03 2019-07-25 mast pei 添加自动邮件 系统需求:2264 V1.04 2020-08-11 weiss 确认为多card板子时直接完成脚本 CQ2系统需求:2174 V1.05 2020-05-05 mast pei 添加自动邮件 系统需求:2822 修改触发邮件规则 和条件 V1.06 2020-09-07 John 系统需求:3132 Cancel RF PN HELP:

功能简介

Create PRE prepare step.


参数配置

● 料号名

设置genesis中料号的名字,${JOB}表示跟TopCAM中的料号名字一样,TL_genesis_work_jobname表示用这个料号属性定义的名字

注意事项


=cut #use strict; #my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR,$APP); use utf8; use Encode; use_module('ATS::GenMath'); use Data::Dump 'dump'; use_module('Top::MailSender'); my $ATS_GenMath = ATS::GenMath->new(); my ($Job,$Step); my $Return = 'Done'; my $incam = 'no'; if ($GEN->{GEN_TYPE} =~/incam/i) { $incam = 'yes'; } ###确定料号名; if (defined $PAR->{job} and ($PAR->{job} eq 'TL_genesis_org_jobname' or $PAR->{job} eq 'TL_genesis_work_jobname')){ $Job = $DB->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>$PAR->{job}); } elsif(defined $PAR->{job}){ $Job = $PAR->{job}; $Job =~ s/\$\{JOB\}/$JOB/g; $Job = lc($Job); } if ( ! defined $Job or $Job =~ /^\s*$/) { $GUI->msgbox(-icon=>'error',-text=>'未定义料号名'); return 'Error'; } my $PLAN_STATE='SHA'; if ( $DB->{DB_NAME} =~ /ATC/i) { $PLAN_STATE='CQ'; } ###处理step过滤 $PAR->{step_filter} = $PAR->{step_filter} ? $PAR->{step_filter} : '.*'; try{ if ($PLAN_STATE eq 'CQ' and $GUI->confirm("是否存在多card 需要用array拼好后在pre分析?") eq 'yes' ){ return $Return; } ###检查Genesis料号是否存在并打开 if (! $GEN->isJobExists(job=>$Job) ){ $GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!"); return 'Error'; } $GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job)); ###check and get work Step name my @steps = $GEN->getStepList(job=>$Job); if ( @steps == 0 ) { $GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!'); return 0; } elsif (@steps != 1){ my @tmp_steps = grep(/$PAR->{step_filter}/,@steps); if ( @tmp_steps == 1 ) { $Step = $tmp_steps[0]; } else { $Step = $GUI->select_step(-title=>'请选择工作Step', -steplist=>[@tmp_steps], -selectmode=>'single'); return 'Cancel' unless ($Step); } } else { $Step = $steps[0]; } ###Open step and clear layer $GEN->openStep(job=>$Job,name=>$Step); $GEN->clearLayers(); $GEN->affectedLayer(mode=>'all',affected=>'no'); $GEN->units(type=>'inch'); my $ans = $GEN->PAUSE("Please check the profile which used as check area!"); unless (defined $ans and $ans eq 'OK' ) {return 'Cancel';} #my $rf_mark= $GUI ->confirm("是否是RF料号"); my $rf_mark="no"; if ($rf_mark eq 'yes'){ $GUI->msgbox(-icon=>'info',-text=>'请检查软板层上是否有SMD/BGA要算金面积'); return unless ($GEN->PAUSE("Pls checking")); } my (@tl_data,@Front,@Back,@Probfr,@Probba,@Goldfr,@Goldba,@Drill); my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash'); foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) { push(@tl_data,{name=>$layer}); push(@Front,{name=>$layer}) if(defined($matrix{$layer}{tl_name}) and $matrix{$layer}{tl_name} =~ /^(top)$/ ); push(@Back,{name=>$layer}) if(defined($matrix{$layer}{tl_name}) and $matrix{$layer}{tl_name} =~ /^(bottom)$/); push(@Probfr,{name=>$layer}) if($matrix{$layer}{side} eq 'top' and $matrix{$layer}{layer_type} eq 'solder_mask'); push(@Probba,{name=>$layer}) if($matrix{$layer}{side} eq 'bottom' and $matrix{$layer}{layer_type} eq 'solder_mask'); push(@Goldfr,{name=>$layer}) if($matrix{$layer}{side} eq 'top' and $matrix{$layer}{layer_type} eq 'solder_paste'); push(@Goldba,{name=>$layer}) if($matrix{$layer}{side} eq 'bottom' and $matrix{$layer}{layer_type} eq 'solder_paste'); push(@Drill,{name=>$layer}) if($matrix{$layer}{layer_type} eq 'drill'); } my $layerinfo = [ {type=>'title',property=>{title=>'1.Carbon layer'}}, { name=>'Carbon_layer', label=>'Is Carbon layer', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field => 'name', tl_data=>[ {name=>'Yes',}, {name=>'No',}, ] }, must_field=>1, value=>'No', }, {type=>'title',property=>{title=>'2.array or card'}}, { name=>'sel', label=>'Surface calculation is based on', type=>'radio', property=>{ tl_columns=>3, tl_list=>['Array'=>'Array','Card'=>'Card'], }, must_field=>1, value=>'', }, {type=>'title',property=>{title=>'3.Setting'}}, { name=>'Front', label=>'Front Layer', type=>'enum', #editable_enum property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>\@Front, }, must_field=>1, value => (($#Front == 0) ? $Front[0]->{name} : ''), }, #2 { name=>'Probfr', label=>'Probfr Layer', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>\@Probfr, }, #must_field=>1, value => ($#Probfr == 0) ? $Probfr[0]->{name} : '', }, #3 { name=>'Goldfr', label=>'Front Reference Layer', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', #tl_data=>\@Goldfr, tl_data=>[{name=>''},@Goldfr], }, #must_field=>1, value => ($#Goldfr == 0) ? $Goldfr[0]->{name} : '', }, #4 { name=>'Reffr', label=>'Front Reference As', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>''}, {name=>'GOLD'}, {name=>'OSP'}, ], }, value => '', }, #5 { name=>'Back', label=>'Back Layer', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>\@Back, }, must_field=>1, value => ($#Back == 0) ? $Back[0]->{name} : '', }, #6 { name=>'Probba', label=>'Probba Layer', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>\@Probba, }, #must_field=>1, value => ($#Probba == 0) ? $Probba[0]->{name} : '', }, #7 { name=>'Goldba', label=>'Back Reference Layer', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>\@Goldba, tl_data=>[{name=>''},@Goldba], }, value => ($#Goldba == 0) ? $Goldba[0]->{name} : '', }, #8 { name=>'Refba', label=>'Back Reference As', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>''}, {name=>'GOLD'}, {name=>'OSP'}, ], }, value => '', }, #9 { name=>'Drill', label=>'Main Drill Layer', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>[{name=>'NA'},@Drill], }, must_field=>1, value => '', }, #10 { name=>'Thickness', label=>'Board Thickness(mm)', type=>'number', units=> 'mm', must_field=>1, value =>1.0, validation=>[ { condition=>'$Value < 0.1', msg_type=>'error', msg=>'Value should > 0.1', style=>{base=>'red'}, }, { condition=>'$Value > 3', msg_type=>'error', msg=>'Value should < 3', style=>{base=>'red'}, }, ] }, ]; $layerinfo = $GUI->show_form( -title=>'Please fill the layer name',-defaultsize => [740,660], -showcheck => 1,-gen => $GEN, -items=>$layerinfo); return 'Cancel' unless (%$layerinfo); my $thick=$layerinfo->{'Thickness'}*1000; $ans = $GEN->PAUSE('Please contourize surface to save script running time'); unless (defined $ans and $ans eq 'OK' ) { return 'Cancel'; } @steps = $GEN->getStepList(job=>$Job); _deleteLayer(step=>$steps[0],layer=>['qec_goldfr','qec_goldba','qec_ospfr','qec_ospba', 'rel_qec_goldfr+qec_ospfr','rel_qec_goldba+qec_ospba', 'qec_goldfr+++','qec_goldba+++','qec_ospfr+++','qec_ospba+++', 'rel_qec_goldfr+qec_ospfr+++','rel_qec_goldba+qec_ospba+++']); if ($layerinfo->{Drill} eq 'NA'){ $layerinfo->{Drill} = 'ats_drill' ; $GEN->matrixAddLayer(job=>$Job,layer=>$layerinfo->{Drill},type=>'drill',context=>'board',polarity=>'positive',) unless ($GEN->isLayerExists(job=>$Job,layer=>$layerinfo->{Drill})); } _deleteLayer(step=>$Step,layer=>['ref_layer_c_fr','ref_layer_c_ba']); foreach my $subStep (@steps){ next if ($subStep =~ /^(.*)(\d{8})\-(\d{6})$/) ; $GEN->openStep(job=>$Job,name=>$subStep); $GEN->units(type=>'mm'); $GEN->createLayer(job=>$Job,layer=>'ats_empty') unless ($GEN->isLayerExists(job=>$Job,layer=>'ats_empty')); if ($incam eq 'no'){ if ($layerinfo->{Goldfr} and $layerinfo->{Reffr}){ CreateGoldLayer($layerinfo->{Front},$layerinfo->{Probfr},$layerinfo->{Goldfr},$layerinfo->{Reffr},$layerinfo->{Drill},'qec_goldfr','qec_ospfr'); } elsif ($layerinfo->{Front} and $layerinfo->{Probfr}){ $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$layerinfo->{Front},$layerinfo->{Probfr}],clear_before=>'yes'); calc_area('ref_layer_c_fr'); } if ($layerinfo->{Goldba} and $layerinfo->{Refba}){ CreateGoldLayer($layerinfo->{Back} ,$layerinfo->{Probba},$layerinfo->{Goldba},$layerinfo->{Refba},$layerinfo->{Drill},'qec_goldba','qec_ospba') ; } elsif ($layerinfo->{Back} and $layerinfo->{Probba}){ $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$layerinfo->{Back},$layerinfo->{Probba}],clear_before=>'yes'); calc_area('ref_layer_c_ba'); } } else{ if ($layerinfo->{Goldfr} and $layerinfo->{Reffr}){ INCAM_CreateGoldLayer($layerinfo->{Front},$layerinfo->{Probfr},$layerinfo->{Goldfr},$layerinfo->{Reffr},$layerinfo->{Drill},'qec_goldfr','qec_ospfr',$subStep) ; } elsif ($layerinfo->{Front} and $layerinfo->{Probfr}){ $GEN->units(type=>'inch'); INCAM_CreateMetalLayer(step=>$subStep,outputLayer=>'ref_layer_c_fr',ep=>$layerinfo->{Front},sm=>$layerinfo->{Probfr}); } if ($layerinfo->{Goldba} and $layerinfo->{Refba}){ INCAM_CreateGoldLayer($layerinfo->{Back} ,$layerinfo->{Probba},$layerinfo->{Goldba},$layerinfo->{Refba},$layerinfo->{Drill},'qec_goldba','qec_ospba',$subStep) } elsif ($layerinfo->{Back} and $layerinfo->{Probba}){ $GEN->units(type=>'inch'); INCAM_CreateMetalLayer(step=>$subStep,outputLayer=>'ref_layer_c_ba',ep=>$layerinfo->{Back},sm=>$layerinfo->{Probba}); } } $GEN->units(type=>'mm'); $GEN->closeStep(); } _deleteLayer(step=>$Step,layer=>['qec_goldfr+++','qec_goldba+++','qec_ospfr+++','qec_ospba+++', 'rel_qec_goldfr+qec_ospfr+++','rel_qec_goldba+qec_ospba+++']); $GEN->openStep(job=>$Job,name=>$Step); $ans = $GEN->PAUSE('Please Check gold layer features,then continue'); unless (defined $ans and $ans eq 'OK' ) { return 'Cancel'; } my $info_step=$layerinfo->{sel}; $GEN->openStep(job=>$Job,name=>$Step); $GEN->units(type=>'mm'); if ($PLAN_STATE eq 'SHA') { my %guard_warning; foreach my $ref_layer_c('ref_layer_c_fr','ref_layer_c_ba'){ my $ll='Front'; my @refs= ('qec_goldfr','qec_ospfr'); if ($ref_layer_c eq 'ref_layer_c_ba'){ @refs= ('qec_goldba','qec_ospba') ; $ll='Back'; } if (!$GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){ foreach my $ggg (@refs){ if ($GEN->isLayerExists(job=>$Job,layer=>$ggg)){ my @steps11 = $GEN->getSubSteps(job=>$Job,step=>$Step); if (@steps11) { foreach my $f (@steps11){ $GEN->openStep(job=>$Job,name=>$f); $GEN->units(type=>'mm'); $GEN->copyLayer(source_job=>$Job, source_step=>$Step, source_layer=>$ggg, dest_layer=>$ref_layer_c.'_tmp', mode=>'append', #append invert=>'yes');#|'yes' } $GEN->openStep(job=>$Job,name=>$Step); $GEN->units(type=>'mm'); $GEN->flattenLayer(source_layer=>$ref_layer_c.'_tmp',target_layer=>$ref_layer_c.'_tmp1'); $GEN->copyLayer(source_job=>$Job, source_step=>$Step, source_layer=>$ref_layer_c.'_tmp1', dest_layer=>$ref_layer_c, #mode=>'append', #append invert=>'no');#|'yes' } else{ $GEN->copyLayer(source_job=>$Job, source_step=>$Step, source_layer=>$ggg, dest_layer=>$ref_layer_c, mode=>'append', #append invert=>'no');#|'yes' } } } } if ($GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){ my $ff = exposed_pad_size($Job,$Step,$layerinfo->{$ll},$ref_layer_c,$info_step); foreach my $num (keys %$ff){ $guard_warning{$ll}{$num}=$ff->{$num}; } } else{ $guard_warning{1} ="On $ll side, All layer exposed"; } } if (keys %guard_warning) { my $subject = "AUTO MAIL:GE01 risk PN[$JOB]"; my $sent_mail = "Base on [$info_step],High Risk PN [$JOB]:
"; $sent_mail.='Design information:
'; $sent_mail.='1, ID Print Side: ${ID_LAYER}
'; $sent_mail.='2, MF information: ${Array}/Panel, ${PCB}/Array
'; my $n1=3; foreach my $layer (qw/Front Back/){ if (keys %{$guard_warning{$layer}}){ $sent_mail.='On '.$layer.'
'; for my $n (1,2){ $sent_mail.=$n1.','.$guard_warning{$layer}{$n}.'
'; $n1++; } } } $sent_mail.='

Action required:
'; $sent_mail.='SM to MF: Use Panel interleaf
'; #$sent_mail.='RT to FI: Use Array interleaf (FR4)

'; $sent_mail.='${et_workflow_sap}

'; $sent_mail.='Part number alarm information:
'; foreach my $layer (qw/Front Back/){ if (@{$guard_warning{$layer}{3}}) { $sent_mail.='On '.$layer.'
'; foreach my $f (@{$guard_warning{$layer}{3}}){ $sent_mail.=$f; } } } #$GUI->debug("$sent_mail"); $DB->save_jobinfo( -jobid=>$JOB_ID, -jobcategory=>'org', -jobinfohash=>{ATS_GE01_mail =>$sent_mail}); } } my %surface; $surface{'gold_fr'}=0; $surface{'gold_ba'}=0; $surface{'gold_total'}=0; if($layerinfo->{Probfr}){ $surface{'cp_fr'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},$layerinfo->{Probfr},'','',$layerinfo->{Drill}); } else{ $surface{'cp_fr'}=expcopperArea($Job,$Step,$thick,$layerinfo->{Front},$layerinfo->{Probfr},'','',$layerinfo->{Drill}); } if($layerinfo->{Probba}){ $surface{'cp_ba'}=exposedArea($Job,$Step,$thick,'','',$layerinfo->{Back},$layerinfo->{Probba},$layerinfo->{Drill}); } else{ $surface{'cp_ba'}=expcopperArea($Job,$Step,$thick,'','',$layerinfo->{Back},$layerinfo->{Probba},$layerinfo->{Drill}); } $surface{'ref_fr'}=$layerinfo->{Reffr}; $surface{'ref_ba'}=$layerinfo->{Refba}; $surface{'gold_fr'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},'qec_goldfr',$layerinfo->{Back},'ats_empty',$layerinfo->{Drill}) if ($layerinfo->{Goldfr} and $layerinfo->{Reffr}); $surface{'gold_ba'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},'ats_empty',$layerinfo->{Back},'qec_goldba',$layerinfo->{Drill}) if ($layerinfo->{Goldba} and $layerinfo->{Refba}); if(($layerinfo->{Goldfr} eq '' or $layerinfo->{Goldfr} == 0) and $layerinfo->{Reffr} =~ /gold/i and !$layerinfo->{Goldfr}){ $surface{'gold_fr'}=$surface{'cp_fr'}; } if(($layerinfo->{Goldba} eq '' or $layerinfo->{Goldba} == 0) and $layerinfo->{Refba} =~ /gold/i and !$layerinfo->{Goldba}){ $surface{'gold_ba'}=$surface{'cp_ba'}; } $surface{'cp_total'}=$surface{'cp_fr'}+$surface{'cp_ba'}; $surface{'gold_total'}=$surface{'gold_fr'}+$surface{'gold_ba'} if ($surface{'gold_fr'} and $surface{'gold_ba'}); $surface{'carbon'}='__NA__'; if ( $layerinfo->{Carbon_laye} eq 'Yes'){ $surface{'carbon'}=0; my @layer = $GUI->select_layer( -title=>'Select Carbon Layers', -layermatrix=>{$GEN->getMatrix(job=>$Job)}, -default => [], -selectmode => 'multiple'); return 'Cancel' if(!defined($layer[0])); foreach my $layer (@layer) { my $reprot = $GEN->copperArea(layer1=>$layer); my $tmp = sprintf ('%.4f',$reprot->{area}); $surface{'carbon'}+=$tmp; } $surface{'carbon'}=$surface{'carbon'} / 10000; $surface{'carbon'}=sprintf('%.4f',$surface{'carbon'}); } $surface{'baseon'} = $info_step; # $GEN->PAUSE("$surface{baseon} g $surface{ref_fr} h $surface{ref_ba} "); my %InfoHash; $InfoHash{TL_exposed_area_front}=$surface{cp_fr}; $InfoHash{TL_exposed_area_back}=$surface{cp_ba}; $InfoHash{TL_gold_area_front}=$surface{gold_fr} * 1.1; $InfoHash{TL_gold_area_back}=$surface{gold_ba} * 1.1; # if ($layerinfo->{Goldfr}) { $InfoHash{ATS_selection_reference_layer_front}=$layerinfo->{Goldfr}; $InfoHash{ATS_selection_reference_type_front}=$surface{ref_fr}; ## Fix BUG 2017-04-25 When REF GOLD, Set REF = GOLD AREA, ## ELSE ,Set REF = ALL - GOLD AREA if ($InfoHash{ATS_selection_reference_type_front} eq 'GOLD') { $InfoHash{ATS_selection_reference_area_front}=$surface{gold_fr}; }else { $InfoHash{ATS_selection_reference_area_front}=$surface{cp_fr} - $surface{gold_fr}; } $InfoHash{ATS_org_area_type_full_front}=''; }else { $InfoHash{ATS_selection_reference_layer_front}=''; $InfoHash{ATS_selection_reference_type_front}=''; $InfoHash{ATS_selection_reference_area_front}=''; $InfoHash{ATS_org_area_type_full_front}='GOLD'; } if ($layerinfo->{Goldba}) { $InfoHash{ATS_selection_reference_layer_back}=$layerinfo->{Goldba}; $InfoHash{ATS_selection_reference_type_back}=$surface{ref_ba}; if ($InfoHash{ATS_selection_reference_type_back}eq 'GOLD') { $InfoHash{ATS_selection_reference_area_back}=$surface{gold_ba}; }else { $InfoHash{ATS_selection_reference_area_back}= $surface{cp_ba} - $surface{gold_ba}; } $InfoHash{ATS_org_area_type_full_back}=''; }else { $InfoHash{ATS_selection_reference_layer_back}=''; $InfoHash{ATS_selection_reference_type_back}=''; $InfoHash{ATS_selection_reference_area_back}=''; $InfoHash{ATS_org_area_type_full_back}='GOLD'; } $InfoHash{ATS_org_area_pe_check}='no'; $InfoHash{TL_carbon_area}=$surface{carbon}; $InfoHash{ATS_surface_area_base_on}=$surface{baseon}; $DB->save_jobinfo( -jobid=>$JOB_ID, -jobcategory=>'org', -jobinfohash=>\%InfoHash); my $Check_gold_size= sprintf('%-15s',' ').sprintf('%-15s','Exposed').sprintf('%-15s','Gold').sprintf('%-15s','Sel.Ref (sqin)')."\n"; my $Check_gold_state = 0; my($step_size_x,$step_size_y); if ($Job =~ /^coc/i ){ my $tmpm1=$InfoHash{TL_gold_area_front}*15.500031000062; my $tmpm2=$InfoHash{TL_gold_area_back}*15.500031000062; my $tmpm3=$InfoHash{TL_exposed_area_front}*15.500031000062; my $tmpm4=$InfoHash{TL_exposed_area_back}*15.500031000062; $tmpm1=sprintf "%.4f",$tmpm1; $tmpm2=sprintf "%.4f",$tmpm2; $tmpm3=sprintf "%.4f",$tmpm3; $tmpm4=sprintf "%.4f",$tmpm4; if ($tmpm1 > 2.5 or $tmpm2 > 2.5 and $InfoHash{selection_reference_type_front} =~/^gold$/i and $InfoHash{selection_reference_type_back} =~/^gold$/i){ $Check_gold_state=1; } $Check_gold_size.= sprintf('%-15s','front').sprintf('%-15s',$tmpm3).sprintf('%-15s',$tmpm1).sprintf('%-15s',$InfoHash{selection_reference_type_front})."\n"; $Check_gold_size.= sprintf('%-15s','back').sprintf('%-15s',$tmpm4).sprintf('%-15s',$tmpm2).sprintf('%-15s',$InfoHash{selection_reference_type_back})."\n"; my $tmpmm="Base on :$InfoHash{surface_area_base_on}"; $Check_gold_size.= sprintf('%-15s',$tmpmm)."\n"; } unless ($GEN->{STATUS}){ return $Return; } else{ $GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}})); addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}})); return 'Error'; } } catch Error::Simple with { my $error = encode("utf8",shift); $GUI->msgbox(-icon=>'error',-text=>$error); return 'Error'; } finally{ }; sub _deleteLayer{ my %par = @_; foreach my $layer(@{$par{layer}}){ $GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer)); } $GEN->openStep(job=>$Job,name=>$par{step}) if ($par{step}); } sub CreateGoldLayer{ my ($ep,$sm,$ref,$refas,$drill,$gold,$osp) = @_; $GEN->COM('chklist_single',action=>'ats_dfm_sit',show=>'no'); $GEN->COM('chklist_cupd',chklist=>'ats_dfm_sit',nact=>1, params=>"((pp_outlayer=$ep)(pp_smlayer=$sm)(pp_refmode=$refas)(pp_reflayer=$ref)(pp_drilllayer=$drill)(pp_goldlayer=$gold)(pp_osplayer=$osp))", mode=>'regular'); $GEN->COM('chklist_run',chklist=>'ats_dfm_sit', nact=>1,area=>'global'); `touch /tmp/script.flag` if( ! (-e "/tmp/script.flag")); } sub INCAM_CreateGoldLayer{ my ($ep,$sm,$ref,$refas,$drill,$gold,$osp,$subStep) = @_; my $tmp_sm = 'script_sm'; my $tmp_ep = 'script_ep'; my $tmp_sm_backup = 'ref_expgold+exposp'; $GEN->units(type=>'mm'); _deleteLayer(step=>$subStep,layer=>[$tmp_sm,$tmp_ep,$tmp_sm_backup]); $GEN->workLayer(name=>$sm,display_number=>1,clear_before=>'yes'); $GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm); $GEN->workLayer(name=>$tmp_sm,display_number=>1,clear_before=>'yes'); $GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y"); $GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm_backup); $GEN->workLayer(name=>$ep,display_number=>1,clear_before=>'yes'); $GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_ep); $GEN->workLayer(name=>$tmp_ep,display_number=>1,clear_before=>'yes'); $GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y"); $GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm,invert=>'yes',size=>2); $GEN->workLayer(name=>$tmp_sm,display_number=>1,clear_before=>'yes'); $GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y"); $GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm_backup,invert=>'yes',size=>2); $GEN->workLayer(name=>$tmp_sm_backup,display_number=>1,clear_before=>'yes'); $GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y"); $GEN->selRefFeat( layers=>$ref, use=>'filter', mode=>'touch', f_types=>'surface\;pad\;text\;line\;arc', polarity=>'positive', ); if ( $GEN->getSelectCount() > 0 ){ if ($refas eq 'GOLD'){ $GEN->selMoveOther(target_layer=>$gold) ; $GEN->selMoveOther(target_layer=>$osp) ; }elsif($refas eq 'OSP'){ $GEN->selMoveOther(target_layer=>$osp) ; $GEN->selMoveOther(target_layer=>$gold) ; } } _deleteLayer(layer=>[$tmp_sm,$tmp_ep,$tmp_sm_backup]); $GEN->units(type=>'inch'); `touch /tmp/script.flag` if( ! (-e "/tmp/script.flag")); } sub expcopperArea { my ($job,$step,$thick,$layer1,$mask1,$layer2,$mask2,$drill) = @_; $GEN->openStep(job=>$Job,name=>$Step); $GEN->units(type=>'mm'); my $reprot; $reprot =$GEN->copperArea( 'layer1'=>$layer1?$layer1:'', 'layer2'=>$layer2?$layer2:'', 'drills'=>$drill?'yes':'no', 'consider_rout'=>'no', 'drills_source'=>'matrix', 'drills_list'=>$drill, 'thickness'=>$thick, 'resolution_value'=>10, 'x_boxes'=>3, 'y_boxes'=>3, 'area'=>'no', 'dist_map'=>'yes' ); $reprot = sprintf "%0.4f",$reprot->{area}/10000; return $reprot; } sub exposedArea { # ($thick,$layerinfo->{Front},'qec_goldfr',$layerinfo->{Back},'ats_empty',$layerinfo->{Drill}) if ($layerinfo->{Goldfr} and $layerinfo->{Reffr}); # ($thick,$layerinfo->{Front},'ats_empty',$layerinfo->{Back},'qec_goldba',$layerinfo->{Drill}) if ($layerinfo->{Goldba} and $layerinfo->{Refba}); my ($job,$step,$thick,$layer1,$mask1,$layer2,$mask2,$drill) = @_; $GEN->openStep(job=>$Job,name=>$Step); $GEN->units(type=>'mm'); my $reprot; $reprot = $GEN->exposedArea( 'layer1'=>$layer1?$layer1:'', 'mask1'=>$mask1?$mask1:'', 'layer2'=>$layer2?$layer2:'', 'mask2'=>$mask2?$mask2:'', 'drills'=>$drill?'yes':'no', 'consider_rout'=>'no', 'drills_source'=>'matrix', 'drills_list'=>$drill, 'thickness'=>$thick, 'resolution_value'=>10, 'x_boxes'=>3, 'y_boxes'=>3, 'area'=>'no', 'dist_map'=>'yes', ); $reprot = sprintf "%0.4f",$reprot->{area}/10000; return $reprot; } sub exposed_pad_size{ my $Job=shift; my $Step= shift; my $layer= shift; my $ref_layer=shift; my $base_on =shift; $GEN->openStep(job=>$Job,name=>$Step); $GEN->units(type=>'mm'); $GEN->workLayer(name=>$ref_layer,display_number=>1,clear_before=>'yes'); $GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y"); $GEN->COM("sel_clean_surface,accuracy=10,clean_size=75,clean_mode=x_or_y,max_fold_len=0"); $GEN->COM("sel_clean_surface,accuracy=2.54,clean_size=75,clean_mode=x_and_y,max_fold_len=0"); $GEN->copyLayer(source_job=>$Job, source_step=>$Step, source_layer=>$layer, dest_layer=>'copper_cal', ); my $copper_a =$GEN->copperArea( 'layer1'=>'copper_cal', 'layer2'=>'', 'drills'=>'no', 'consider_rout'=>'no', 'drills_source'=>'matrix', 'drills_list'=>'', 'thickness'=>'1', 'resolution_value'=>10, 'x_boxes'=>3, 'y_boxes'=>3, 'area'=>'no', 'dist_map'=>'yes' ); $copper_a = sprintf "%0.4f",$copper_a->{area}; my $f_all =$GEN->copperArea( 'layer1'=>$ref_layer, 'layer2'=>'', 'drills'=>'no', 'consider_rout'=>'no', 'drills_source'=>'matrix', 'drills_list'=>'', 'thickness'=>'1', 'resolution_value'=>10, 'x_boxes'=>3, 'y_boxes'=>3, 'area'=>'no', 'dist_map'=>'yes' ); $f_all = sprintf "%0.4f",$f_all->{area}; my $percent =12; my $all_percent = 45;# my $all_ratio = sprintf "%0.3f",($f_all/$copper_a)*100; my %guard_warning1=(); my ($condition1,$condition2); my @guard_warning1; if ($all_ratio >= $all_percent) { $condition2 ='ok'; push @guard_warning1,"All exposed pad area: ${f_all} mm2 ; Ratio: $all_ratio%"; } my @features1 = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>$ref_layer,units=>'mm',surface=>1); my @guard_warning=(); my (%max1,%max2); foreach my $surface (@features1){ my $f =$ATS_GenMath->Polygon_Calculate_getArea(polygon=>\@{$surface->{feats}},tol=>'0.1',mode=> 'surface'); $f = sprintf "%0.4f",$f; next if ($f==0); my $ratio=sprintf "%0.3f",($f/$copper_a)*100; my $ratio1=sprintf "%0.3f",($f/$f_all)*100; $max1{$f}=$ratio; $max2{$f}=$ratio1; if ($ratio >= $percent ) { my $Center = $ATS_GenMath->Calculate_Surface_Center(polygon=>\@{$surface->{feats}},precision=>'1',units=>'mm'); push @guard_warning ,"Exposed Pad Size all Area :${f_all}mm2 ,Single Area:${f}mm2;Ratio:[$ratio%].Pad Point :X:$Center->{1}{x}mm,Y:$Center->{1}{y}mm
"; $condition1= 'ok'; } } #$GUI->debug("$condition1 $condition2 $all_ratio"); if ($condition1 eq 'ok' or $condition2 eq 'ok'){ my ($max1) = sort {$b <=> $a} %max1; $guard_warning1{1}="The Max exposed pad area: ${max1} mm2 ; Ratio: $max1{$max1}%"; $guard_warning1{2}="All exposed pad area: ${f_all} mm2 ; Ratio: $all_ratio%"; if (@guard_warning1) { push @{$guard_warning1{3}},@guard_warning1; } push @{$guard_warning1{3}},@guard_warning if ($condition1 eq 'ok'); } return \%guard_warning1; } sub exposed_pad_size1{ my $Job=shift; my $Step= shift; my $layer= shift; my $ref_layer=shift; my $base_on =shift; my $f_all; $GEN->openStep(job=>$Job,name=>$Step); $GEN->units(type=>'mm'); $GEN->workLayer(name=>$ref_layer,display_number=>1,clear_before=>'yes'); $GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y"); $GEN->COM("sel_clean_surface,accuracy=10,clean_size=75,clean_mode=x_or_y,max_fold_len=0"); $f_all =$GEN->copperArea( 'layer1'=>$ref_layer, 'layer2'=>'', 'drills'=>'no', 'consider_rout'=>'no', 'drills_source'=>'matrix', 'drills_list'=>'', 'thickness'=>'1', 'resolution_value'=>10, 'x_boxes'=>3, 'y_boxes'=>3, 'area'=>'no', 'dist_map'=>'yes' ); $f_all = sprintf "%0.4f",$f_all->{area}; my @features1 = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>$ref_layer,units=>'mm',surface=>1); my $guard_Area= 400;#mm my $percent =35; my @guard_warning=(); foreach my $surface (@features1){ my $f =$ATS_GenMath->Polygon_Calculate_getArea(polygon=>\@{$surface->{feats}},tol=>'0.1',mode=> 'surface'); $f = sprintf "%0.4f",$f; next if ($f==0); my $ratio=sprintf "%0.3f",($f/$f_all)*100; if ($f >$guard_Area or $ratio > $percent) { my $Center = $ATS_GenMath->Calculate_Surface_Center(polygon=>\@{$surface->{feats}},precision=>'1',units=>'mm'); push @guard_warning ,"Exposed Pad Size all Area :${f_all}mm2 ,Single Area:${f}mm2;Ratio:[$ratio%].Pad Point :X:$Center->{1}{x}mm,Y:$Center->{1}{y}mm"; } } return \@guard_warning; } sub polygon_surface{ my $Job=shift; my $Step= shift; my $layer= shift; my $options = shift;#select my $units= shift; my $cshfile; $cshfile=$GEN->INFO('entity_type'=>'layer', 'entity_path'=>"$Job/$Step/$layer", 'data_type'=>'FEATURES', 'parse'=>'no', units=>$units, ) if (!$options); $cshfile=$GEN->INFO('entity_type'=>'layer', 'entity_path'=>"$Job/$Step/$layer", 'data_type'=>'FEATURES', 'parse'=>'no', options=>$options, units=>$units, ) if ($options); open(CSHFILE,"$cshfile"); my @polygon=; close(CSHFILE); shift @polygon; return @polygon; } sub mail_sand_task { my %par = @_; ## subject ##body ## title my $mailinfo=$DB->select_hash(-table=>'ats_mail_sand_task',-where=>{mail_title=>$par{title}}); if ($mailinfo->{status} eq 'Start'){ my $mail_to=$mailinfo->{mail_to}; my $mail_cc=$mailinfo->{mail_cc}; if ($mail_to=~/^sub/){ $mail_to=eval($mail_to); $mail_to= $mail_to->(job_id=>$JOB_ID); } else{ $mail_to=eval($mail_to) if ($mail_to=~/^\$/); } if ($mail_cc=~/^sub/){ $mail_cc=eval($mail_cc); $mail_cc= $mail_cc->(job_id=>$JOB_ID); } else{ $mail_cc=eval($mail_cc) if ($mail_cc=~/^\$/); } my @to = split(/\;|\:|\,|\n/,$mail_to); foreach my $it (@to){ $it =~ s/(^\s+|\s+$)//g; } $par{-to} = \@to; #$data{cc} =~ s/\s+//g; my @cc = split(/\;|\:|\,|\n/,$mail_cc); foreach my $it (@cc){ $it =~ s/(^\s+|\s+$)//g; } $par{-cc} = \@cc; $par{cc_user}=''; $par{group}=''; #$GUI->debug("@to m @cc "); my $subject=$par{subject}; my $body = $par{body}; my $mail_version = $DB->select_value( -table=>'ats_auto_mail_record', -field=>'max(mail_version)', -where=>"job_id = $JOB_ID and mail_title = '$par{title}'", ); $mail_version = 0 unless ($mail_version); $mail_version++; my $resart_mail= 'yes'; if ($mail_version > 1 and $par{sand_mode} ne 'always' ){ my $tmp_v=$mail_version-1; my $mail_subject = $DB->select_value( -table=>'ats_auto_mail_record', -field=>'mail_subject', -where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v", ); my $mail_body = $DB->select_value( -table=>'ats_auto_mail_record', -field=>'mail_content', -where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v", ); if ($mail_subject eq $subject){ $resart_mail='no'; if ($mail_body ne $body){ $resart_mail='yes'; } } elsif ($mail_body ne $body){ $resart_mail='yes'; } } #$GUI->debug(dump\%par); #exit; if ($resart_mail eq 'yes'){ Top::MailSender->send_mail(%par); my ($content,$att); if (ref $par{body} eq 'ARRAY') { ($content,$att) = @{$par{body}}; } else { $content = $par{body}; } if ($att) { my @att = @{$att}; if (@att) { $att = join(',',@att); $att = '' unless ($att); }else { $att = ''; } } else { $att = ''; } $DB->insert( -table=>'ats_auto_mail_record', -data=>{ job_id => $JOB_ID, mail_from=>$APP->{USER_NAME}, mail_to=>$mail_to, mail_cc=>$mail_cc, mail_subject=>$par{subject}, mail_title=>$par{title}, mail_content=>$content, mail_attachment=>$att, mail_version=>$mail_version, } ); } } } sub calc_area{ my $output_layer=shift; $GEN->COM('chklist_single,action=ats_analysis_calc_area,show=no'); $GEN->COM("chklist_cupd,chklist=ats_analysis_calc_area,nact=1,params=((pp_layer=.affected)(pp_output_layer=$output_layer)(pp_flatten_mode=Yes)),mode=regular"); $GEN->COM('chklist_run,chklist=ats_analysis_calc_area,nact=1,area=profile'); } sub INCAM_CreateMetalLayer{ my %par = @_; my $outputLayer=$par{outputLayer}; my $ep = $par{ep}; my $sm = $par{sm}; my $tmp_ep = "script_".$ep; my $tmp_sm = "script_".$sm; my $step = $par{step}; $GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$ep,dest_layer=>$tmp_ep); $GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$sm,dest_layer=>$tmp_sm); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$tmp_ep,$tmp_sm],clear_before=>'yes'); $GEN->selContourize(); $GEN->COM("sel_feat2outline,width=0,location=on_edge,offset=0,polarity=as_feature,keep_original=no,text2limit=no"); $GEN->COM("sel_cut_data,det_tol=1,con_tol=1,rad_tol=0,ignore_width=yes,filter_overlaps=no,delete_doubles=no,use_order=yes,ignore_holes=none,start_positive=yes,polarity_of_touching=same,contourize=yes,simplify=yes,resize_thick_lines=no"); $GEN->COM("rv_tab_view_results_enabled,report=cut_data_rep,is_enabled=no,serial_num=-1,all_count=-1"); $GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$tmp_sm,dest_layer=>$outputLayer); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$tmp_sm],clear_before=>'yes'); $GEN->COM("sel_resize,size=0.5,corner_ctl=no"); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$tmp_ep],clear_before=>'yes'); $GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm,invert=>'yes',size=>0.5); $GEN->workLayer(name=>$tmp_sm,display_number=>1,clear_before=>'yes'); $GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y"); $GEN->selCopyOther(dest=>'layer_name',target_layer=>$outputLayer,invert=>'yes',size=>0.5); $GEN->workLayer(name=>$outputLayer,display_number=>1,clear_before=>'yes'); $GEN->selContourize(); _deleteLayer(job=>$Job,step=>$step,layer=>[$tmp_ep,$tmp_sm]); }