=head NAME: DESCRIPTION: Signal线路掏铜 PARAMETER: [ { name : 'step_filter', type : 'LineEdit', title : 'step过滤', pack : {row:0,column:1}, property:{tool_tip:'选择step时候的过滤器'}, }, { name : 'opt_item', title : '优化类型', type : 'ComboBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'inner',text:'内层'}, {name:'outer',text:'外层'}, ] }, }, { name : 'drl_layer', type : 'LineEdit', title : '钻孔层', pack : {row:0,column:1}, property:{tool_tip:'钻孔层'}, }, { name : 'outline_layer', type : 'LineEdit', title : '外形层', pack : {row:0,column:1}, property:{tool_tip:'外形层'}, }, { name : 'ignore_attributes', type : 'LineEdit', title : '忽略的铜皮属性', pack : {row:0,column:1}, property:{tool_tip:'忽略的铜皮属性'}, }, { name : 'fill_data', type : 'LineEdit', title : '去铜丝参数', pack : {row:0,column:1}, property:{tool_tip:'去铜丝参数'}, }, { name : 'shave_cu_rule', title : '削铜参数规则', type : 'CodeEdit', property : {min_row_count: 5, tool_tip : ''}, }, { name : 'bak_layer_suf', type : 'LineEdit', title : '备份层后缀', pack : {row:0,column:1}, property:{tool_tip:'去铜丝参数'}, } ] VERSION_HISTORY: V1.00 2020-10-30 Super 1.新版 V1.01 2020-11-5 Super 1.分内外层优化 HELP:

功能简介

DFM优化


参数配置

● 无

注意事项

● 无


=cut use strict; use utf8; use Data::Dump 'dump'; my ($Job,$Step)=($JOB,undef); my $Report = 'done'; my @work_layers; $PAR->{fill_data} = $PAR->{fill_data} ? $PAR->{fill_data} : 1; $PAR->{bak_layer_suf} = $PAR->{bak_layer_suf} ? $PAR->{bak_layer_suf} : '++--bak++'; try { unless($PAR->{drl_layer}){ $GUI->msgbox(-icon=>'error',-text=>"请先设置钻孔层参数!"); return 'Error'; } unless($PAR->{outline_layer}){ $GUI->msgbox(-icon=>'error',-text=>"请先设置外形层参数!"); return 'Error'; } unless($PAR->{opt_item}){ $GUI->msgbox(-icon=>'error',-text=>"请先设置优化类型!"); return 'Error'; } ###检查Genesis料号是否存在并打开 show_loading("检查${Job}是否存在..",0,position=>'n'); if (! $GEN->isJobExists(job=>$Job) ){ $GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!"); return 'Error'; } update_loading("正在打开料号 ${Job} ...",0,position=>'n'); $GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job)); my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash'); my @steps = $GEN->getStepList(job=>$Job); if ( @steps == 0 ) { $GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!'); return 'Error'; } elsif (@steps != 1){ my $srep_filter = $PAR->{step_filter} ? $PAR->{step_filter} : '.*'; my @tmp_steps = grep(/$srep_filter/,@steps); if ( @tmp_steps == 0 ) { $GUI->msgbox(-icon=>'error',-text=>'在料号中没有过滤器中的step存在,你将退出!'); return 'Error'; } elsif ( @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]; } ## update_loading("过滤层别...",0,position=>'n'); @work_layers = get_work_layer(); return 'Cancel' if grep /^Cancel$/,@work_layers; ###打开step $GEN->openStep(job=>$Job,name=>$Step); $GEN->clearLayers(); $GEN->affectedLayer( mode=>'all',affected=>'no' ); $GEN->COM( "sel_options,clear_mode=clear_after,display_mode=all_layers,area_inout=inside,area_select=select,select_mode=standard,area_touching_mode=exclude"); $GEN->units(type=>'inch'); $GEN->zoomHome(); update_loading("确认削铜参数...",0,position=>'n'); my $file = $GEN->getJobPath(job=>$Job).'/user/'.'shave_cu_info'; my (%rows,$n); foreach my $layer (@work_layers){ $n++; $rows{$layer}{sequence} = $n; $rows{$layer}{layer} = $layer; $rows{$layer}{cu} = ''; $rows{$layer}{pad_cu} = 0; $rows{$layer}{line_cu} = 0; $rows{$layer}{smd_cu} = 0; $rows{$layer}{bga_cu} = 0; $rows{$layer}{np_cu} = 0; $rows{$layer}{drl_cu} = 0; $rows{$layer}{cu_cu} = 0; $rows{$layer}{outline_cu} = 0; } my $ShowForm = $GUI->show_tableform ( -title=>'请确认参数', -defaultsize=>[900,500], -rows => \%rows, -showcheck => 1,-gen => $GEN, -buttons=>[ { response=>'help', stock=>'载入上次填入值', command=>sub{ my %par = @_; $par{formpanel}->load_data(do($file)) if -f $file; } }, {response=>'ok',stock=>'gtk-ok'}, {response=>'cancel',stock=>'gtk-cancel'}, ], -columns => [ { column_name=>'layer', label=>'层名称', width=>70, type=>'label', }, { column_name=>'cu', label=>'铜箔厚度', type=>'enum', width=>70, must_field=>1, property=>{ tl_field=>[name=>'scalar',display_name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>'1/4',display_name=>'1/4oz'}, {name=>'1/3',display_name=>'1/3oz'}, {name=>'1/2',display_name=>'1/2oz'}, {name=>'1',display_name=>'1oz'}, {name=>'1.5',display_name=>'1.5oz'}, {name=>'2',display_name=>'2oz'}, ] }, validate_func=>sub{ my %par = @_; my $cu = $par{formpanel}->get_value($par{row},'cu'); my ($pad_cu,$line_cu,$smd_cu,$bga_cu,$drl_cu,$np_cu,$cu_cu,$outline_cu); unless($PAR->{shave_cu_rule}){ ($pad_cu,$line_cu,$smd_cu,$bga_cu,$drl_cu,$np_cu,$cu_cu,$outline_cu) = (0,0,0,0,0,0,0,0); }else{ ($pad_cu,$line_cu,$smd_cu,$bga_cu,$drl_cu,$np_cu,$cu_cu,$outline_cu) = eval($PAR->{shave_cu_rule})->($cu); } $par{formpanel}->set_value($par{row},'pad_cu',$pad_cu) if ( $par{mode} eq 'keyin' ); $par{formpanel}->set_value($par{row},'line_cu',$line_cu) if ( $par{mode} eq 'keyin' ); $par{formpanel}->set_value($par{row},'smd_cu',$smd_cu) if ( $par{mode} eq 'keyin' ); $par{formpanel}->set_value($par{row},'bga_cu',$bga_cu) if ( $par{mode} eq 'keyin' ); $par{formpanel}->set_value($par{row},'drl_cu',$drl_cu) if ( $par{mode} eq 'keyin' ); $par{formpanel}->set_value($par{row},'np_cu',$np_cu) if ( $par{mode} eq 'keyin' ); $par{formpanel}->set_value($par{row},'cu_cu',$cu_cu) if ( $par{mode} eq 'keyin' ); $par{formpanel}->set_value($par{row},'outline_cu',$outline_cu) if ( $par{mode} eq 'keyin' ); return {}; } }, { column_name=>'pad_cu', label=>'PAD到铜', width=>80, type=>'number', units=>'mil', }, { column_name=>'line_cu', label=>'线到铜', width=>80, type=>'number', units=>'mil', }, { column_name=>'smd_cu', label=>'SMD到铜', width=>80, type=>'number', units=>'mil', validate_func=>sub{ my %par = @_; my $layer = $par{formpanel}->get_value($par{row},'layer'); if($matrix{$layer}{tl_type} eq 'inner'){ $par{formpanel}->set_value($par{row},'smd_cu',0)unless( $par{mode} eq 'save' ); $par{formpanel}->get_widget($par{row},'smd_cu')->set_sensitive(0); } return {}; } }, { column_name=>'bga_cu', label=>'BGA到铜', width=>80, type=>'number', units=>'mil', validate_func=>sub{ my %par = @_; my $layer = $par{formpanel}->get_value($par{row},'layer'); if($matrix{$layer}{tl_type} eq 'inner'){ $par{formpanel}->set_value($par{row},'bga_cu',0)unless( $par{mode} eq 'save' ); $par{formpanel}->get_widget($par{row},'bga_cu')->set_sensitive(0); } return {}; } }, { column_name=>'drl_cu', label=>'孔到铜', width=>80, type=>'number', units=>'mil', validate_func=>sub{ my %par = @_; my $layer = $par{formpanel}->get_value($par{row},'layer'); if($matrix{$layer}{tl_type} eq 'outer'){ $par{formpanel}->set_value($par{row},'drl_cu',0)unless( $par{mode} eq 'save' ); $par{formpanel}->get_widget($par{row},'drl_cu')->set_sensitive(0); } return {}; } }, { column_name=>'np_cu', label=>'NP孔到铜', width=>80, type=>'number', units=>'mil', }, { column_name=>'cu_cu', label=>'铜到铜', width=>80, type=>'number', units=>'mil', }, { column_name=>'outline_cu', label=>'外形到铜', width=>90, type=>'number', units=>'mil', }, ] ); return 'Cancel' unless $ShowForm; open(my $fh,'>',$file); print $fh dump($ShowForm); close $fh; $GEN->COM("disp_off"); foreach my $layer (@work_layers){ my @del_layers; $GEN->affectedLayer(affected=>'yes',layer=>$layer,clear_before=>'yes'); $GEN->selectByFilter(polarity=>'negative',profile=>'all'); if ( $GEN->getSelectCount() > 0 ){ $GEN->COM('sel_clear_feat'); $GUI->msgbox(-icon=>'error',-text=>$layer.'层资料中有负片,请先处理好!'); return 'Error'; } my $bak_layer = $layer.($PAR->{bak_layer_suf}); #备份 $GEN->createLayer(job=>$Job,layer=>$bak_layer,context=>'misc',type=>'document',delete_exists=>'yes'); $GEN->selCopyOther(target_layer=>$bak_layer,invert=>'no'); #铜皮层 my $cu_tmp_layer = $layer.'+-+tmp+cu++'; $GEN->createLayer(job=>$Job,layer=>$cu_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes'); $GEN->selectByFilter(feat_types=>'surface',polarity=>'positive',profile=>'all'); if(defined($PAR->{ignore_attributes})){ $GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>$PAR->{ignore_attributes}}],operation=>'unselect'); } if ( $GEN->getSelectCount() > 0 ){ $GEN->selMoveOther(target_layer=>$cu_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0); push @del_layers,$cu_tmp_layer; }else{ next; } #SMD层 my $smd_tmp_layer = $layer.'+-+tmp+smd++'; if($ShowForm->{$layer}{smd_cu} > 0){ $GEN->createLayer(job=>$Job,layer=>$smd_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes'); $GEN->selectByFilter(feat_types=>'pad',attribute=>[{attribute=>'.smd'}],polarity=>'positive',profile=>'all'); $GEN->selectByFilter(attribute=>[{attribute=>'.bga'}],operation=>'unselect'); $GEN->selMoveOther(target_layer=>$smd_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 ); push @del_layers,$smd_tmp_layer; } #BGA层 my $bga_tmp_layer = $layer.'+-+tmp+bga++'; if($ShowForm->{$layer}{bga_cu} > 0){ $GEN->createLayer(job=>$Job,layer=>$bga_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes'); $GEN->selectByFilter(feat_types=>'pad',attribute=>[{attribute=>'.bga'}],polarity=>'positive',profile=>'all'); $GEN->selMoveOther(target_layer=>$bga_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 ); push @del_layers,$bga_tmp_layer; } #PAD层 my $pad_tmp_layer = $layer.'+-+tmp+pad++'; if($ShowForm->{$layer}{pad_cu} > 0){ $GEN->createLayer(job=>$Job,layer=>$pad_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes'); $GEN->selectByFilter(feat_types=>'pad',polarity=>'positive',profile=>'all'); $GEN->selMoveOther(target_layer=>$pad_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 ); push @del_layers,$pad_tmp_layer; } #line层 my $line_tmp_layer = $layer.'+-+tmp+line++'; if($ShowForm->{$layer}{line_cu} > 0){ $GEN->createLayer(job=>$Job,layer=>$line_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes'); $GEN->selectByFilter(feat_types=>'line\;arc',polarity=>'positive',profile=>'all'); $GEN->selMoveOther(target_layer=>$line_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 ); push @del_layers,$line_tmp_layer; } #掏铜 my %feat_hist = $GEN->getLayerFeatHist(job=>$Job,step=>$Step,layer=>$cu_tmp_layer); my $tmp_layer = 'tl++tmp+cu+++'; $GEN->createLayer(job=>$Job,layer=>$tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes'); for(my $index = 1;$index <= $feat_hist{total};$index++){ update_loading('一共'.($feat_hist{total}).'铜皮'.' '.'第'.$index.'块优化中...',0,position=>'n'); $GEN->affectedLayer(affected=>'yes',layer=>$cu_tmp_layer,clear_before=>'yes'); $GEN->COM('sel_layer_feat',operation=>'select',layer=>$cu_tmp_layer,index=>$index); $GEN->selMoveOther(target_layer=>$tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0); if($ShowForm->{$layer}{smd_cu} > 0){ $GEN->affectedLayer(affected=>'yes',layer=>$smd_tmp_layer,clear_before=>'yes'); $GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint'); $GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{smd_cu}) if ( $GEN->getSelectCount() > 0 ); } if($ShowForm->{$layer}{bga_cu} > 0){ $GEN->affectedLayer(affected=>'yes',layer=>$bga_tmp_layer,clear_before=>'yes'); $GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint'); $GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{bga_cu}) if ( $GEN->getSelectCount() > 0 ); } if($ShowForm->{$layer}{pad_cu} > 0){ $GEN->affectedLayer(affected=>'yes',layer=>$pad_tmp_layer,clear_before=>'yes'); $GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint'); $GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{pad_cu}) if ( $GEN->getSelectCount() > 0 ); } if($ShowForm->{$layer}{line_cu} > 0){ $GEN->affectedLayer(affected=>'yes',layer=>$line_tmp_layer,clear_before=>'yes'); $GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint'); $GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{line_cu}) if ( $GEN->getSelectCount() > 0 ); } #NP孔到铜 $GEN->affectedLayer(affected=>'yes',layer=>$PAR->{drl_layer},clear_before=>'yes'); $GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'non_plated'}]); $GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{np_cu}) if ( $GEN->getSelectCount() > 0 ); if($ShowForm->{$layer}{drl_cu} > 0){ $GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint'); $GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{drl_cu}) if ( $GEN->getSelectCount() > 0 ); } #外形到铜 $GEN->affectedLayer(affected=>'yes',layer=>$PAR->{outline_cu},clear_before=>'yes'); $GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{outline_cu}) if ( $GEN->getSelectCount() > 0 ); #铜到铜 $GEN->affectedLayer(affected=>'yes',layer=>$cu_tmp_layer,clear_before=>'yes'); $GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint'); $GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>$ShowForm->{$layer}{cu_cu}) if ( $GEN->getSelectCount() > 0 ); #转铜,除细丝 $GEN->affectedLayer(affected=>'yes',layer=>$tmp_layer,clear_before=>'yes'); $GEN->selContourize(); if($PAR->{fill_data}){ $GEN->selFill(solid_type=>'fill',min_brush=>$PAR->{fill_data}); $GEN->selContourize(); } $GEN->selMoveOther(target_layer=>$layer,invert=>'no',dx=>0,dy=>0,size=>0); $GEN->deleteLayer(job=>$Job,layer=>$tmp_layer); } #与铜皮相连的PAD处理 #补铜桥部分 #物件还原 foreach my $tmp (@del_layers){ if($GEN->isLayerExists(job=>$Job,layer=>$tmp) and ! $GEN->isLayerEmpty(job=>$Job,step=>$Step,layer=>$tmp)){ $GEN->affectedLayer(affected=>'yes',layer=>$tmp,clear_before=>'yes'); $GEN->selMoveOther(target_layer=>$layer,invert=>'no',dx=>0,dy=>0,size=>0); } $GEN->deleteLayer(job=>$Job,layer=>$tmp); } } ###output and return status, if genesis error, it will output genesis error command unless ($GEN->{STATUS}){ return $Report; } 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 = shift; $GUI->msgbox(-icon=>'error',-text=>$error); return 'Error'; } finally{ $GEN->clearLayers(); $GEN->affectedLayer( mode=>'all',affected=>'no' ); $GEN->COM("disp_on"); }; sub isChecklistExist{ my %par = @_ ; my @chklists = $GEN->getChecklist(job=>$par{job},step=>$par{step}); if(grep /^$par{checkklist}$/,@chklists){ return 1; } else{ return 0; } } =head 选择线路层 =cut sub get_work_layer{ # 获取工作层 my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash'); foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) { if(defined($matrix{$layer}{context}) and $matrix{$layer}{context} eq 'board' ){ if(defined($matrix{$layer}{layer_type}) and $matrix{$layer}{layer_type} eq 'signal' and $matrix{$layer}{tl_type} eq $PAR->{opt_item}){ push @work_layers,$layer; } } } my %tmp_matrix; foreach my $layer (@work_layers) { $tmp_matrix{$layer} = $matrix{$layer}; } if (@work_layers > 1) { @work_layers = $GUI->select_layer( -title=>'请选择工作层别', -layermatrix=>\%tmp_matrix, -selectmode => 'multiple');#single return 'Cancel' unless(@work_layers); } else { @work_layers = @work_layers; } return @work_layers; } #掏铜参数 # sub{ # my $cu = shift; # my $data; # @{$data->{0.5}}=(1,2,3,4,5,1,6); # @{$data->{1}}=(2,3,4,5,6,2,7); # if(defined($data->{$cu})){ # return @{$data->{$cu}}; # }else{ # return (0,0,0,0,0,0); # } # }