KiCad PCB EDA Suite
board_netlist_updater.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
10  * Copyright (C) 2015 CERN
11  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
12  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
13  *
14  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, you may find one here:
28  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
29  * or you may search the http://www.gnu.org website for the version 2 license,
30  * or you may write to the Free Software Foundation, Inc.,
31  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
32  */
33 
34 
35 #include <common.h> // for PAGE_INFO
36 
37 #include <class_board.h>
38 #include <netinfo.h>
39 #include <class_module.h>
40 #include <class_pad.h>
41 #include <class_track.h>
42 #include <class_zone.h>
43 #include <kicad_string.h>
44 
45 #include "pcb_netlist.h"
47 #include <reporter.h>
48 
49 #include "board_netlist_updater.h"
50 
51 #include <pcb_edit_frame.h>
52 
53 
55  m_frame( aFrame ),
56  m_commit( aFrame ),
57  m_board( aBoard )
58 {
60 
61  m_deleteSinglePadNets = true;
63  m_isDryRun = false;
64  m_replaceFootprints = true;
65  m_lookupByTimestamp = false;
66  m_warnForNoNetPads = false;
67 
68  m_warningCount = 0;
69  m_errorCount = 0;
71 }
72 
73 
75 {
76 }
77 
78 
79 // These functions allow inspection of pad nets during dry runs by keeping a cache of
80 // current pad netnames indexed by pad.
81 
82 void BOARD_NETLIST_UPDATER::cacheNetname( D_PAD* aPad, const wxString& aNetname )
83 {
84  m_padNets[ aPad ] = aNetname;
85 }
86 
87 
89 {
90  if( m_isDryRun && m_padNets.count( aPad ) )
91  return m_padNets[ aPad ];
92  else
93  return aPad->GetNetname();
94 }
95 
96 
97 void BOARD_NETLIST_UPDATER::cachePinFunction( D_PAD* aPad, const wxString& aPinFunction )
98 {
99  m_padPinFunctions[ aPad ] = aPinFunction;
100 }
101 
102 
104 {
105  if( m_isDryRun && m_padPinFunctions.count( aPad ) )
106  return m_padPinFunctions[ aPad ];
107  else
108  return aPad->GetPinFunction();
109 }
110 
111 
113 {
114  wxPoint bestPosition;
115 
116  if( !m_board->IsEmpty() )
117  {
118  // Position new components below any existing board features.
120 
121  if( bbox.GetWidth() || bbox.GetHeight() )
122  {
123  bestPosition.x = bbox.Centre().x;
124  bestPosition.y = bbox.GetBottom() + Millimeter2iu( 10 );
125  }
126  }
127  else
128  {
129  // Position new components in the center of the page when the board is empty.
130  wxSize pageSize = m_board->GetPageSettings().GetSizeIU();
131 
132  bestPosition.x = pageSize.GetWidth() / 2;
133  bestPosition.y = pageSize.GetHeight() / 2;
134  }
135 
136  return bestPosition;
137 }
138 
139 
141 {
142  wxString msg;
143 
144  if( aComponent->GetFPID().empty() )
145  {
146  msg.Printf( _( "Cannot add %s (no footprint assigned)." ),
147  aComponent->GetReference(),
148  aComponent->GetFPID().Format().wx_str() );
150  ++m_errorCount;
151  return nullptr;
152  }
153 
154  MODULE* footprint = m_frame->LoadFootprint( aComponent->GetFPID() );
155 
156  if( footprint == nullptr )
157  {
158  msg.Printf( _( "Cannot add %s (footprint \"%s\" not found)." ),
159  aComponent->GetReference(),
160  aComponent->GetFPID().Format().wx_str() );
162  ++m_errorCount;
163  return nullptr;
164  }
165 
166  msg.Printf( _( "Add %s (footprint \"%s\")." ),
167  aComponent->GetReference(),
168  aComponent->GetFPID().Format().wx_str() );
170 
171  // Set the pads ratsnest settings to the global settings
172  bool set_ratsnest = m_frame->GetDisplayOptions().m_ShowGlobalRatsnest;
173 
174  for ( D_PAD* pad : footprint->Pads() )
175  pad->SetLocalRatsnestVisible( set_ratsnest );
176 
178 
179  if( !m_isDryRun )
180  {
181  footprint->SetParent( m_board );
183 
184  m_addedComponents.push_back( footprint );
185  m_commit.Add( footprint );
186 
187  return footprint;
188  }
189  else
190  delete footprint;
191 
192  return NULL;
193 }
194 
195 
197  COMPONENT* aNewComponent )
198 {
199  wxString msg;
200 
201  if( aNewComponent->GetFPID().empty() )
202  {
203  msg.Printf( _( "Cannot update %s (no footprint assigned)." ),
204  aNewComponent->GetReference(),
205  aNewComponent->GetFPID().Format().wx_str() );
207  ++m_errorCount;
208  return nullptr;
209  }
210 
211  MODULE* newFootprint = m_frame->LoadFootprint( aNewComponent->GetFPID() );
212 
213  if( newFootprint == nullptr )
214  {
215  msg.Printf( _( "Cannot update %s (footprint \"%s\" not found)." ),
216  aNewComponent->GetReference(),
217  aNewComponent->GetFPID().Format().wx_str() );
219  ++m_errorCount;
220  return nullptr;
221  }
222 
223  msg.Printf( _( "Change %s footprint from \"%s\" to \"%s\"."),
224  aPcbComponent->GetReference(),
225  aPcbComponent->GetFPID().Format().wx_str(),
226  aNewComponent->GetFPID().Format().wx_str() );
228 
230 
231  if( !m_isDryRun )
232  {
233  m_frame->ExchangeFootprint( aPcbComponent, newFootprint, m_commit );
234  return newFootprint;
235  }
236  else
237  delete newFootprint;
238 
239  return nullptr;
240 }
241 
242 
244  COMPONENT* aNewComponent )
245 {
246  wxString msg;
247 
248  // Create a copy only if the module has not been added during this update
249  MODULE* copy = m_commit.GetStatus( aPcbComponent ) ? nullptr : (MODULE*) aPcbComponent->Clone();
250  bool changed = false;
251 
252  // Test for reference designator field change.
253  if( aPcbComponent->GetReference() != aNewComponent->GetReference() )
254  {
255  msg.Printf( _( "Change %s reference designator to %s." ),
256  aPcbComponent->GetReference(),
257  aNewComponent->GetReference() );
259 
260  if ( !m_isDryRun )
261  {
262  changed = true;
263  aPcbComponent->SetReference( aNewComponent->GetReference() );
264  }
265  }
266 
267  // Test for value field change.
268  if( aPcbComponent->GetValue() != aNewComponent->GetValue() )
269  {
270  msg.Printf( _( "Change %s value from %s to %s." ),
271  aPcbComponent->GetReference(),
272  aPcbComponent->GetValue(),
273  aNewComponent->GetValue() );
275 
276  if( !m_isDryRun )
277  {
278  changed = true;
279  aPcbComponent->SetValue( aNewComponent->GetValue() );
280  }
281  }
282 
283  // Test for time stamp change.
284  if( aPcbComponent->GetPath() != aNewComponent->GetPath() )
285  {
286  msg.Printf( _( "Update %s symbol association from %s to %s." ),
287  aPcbComponent->GetReference(),
288  aPcbComponent->GetPath().AsString(),
289  aNewComponent->GetPath().AsString() );
291 
292  if( !m_isDryRun )
293  {
294  changed = true;
295  aPcbComponent->SetPath( aNewComponent->GetPath() );
296  }
297  }
298 
299  if( aPcbComponent->GetProperties() != aNewComponent->GetProperties() )
300  {
301  msg.Printf( _( "Update %s properties." ),
302  aPcbComponent->GetReference() );
304 
305  if( !m_isDryRun )
306  {
307  changed = true;
308  aPcbComponent->SetProperties( aNewComponent->GetProperties() );
309  }
310  }
311 
312  if( ( aNewComponent->GetProperties().count( "exclude_from_bom" ) > 0 )
313  != ( ( aPcbComponent->GetAttributes() & MOD_EXCLUDE_FROM_BOM ) > 0 ) )
314  {
315  int attributes = aPcbComponent->GetAttributes();
316 
317  if( aNewComponent->GetProperties().count( "exclude_from_bom" ) )
318  {
319  attributes |= MOD_EXCLUDE_FROM_BOM;
320  msg.Printf( _( "Setting %s 'exclude from BOM' fabrication attribute." ),
321  aPcbComponent->GetReference() );
322  }
323  else
324  {
325  attributes &= ~MOD_EXCLUDE_FROM_BOM;
326  msg.Printf( _( "Removing %s 'exclude from BOM' fabrication attribute." ),
327  aPcbComponent->GetReference() );
328  }
329 
331 
332  if( !m_isDryRun )
333  {
334  changed = true;
335  aPcbComponent->SetAttributes( attributes );
336  }
337  }
338 
339  if( changed && copy )
340  m_commit.Modified( aPcbComponent, copy );
341  else
342  delete copy;
343 
344  return true;
345 }
346 
347 
349  COMPONENT* aNewComponent )
350 {
351  wxString msg;
352 
353  // Create a copy only if the module has not been added during this update
354  MODULE* copy = m_commit.GetStatus( aPcbComponent ) ? nullptr : (MODULE*) aPcbComponent->Clone();
355  bool changed = false;
356 
357  // At this point, the component footprint is updated. Now update the nets.
358  for( D_PAD* pad : aPcbComponent->Pads() )
359  {
360  const COMPONENT_NET& net = aNewComponent->GetNet( pad->GetName() );
361 
362  wxString pinFunction;
363 
364  if( net.IsValid() ) // i.e. the pad has a name
365  pinFunction = net.GetPinFunction();
366 
367  if( !m_isDryRun )
368  {
369  if( pad->GetPinFunction() != pinFunction )
370  {
371  changed = true;
372  pad->SetPinFunction( pinFunction );
373  }
374  }
375  else
376  cachePinFunction( pad, pinFunction );
377 
378  // Test if new footprint pad has no net (pads not on copper layers have no net).
379  if( !net.IsValid() || !pad->IsOnCopperLayer() )
380  {
381  if( !pad->GetNetname().IsEmpty() )
382  {
383  msg.Printf( _( "Disconnect %s pin %s." ),
384  aPcbComponent->GetReference(),
385  pad->GetName() );
387  }
388  else if( m_warnForNoNetPads && pad->IsOnCopperLayer() && !pad->GetName().IsEmpty() )
389  {
390  // pad is connectable but has no net found in netlist
391  msg.Printf( _( "No net for component %s pin %s." ),
392  aPcbComponent->GetReference(),
393  pad->GetName() );
395  }
396 
397  if( !m_isDryRun )
398  {
399  changed = true;
400  pad->SetNetCode( NETINFO_LIST::UNCONNECTED );
401 
402  // If the pad has no net from netlist (i.e. not in netlist
403  // it cannot have a pin function
404  if( pad->GetNetname().IsEmpty() )
405  pad->SetPinFunction( wxEmptyString );
406 
407  }
408  else
409  cacheNetname( pad, wxEmptyString );
410  }
411  else // New footprint pad has a net.
412  {
413  const wxString& netName = net.GetNetName();
414  NETINFO_ITEM* netinfo = m_board->FindNet( netName );
415 
416  if( netinfo && !m_isDryRun )
417  netinfo->SetIsCurrent( true );
418 
419  if( pad->GetNetname() != netName )
420  {
421 
422  if( netinfo == nullptr )
423  {
424  // It might be a new net that has not been added to the board yet
425  if( m_addedNets.count( netName ) )
426  netinfo = m_addedNets[ netName ];
427  }
428 
429  if( netinfo == nullptr )
430  {
431  netinfo = new NETINFO_ITEM( m_board, netName );
432 
433  // It is a new net, we have to add it
434  if( !m_isDryRun )
435  {
436  changed = true;
437  m_commit.Add( netinfo );
438  }
439 
440  m_addedNets[netName] = netinfo;
441  msg.Printf( _( "Add net %s." ), UnescapeString( netName ) );
443  }
444 
445  if( !pad->GetNetname().IsEmpty() )
446  {
447  m_oldToNewNets[ pad->GetNetname() ] = netName;
448 
449  msg.Printf( _( "Reconnect %s pin %s from %s to %s."),
450  aPcbComponent->GetReference(),
451  pad->GetName(),
452  UnescapeString( pad->GetNetname() ),
453  UnescapeString( netName ) );
454  }
455  else
456  {
457  msg.Printf( _( "Connect %s pin %s to %s."),
458  aPcbComponent->GetReference(),
459  pad->GetName(),
460  UnescapeString( netName ) );
461  }
463 
464  if( !m_isDryRun )
465  {
466  changed = true;
467  pad->SetNet( netinfo );
468  }
469  else
470  cacheNetname( pad, netName );
471  }
472  }
473  }
474 
475  if( changed && copy )
476  m_commit.Modified( aPcbComponent, copy );
477  else
478  delete copy;
479 
480  return true;
481 }
482 
483 
485 {
486  for( ZONE_CONTAINER* zone : m_board->Zones() )
487  {
488  if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
489  continue;
490 
491  m_zoneConnectionsCache[ zone ] = m_board->GetConnectivity()->GetConnectedPads( zone );
492  }
493 }
494 
495 
497 {
498  wxString msg;
499  std::set<wxString> netlistNetnames;
500 
501  for( int ii = 0; ii < (int) aNetlist.GetCount(); ii++ )
502  {
503  const COMPONENT* component = aNetlist.GetComponent( ii );
504  for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
505  {
506  const COMPONENT_NET& net = component->GetNet( jj );
507  netlistNetnames.insert( net.GetNetName() );
508  }
509  }
510 
511  for( TRACK* via : m_board->Tracks() )
512  {
513  if( via->Type() != PCB_VIA_T )
514  continue;
515 
516  if( netlistNetnames.count( via->GetNetname() ) == 0 )
517  {
518  wxString updatedNetname = wxEmptyString;
519 
520  // Take via name from name change map if it didn't match to a new pad
521  // (this is useful for stitching vias that don't connect to tracks)
522  if( m_oldToNewNets.count( via->GetNetname() ) )
523  {
524  updatedNetname = m_oldToNewNets[via->GetNetname()];
525  }
526 
527  if( !updatedNetname.IsEmpty() )
528  {
529  msg.Printf( _( "Reconnect via from %s to %s." ),
530  UnescapeString( via->GetNetname() ),
531  UnescapeString( updatedNetname ) );
533 
534  if( !m_isDryRun )
535  {
536  NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
537 
538  if( !netinfo )
539  netinfo = m_addedNets[updatedNetname];
540 
541  if( netinfo )
542  {
543  m_commit.Modify( via );
544  via->SetNet( netinfo );
545  }
546  }
547  }
548  else
549  {
550  msg.Printf( _( "Via connected to unknown net (%s)." ),
551  UnescapeString( via->GetNetname() ) );
553  ++m_warningCount;
554  }
555  }
556  }
557 
558  // Test copper zones to detect "dead" nets (nets without any pad):
559  for( ZONE_CONTAINER* zone : m_board->Zones() )
560  {
561  if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() )
562  continue;
563 
564  if( netlistNetnames.count( zone->GetNetname() ) == 0 )
565  {
566  // Look for a pad in the zone's connected-pad-cache which has been updated to
567  // a new net and use that. While this won't always be the right net, the dead
568  // net is guaranteed to be wrong.
569  wxString updatedNetname = wxEmptyString;
570 
571  for( D_PAD* pad : m_zoneConnectionsCache[ zone ] )
572  {
573  if( getNetname( pad ) != zone->GetNetname() )
574  {
575  updatedNetname = getNetname( pad );
576  break;
577  }
578  }
579 
580  // Take zone name from name change map if it didn't match to a new pad
581  // (this is useful for zones on internal layers)
582  if( updatedNetname.IsEmpty() && m_oldToNewNets.count( zone->GetNetname() ) )
583  {
584  updatedNetname = m_oldToNewNets[ zone->GetNetname() ];
585  }
586 
587  if( !updatedNetname.IsEmpty() )
588  {
589  msg.Printf( _( "Reconnect copper zone from %s to %s." ),
590  UnescapeString( zone->GetNetname() ),
591  UnescapeString( updatedNetname ) );
593 
594  if( !m_isDryRun )
595  {
596  NETINFO_ITEM* netinfo = m_board->FindNet( updatedNetname );
597 
598  if( !netinfo )
599  netinfo = m_addedNets[ updatedNetname ];
600 
601  if( netinfo )
602  {
603  m_commit.Modify( zone );
604  zone->SetNet( netinfo );
605  }
606  }
607  }
608  else
609  {
610  msg.Printf( _( "Copper zone (%s) has no pads connected." ),
611  UnescapeString( zone->GetNetname() ) );
613  ++m_warningCount;
614  }
615  }
616  }
617 
618  return true;
619 }
620 
621 
623 {
624  wxString msg;
625  const COMPONENT* component;
626 
627  for( MODULE* module : m_board->Modules() )
628  {
629  if( ( module->GetAttributes() & MOD_BOARD_ONLY ) > 0 )
630  continue;
631 
632  if( m_lookupByTimestamp )
633  component = aNetlist.GetComponentByPath( module->GetPath() );
634  else
635  component = aNetlist.GetComponentByReference( module->GetReference() );
636 
637  if( component == NULL || component->GetProperties().count( "exclude_from_board" ) )
638  {
639  if( module->IsLocked() )
640  {
641  msg.Printf( _( "Cannot remove unused footprint %s (locked)." ), module->GetReference() );
643  continue;
644  }
645 
646  msg.Printf( _( "Remove unused footprint %s." ), module->GetReference() );
648 
649  if( !m_isDryRun )
650  m_commit.Remove( module );
651  }
652  }
653 
654  return true;
655 }
656 
657 
659 {
660  int count = 0;
661  wxString netname;
662  wxString msg;
663  D_PAD* previouspad = NULL;
664 
665  // We need the pad list for next tests.
666 
668 
669  std::vector<D_PAD*> padlist = m_board->GetPads();
670 
671  // Sort pads by netlist name
672  std::sort( padlist.begin(), padlist.end(), [ this ]( D_PAD* a, D_PAD* b ) -> bool
673  {
674  return getNetname( a ) < getNetname( b );
675  } );
676 
677  for( D_PAD* pad : padlist )
678  {
679  if( getNetname( pad ).IsEmpty() )
680  continue;
681 
682  if( netname != getNetname( pad ) ) // End of net
683  {
684  if( previouspad && count == 1 )
685  {
686  // First, see if we have a copper zone attached to this pad.
687  // If so, this is not really a single pad net
688 
689  for( ZONE_CONTAINER* zone : m_board->Zones() )
690  {
691  if( !zone->IsOnCopperLayer() )
692  continue;
693 
694  if( zone->GetIsRuleArea() )
695  continue;
696 
697  if( zone->GetNetname() == getNetname( previouspad ) )
698  {
699  count++;
700  break;
701  }
702  }
703 
704  if( count == 1 ) // Really one pad, and nothing else
705  {
706  msg.Printf( _( "Remove single pad net %s." ),
707  UnescapeString( getNetname( previouspad ) ) );
709 
710  if( !m_isDryRun )
711  previouspad->SetNetCode( NETINFO_LIST::UNCONNECTED );
712  else
713  cacheNetname( previouspad, wxEmptyString );
714  }
715  }
716 
717  netname = getNetname( pad );
718  count = 1;
719  }
720  else
721  {
722  count++;
723  }
724 
725  previouspad = pad;
726  }
727 
728  // Examine last pad
729  if( count == 1 )
730  {
731  if( !m_isDryRun )
732  previouspad->SetNetCode( NETINFO_LIST::UNCONNECTED );
733  else
734  cacheNetname( previouspad, wxEmptyString );
735  }
736 
737  return true;
738 }
739 
740 
742 {
743  // Verify that board contains all pads in netlist: if it doesn't then footprints are
744  // wrong or missing.
745  // Note that we use references to find the footprints as they're already updated by this
746  // point (whether by-reference or by-timestamp).
747 
748  wxString msg;
749  wxString padname;
750 
751  for( int i = 0; i < (int) aNetlist.GetCount(); i++ )
752  {
753  const COMPONENT* component = aNetlist.GetComponent( i );
754  MODULE* footprint = m_board->FindModuleByReference( component->GetReference() );
755 
756  if( footprint == NULL ) // It can be missing in partial designs
757  continue;
758 
759  // Explore all pins/pads in component
760  for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
761  {
762  const COMPONENT_NET& net = component->GetNet( jj );
763  padname = net.GetPinName();
764 
765  if( footprint->FindPadByName( padname ) )
766  continue; // OK, pad found
767 
768  // not found: bad footprint, report error
769  msg.Printf( _( "%s pad %s not found in %s." ),
770  component->GetReference(),
771  padname,
772  footprint->GetFPID().Format().wx_str() );
774  ++m_errorCount;
775  }
776  }
777 
778  return true;
779 }
780 
781 
783 {
784  wxString msg;
785  m_errorCount = 0;
786  m_warningCount = 0;
788  MODULE* lastPreexistingFootprint = m_board->Modules().empty() ? NULL : m_board->Modules().back();
789 
791 
792  if( !m_isDryRun )
793  {
794  m_board->SetStatus( 0 );
795 
796  // Mark all nets (except <no net>) as stale; we'll update those to current that
797  // we find in the netlist
798  for( NETINFO_ITEM* net : m_board->GetNetInfo() )
799  net->SetIsCurrent( net->GetNet() == 0 );
800  }
801 
802  for( unsigned i = 0; i < aNetlist.GetCount(); i++ )
803  {
804  COMPONENT* component = aNetlist.GetComponent( i );
805  int matchCount = 0;
806  MODULE* tmp;
807 
808  if( component->GetProperties().count( "exclude_from_board" ) )
809  continue;
810 
811  msg.Printf( _( "Processing component \"%s:%s\"." ),
812  component->GetReference(),
813  component->GetFPID().Format().wx_str() );
815 
816  for( auto footprint : m_board->Modules() )
817  {
818  bool match = false;
819 
820  if( footprint )
821  {
822  if( m_lookupByTimestamp )
823  match = footprint->GetPath() == component->GetPath();
824  else
825  match = footprint->GetReference().CmpNoCase( component->GetReference() ) == 0;
826  }
827 
828  if( match )
829  {
830  tmp = footprint;
831 
832  if( m_replaceFootprints && component->GetFPID() != footprint->GetFPID() )
833  tmp = replaceComponent( aNetlist, footprint, component );
834 
835  if( tmp )
836  {
837  updateComponentParameters( tmp, component );
838  updateComponentPadConnections( tmp, component );
839  }
840 
841  matchCount++;
842  }
843 
844  if( footprint == lastPreexistingFootprint )
845  {
846  // No sense going through the newly-created footprints: end of loop
847  break;
848  }
849  }
850 
851  if( matchCount == 0 )
852  {
853  tmp = addNewComponent( component );
854 
855  if( tmp )
856  {
857  updateComponentParameters( tmp, component );
858  updateComponentPadConnections( tmp, component );
859  }
860  }
861  else if( matchCount > 1 )
862  {
863  msg.Printf( _( "Multiple footprints found for \"%s\"." ),
864  component->GetReference() );
866  }
867  }
868 
869  updateCopperZoneNets( aNetlist );
870 
872  deleteUnusedComponents( aNetlist );
873 
874  if( !m_isDryRun )
875  {
876  m_board->GetConnectivity()->Build( m_board );
877  testConnectivity( aNetlist );
878 
879  // Now the connectivity data is rebuilt, we can delete single pads nets
882 
883  for( NETINFO_ITEM* net : m_board->GetNetInfo() )
884  {
885  if( !net->IsCurrent() )
886  {
887  msg.Printf( _( "Remove unused net \"%s\"." ), net->GetNetname() );
889  m_commit.Removed( net );
890  }
891  }
892 
894  m_commit.Push( _( "Update netlist" ) );
895  }
897  // We can delete single net pads in dry run mode only if no new footprints
898  // are added, because these new footprints are not actually added to the board
899  // and the current pad list is wrong in this case.
901 
902  if( m_isDryRun )
903  {
904  for( const auto& it : m_addedNets )
905  delete it.second;
906 
907  m_addedNets.clear();
908  }
909 
910  // Update the ratsnest
913 
914  msg.Printf( _( "Total warnings: %d, errors: %d." ), m_warningCount, m_errorCount );
916 
917  if( m_errorCount )
918  {
919  m_reporter->ReportTail( _( "Errors occurred during the netlist update. Unless you fix them "
920  "your board will not be consistent with the schematics." ),
922  return false;
923  }
924 
925  return true;
926 }
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
void BuildListOfNets()
Definition: class_board.h:702
int GetAttributes() const
Definition: class_module.h:251
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
MODULE * replaceComponent(NETLIST &aNetlist, MODULE *aPcbComponent, COMPONENT *aNewComponent)
const PAGE_INFO & GetPageSettings() const
Definition: class_board.h:572
COMPONENT * GetComponentByPath(const KIID_PATH &aPath)
Function GetComponentByPath returns a COMPONENT by aPath.
void cacheNetname(D_PAD *aPad, const wxString &aNetname)
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
const EDA_RECT GetBoardEdgesBoundingBox() const
Returns the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: class_board.h:779
void SetIsCurrent(bool isCurrent)
Definition: netinfo.h:256
std::map< ZONE_CONTAINER *, std::vector< D_PAD * > > m_zoneConnectionsCache
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Function ReportTail Places the report at the end of the list, for objects that support report orderin...
Definition: reporter.h:94
int GetWidth() const
Definition: eda_rect.h:119
PADS & Pads()
Definition: class_module.h:182
const wxString GetValue() const
Function GetValue.
Definition: class_module.h:460
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
wxString GetNetname() const
Function GetNetname.
BOARD_NETLIST_UPDATER class definition.
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:224
int GetStatus(EDA_ITEM *aItem)
Returns status of an item.
Definition: commit.cpp:132
const NETINFO_LIST & GetNetInfo() const
Definition: class_board.h:721
const LIB_ID & GetFPID() const
Definition: class_module.h:210
bool updateComponentPadConnections(MODULE *aPcbComponent, COMPONENT *aNewComponent)
bool updateCopperZoneNets(NETLIST &aNetlist)
const KIID_PATH & GetPath() const
Definition: class_module.h:219
bool testConnectivity(NETLIST &aNetlist)
const wxString & GetPinFunction() const
Definition: class_pad.h:138
void RemoveUnusedNets()
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Function GetDisplayOptions Display options control the way tracks, vias, outlines and other things ar...
bool UpdateNetlist(NETLIST &aNetlist)
Function UpdateNetlist()
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
bool empty() const
Definition: lib_id.h:186
void ExchangeFootprint(MODULE *aExisting, MODULE *aNew, BOARD_COMMIT &aCommit, bool deleteExtraTexts=true, bool resetTextLayers=true, bool resetTextEffects=true, bool resetFabricationAttrs=true, bool reset3DModels=true)
Function Exchange_Module Replaces OldModule by NewModule, using OldModule settings: position,...
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:184
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
int GetBottom() const
Definition: eda_rect.h:124
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:435
std::map< wxString, NETINFO_ITEM * > m_addedNets
const LIB_ID & GetFPID() const
Definition: pcb_netlist.h:157
COMPONENT_NET is used to store the component pin name to net name (and pin function) associations sto...
Definition: pcb_netlist.h:44
COMMIT & Removed(EDA_ITEM *aItem)
Notifies observers that aItem has been removed
Definition: commit.h:96
D_PAD * FindPadByName(const wxString &aPadName) const
Function FindPadByName returns a D_PAD* with a matching name.
const wxString & GetNetName() const
Definition: pcb_netlist.h:60
NETLIST stores all of information read from a netlist along with the flags used to update the NETLIST...
Definition: pcb_netlist.h:194
#define NULL
wxString getNetname(D_PAD *aPad)
MODULES & Modules()
Definition: class_board.h:284
wxString getPinFunction(D_PAD *aPad)
unsigned GetNetCount() const
Definition: pcb_netlist.h:133
const wxString & GetReference() const
Definition: pcb_netlist.h:147
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: class_board.h:380
std::map< wxString, wxString > m_oldToNewNets
void SetReference(const wxString &aReference)
Function SetReference.
Definition: class_module.h:445
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
COMMIT & Remove(EDA_ITEM *aItem)
Removes a new item from the model
Definition: commit.h:90
void SetPosition(const wxPoint &aPos) override
const COMPONENT_NET & GetNet(unsigned aIndex) const
Definition: pcb_netlist.h:135
std::map< D_PAD *, wxString > m_padNets
int GetHeight() const
Definition: eda_rect.h:120
UTF8 Format() const
Definition: lib_id.cpp:237
Pad object description.
COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:80
const wxString & GetPinFunction() const
Definition: pcb_netlist.h:61
bool IsValid() const
Definition: pcb_netlist.h:63
COMPONENT * GetComponent(unsigned aIndex)
Function GetComponent returns the COMPONENT at aIndex.
Definition: pcb_netlist.h:233
void cachePinFunction(D_PAD *aPad, const wxString &aPinFunction)
COMMIT & Modified(EDA_ITEM *aItem, EDA_ITEM *aCopy)
Creates an undo entry for an item that has been already modified.
Definition: commit.h:110
const std::vector< D_PAD * > GetPads()
Return a reference to a list of all the pads.
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
ZONE_CONTAINERS & Zones()
Definition: class_board.h:290
MODULE * LoadFootprint(const LIB_ID &aFootprintId)
Function LoadFootprint attempts to load aFootprintId from the footprint library table.
bool updateComponentParameters(MODULE *aPcbComponent, COMPONENT *aNewComponent)
void SetProperties(const std::map< wxString, wxString > &aProps)
Definition: class_module.h:483
std::map< D_PAD *, wxString > m_padPinFunctions
Information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:186
#define _(s)
Definition: 3d_actions.cpp:33
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:151
wxString AsString() const
Definition: common.h:139
wxString wx_str() const
Definition: utf8.cpp:51
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
PCB_EDIT_FRAME is the main frame for Pcbnew.
void SetValue(const wxString &aValue)
Function SetValue.
Definition: class_module.h:469
The common library.
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
MODULE * FindModuleByReference(const wxString &aReference) const
Search for a MODULE within this board with the given reference designator.
void SetStatus(STATUS_FLAGS aStatus)
Definition: eda_item.h:218
wxPoint Centre() const
Definition: eda_rect.h:62
const wxString & GetPinName() const
Definition: pcb_netlist.h:59
const std::map< wxString, wxString > & GetProperties() const
Definition: class_module.h:482
const std::map< wxString, wxString > & GetProperties() const
Definition: pcb_netlist.h:154
const wxString & GetValue() const
Definition: pcb_netlist.h:148
COMPONENT * GetComponentByReference(const wxString &aReference)
Function GetComponentByReference returns a COMPONENT by aReference.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
std::vector< MODULE * > m_addedComponents
void SetPath(const KIID_PATH &aPath)
Definition: class_module.h:220
static REPORTER & GetInstance()
Definition: reporter.cpp:105
BOARD_NETLIST_UPDATER(PCB_EDIT_FRAME *aFrame, BOARD *aBoard)
const KIID_PATH & GetPath() const
Definition: pcb_netlist.h:162
bool deleteUnusedComponents(NETLIST &aNetlist)
static constexpr int Millimeter2iu(double mm)
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:478
bool IsEmpty() const
Definition: class_board.h:328
TRACKS & Tracks()
Definition: class_board.h:281
void SetAttributes(int aAttributes)
Definition: class_module.h:252
MODULE * addNewComponent(COMPONENT *aComponent)