← Back to team overview

kicad-developers team mailing list archive

[PATCH] Floating tracks loose netcode

 

Hi!

Been using KiCAD and encountered bug.

Description of bug:
The issue is that tracks that are floating (not connected to any pad) lost
netcodes after reloading board file or doing DRC. This was important
because I use VIAs to improve impedance, thermal conductivity etc.

Solution:
My attached patch fixes this.

The principle is that all tracks created have netcode so in recalculation
function "PCB_BASE_FRAME::RecalculateAllTracksNetcode" I simply mark track
netcode with flag bit in MSB. Then one pass trough all tracks creating set
of substitution pairs. This is done finding tracks connected to pads and
storing this tracks netcode together with pads netcode as substitution pair
in a set. Remember that track netcodes are flaged so no chance of equal
netcodes.

Then continue with track interconnection generation, as I understand this
is not done after file read.

Last step, go trough all tracks again and change netcodes according to
substitution set data. Difference is that now even tracks not connected can
have their netcode updated to correct value. Netcodes that doesn't have
substitution data are set to 0. This would be case where some part is
deleted and traces left with now non-existing netcode.

Janis Skujenieks
=== modified file 'pcbnew/connect.cpp'
--- pcbnew/connect.cpp	2012-02-09 12:06:38 +0000
+++ pcbnew/connect.cpp	2012-02-09 12:41:38 +0000
@@ -39,6 +39,16 @@
 #include "pcbnew.h"
 
 
+#define OLD_TRACK_NET           0x40000000          /**< Flag to set indicating old netcode while keeping the code data valid */
+
+/// Structure for holding needed substitution data.
+typedef struct NET_SUBST_STRUCT
+{
+	int OldNetcode;             /**< Stores netcode that must be found and changed */
+	int NewNetcode;             /**< Indicates netcode that must be set */
+}NET_SUBS;
+
+
 extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb );
 extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode );
 
@@ -619,6 +629,19 @@
     return;
 }
 
+/**
+ * Function SubsCompare
+ * compares two parameters of type NET_SUBS.
+ *
+ * @param A is first member for comparision.
+ * @param B is second member for comparision.
+ * @return bool, true if A.OldNetcode < B.OldNetcode.
+ */
+bool SubsCompare( NET_SUBS A, NET_SUBS B )
+{
+	if( A.OldNetcode < B.OldNetcode ) return true;
+	return false;
+}
 
 /* search connections between tracks and pads and propagate pad net codes to the track
  * segments.
@@ -628,37 +651,35 @@
 {
     TRACK*              curr_track;
     std::vector<D_PAD*> sortedPads;
+	NET_SUBS            subst_pair;                                                         /**< Temporary holds substitution data */
+
+    std::set<NET_SUBS, bool (*)( NET_SUBS, NET_SUBS )> substitut_set( SubsCompare );        /**< Stores substitution set for netcodes */
+    std::set<NET_SUBS>::iterator subs_el;                                                   /**< Iterator for substitution set */
 
     // Build the net info list
     GetBoard()->m_NetInfo->BuildListOfNets();
 
-    // Reset variables and flags used in computation
-    curr_track = m_Pcb->m_Track;
-    for( ; curr_track != NULL; curr_track = curr_track->Next() )
+    // Go trough all tracks and mark them with old flag
+    for( curr_track = m_Pcb->m_Track; curr_track != NULL; curr_track = curr_track->Next() )
     {
         curr_track->m_TracksConnected.clear();
         curr_track->start = NULL;
         curr_track->end = NULL;
         curr_track->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, OFF );
-        curr_track->SetZoneSubNet( 0 );
-        curr_track->SetNet( 0 );    // net code = 0 means not connected
-    }
-
-    // If no pad, reset pointers and netcode, and do nothing else
-    if( m_Pcb->GetPadsCount() == 0 )
-        return;
-
-    // Prepare connections calculations between tracks and pads */
+        curr_track->SetNet( curr_track->GetNet() | OLD_TRACK_NET );
+    }	
+	
+    // Prepare connections calculations between tracks and pads 
     m_Pcb->GetSortedPadListByXthenYCoord( sortedPads );
 
     /* First pass: search connection between a track segment and a pad.
      * if found, set the track net code to the pad netcode
      */
-    curr_track = m_Pcb->m_Track;
-
-    for( ; curr_track != NULL; curr_track = curr_track->Next() )
+    for( curr_track = m_Pcb->m_Track; curr_track != NULL; curr_track = curr_track->Next() )
     {
         int layerMask = g_TabOneLayerMask[curr_track->GetLayer()];
+        bool pad_found = false;
+        D_PAD* connected_pad;
 
         /* Search for a pad on the segment starting point */
         curr_track->start = m_Pcb->GetPad( sortedPads, curr_track->m_Start, layerMask );
@@ -666,7 +687,8 @@
         if( curr_track->start != NULL )
         {
             curr_track->SetState( BEGIN_ONPAD, ON );
-            curr_track->SetNet( ( (D_PAD*) (curr_track->start) )->GetNet() );
+            connected_pad = (D_PAD*)curr_track->start;
+            pad_found  = true;
         }
 
         /* Search for a pad on the segment ending point */
@@ -675,24 +697,26 @@
         if( curr_track->end != NULL )
         {
             curr_track->SetState( END_ONPAD, ON );
-            curr_track->SetNet( ( (D_PAD*) (curr_track->end) )->GetNet() );
+            connected_pad = (D_PAD*)curr_track->end;
+            pad_found = true;
+        }
+        
+        if( pad_found )
+        {
+            subst_pair.OldNetcode = curr_track->GetNet();
+            subst_pair.NewNetcode = connected_pad->GetNet();
+			
+            // Register substitution pair
+            substitut_set.insert(subst_pair);
         }
     }
 
-    /*****************************************************/
-    /* Pass 2: search the connections between track ends */
-    /*****************************************************/
-
-    /* the .start and .end member pointers are updated, and point on connected pads
-     * or are null for tracks whitch are not connection to pads
-     * Now build connections lists to tracks
-     */
+    // Must generate track connections because after file load its done here - otherwise its useless
 
     CONNECTIONS connections( m_Pcb );
     connections.BuildCandidatesList();
     for( curr_track = m_Pcb->m_Track; curr_track != NULL; curr_track = curr_track->Next() )
     {
-
         if( curr_track->start != NULL && curr_track->end != NULL )
             continue;
 
@@ -700,46 +724,24 @@
         curr_track->m_TracksConnected = connections.m_Connected;
     }
 
-    // Propagate net codes from a segment to other connected segments
-    bool new_pass_request = true;   // is true if a track has its netcode changes from 0
-                                    // to a known netcode to re-evaluate netcodes
-                                    // of connected items
-    while( new_pass_request )
+    // Go trough tracks and apply substitution list or set to 0 if not found
+    for( curr_track = m_Pcb->m_Track; curr_track != NULL; curr_track = curr_track->Next() )
     {
-        new_pass_request = false;
-
-        for( curr_track = m_Pcb->m_Track; curr_track; curr_track = curr_track->Next() )
-        {
-            int netcode = curr_track->GetNet();
-            if( netcode == 0 )
-            {   // try to find a connected item having a netcode
-                for( unsigned kk = 0; kk < curr_track->m_TracksConnected.size(); kk++ )
-                {
-                    int altnetcode = curr_track->m_TracksConnected[kk]->GetNet();
-                    if( altnetcode )
-                    {
-                        new_pass_request = true;
-                        netcode = altnetcode;
-                        curr_track->SetNet(netcode);
-                        break;
-                    }
-                }
-            }
-            if( netcode )    // this track has a netcode
-            {   // propagate this netcode to connected tracks having no netcode
-                for( unsigned kk = 0; kk < curr_track->m_TracksConnected.size(); kk++ )
-                {
-                    int altnetcode = curr_track->m_TracksConnected[kk]->GetNet();
-                    if( altnetcode == 0 )
-                    {
-                        curr_track->m_TracksConnected[kk]->SetNet(netcode);
-                        new_pass_request = true;
-                    }
-                }
-            }
+        subst_pair.OldNetcode = curr_track->GetNet();
+        subs_el = substitut_set.find(subst_pair);
+        if( subs_el != substitut_set.end() )
+        {
+            curr_track->SetNet( (*subs_el).NewNetcode );
+        }
+        else
+        {
+	        curr_track->SetNet( 0 );
         }
     }
 
+    /* Clear list */
+    substitut_set.clear();
+
     /* Sort the track list by net codes: */
     RebuildTrackChain( m_Pcb );
 }