diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index d52d6d7ff6..d6ec4d4197 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -6,11 +6,11 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2011 Wayne Stambaugh * - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -2459,14 +2459,14 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, } } + // We need the pad list, for next tests. + // padlist is the list of pads, sorted by netname. + BuildListOfNets(); + std::vector padlist = GetPads(); + // If needed, remove the single pad nets: if( aDeleteSinglePadNets && !aNetlist.IsDryRun() ) { - BuildListOfNets(); - - std::vector padlist = GetPads(); - - // padlist is the list of pads, sorted by netname. int count = 0; wxString netname; D_PAD* pad = NULL; @@ -2483,17 +2483,41 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, { if( previouspad && count == 1 ) { - if( aReporter && aReporter->ReportAll() ) + // First, see if we have a copper zone attached to this pad. + // If so, this is not really a single pad net + + for( int ii = 0; ii < GetAreaCount(); ii++ ) { - msg.Printf( _( "Remove single pad net \"%s\" on \"%s\" pad '%s'\n" ), - GetChars( previouspad->GetNetname() ), - GetChars( previouspad->GetParent()->GetReference() ), - GetChars( previouspad->GetPadName() ) ); - aReporter->Report( msg ); + ZONE_CONTAINER* zone = GetArea( ii ); + + if( !zone->IsOnCopperLayer() ) + continue; + + if( zone->GetIsKeepout() ) + continue; + + if( zone->GetNet() == previouspad->GetNet() ) + { + count++; + break; + } } - previouspad->SetNetCode( NETINFO_LIST::UNCONNECTED ); + if( count == 1 ) // Really one pad, and nothing else + { + if( aReporter && aReporter->ReportAll() ) + { + msg.Printf( _( "Remove single pad net \"%s\" on \"%s\" pad '%s'\n" ), + GetChars( previouspad->GetNetname() ), + GetChars( previouspad->GetParent()->GetReference() ), + GetChars( previouspad->GetPadName() ) ); + aReporter->Report( msg ); + } + + previouspad->SetNetCode( NETINFO_LIST::UNCONNECTED ); + } } + netname = pad->GetNetname(); count = 1; } @@ -2515,6 +2539,10 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, // They should exist in footprints, otherwise the footprint is wrong // note also references or time stamps are updated, so we use only // the reference to find a footprint + // + // Also verify if zones have acceptable nets, i.e. nets with pads. + // Zone with no pad belongs to a "dead" net which happens after changes in schematic + // when no more pad use this net name. if( aReporter && aReporter->ReportErrors() ) { wxString padname; @@ -2543,6 +2571,22 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets, aReporter->Report( msg ); } } + + // Test copper zones to detect "dead" nets (nets without any pad): + for( int ii = 0; ii < GetAreaCount(); ii++ ) + { + ZONE_CONTAINER* zone = GetArea( ii ); + + if( !zone->IsOnCopperLayer() || zone->GetIsKeepout() ) + continue; + + if( zone->GetNet()->GetNodesCount() == 0 ) + { + msg.Printf( _( "* Warning: copper zone (net name '%s'): net has no pad*\n" ), + GetChars( zone->GetNet()->GetNetname() ) ); + aReporter->Report( msg ); + } + } } } diff --git a/pcbnew/class_board_connected_item.cpp b/pcbnew/class_board_connected_item.cpp index 09cc9eafd8..dfe4e96f3e 100644 --- a/pcbnew/class_board_connected_item.cpp +++ b/pcbnew/class_board_connected_item.cpp @@ -1,9 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -50,10 +50,10 @@ BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& aItem ) void BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode ) { - assert( aNetCode >= 0 ); +// assert( aNetCode >= 0 ); BOARD* board = GetBoard(); - if( board ) + if( ( aNetCode >= 0 ) && board ) m_netinfo = board->FindNet( aNetCode ); else m_netinfo = &NETINFO_LIST::ORPHANED; diff --git a/pcbnew/class_drc_item.cpp b/pcbnew/class_drc_item.cpp index efb70268e1..ff145f47da 100644 --- a/pcbnew/class_drc_item.cpp +++ b/pcbnew/class_drc_item.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2015 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -75,8 +75,10 @@ wxString DRC_ITEM::GetErrorText() const return wxString( _( "Copper area inside copper area" ) ); case COPPERAREA_CLOSE_TO_COPPERAREA: return wxString( _( "Copper areas intersect or are too close" ) ); - case DRCE_NON_EXISTANT_NET_FOR_ZONE_OUTLINE: - return wxString( _( "Copper area has a nonexistent net name" ) ); + + case DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE: + return wxString( _( "Copper area belongs a net which has no pads. This is strange" ) ); + case DRCE_HOLE_NEAR_PAD: return wxString( _( "Hole near pad" ) ); case DRCE_HOLE_NEAR_TRACK: diff --git a/pcbnew/class_netinfo.h b/pcbnew/class_netinfo.h index 3b28a9ed8f..8d8f3df89c 100644 --- a/pcbnew/class_netinfo.h +++ b/pcbnew/class_netinfo.h @@ -320,7 +320,7 @@ public: return NULL; } - ///> Constant that holds the unconnected net number + ///> Constant that holds the unconnected net number (typically 0) static const int UNCONNECTED; ///> NETINFO_ITEM meaning that there was no net assigned for an item, as there was no diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index e7e3081e34..17938aea9f 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -1,9 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -625,27 +625,21 @@ void ZONE_CONTAINER::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) { if( GetNetCode() >= 0 ) { - NETINFO_ITEM* equipot = GetNet(); + NETINFO_ITEM* net = GetNet(); - if( equipot ) - msg = equipot->GetNetname(); - else - msg = wxT( "" ); - } - else // a netcode < 0 is an error - { - msg = wxT( " [" ); - msg << GetNetname() + wxT( "]" ); - msg << wxT( " <" ) << _( "Not Found" ) << wxT( ">" ); + if( net ) + msg = net->GetNetname(); + else // Should not occur + msg = _( "" ); } + else // a netcode < 0 is an error + msg = wxT( "" ); aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) ); -#if 1 // Display net code : (useful in test or debug) msg.Printf( wxT( "%d" ), GetNetCode() ); aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) ); -#endif // Display priority level msg.Printf( wxT( "%d" ), GetPriority() ); diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 17c51cfcf9..13eb37b271 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -2,8 +2,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -578,7 +578,6 @@ public: void SetDoNotAllowVias( bool aEnable ) { m_doNotAllowVias = aEnable; } void SetDoNotAllowTracks( bool aEnable ) { m_doNotAllowTracks = aEnable; } - #if defined(DEBUG) virtual void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override #endif @@ -632,8 +631,8 @@ private: /// The index of the corner being moved or -1 if no corner is selected. int m_CornerSelection; - int m_localFlgs; ///< Flags used in polygon calculations. - + /// Variable used in polygon calculations. + int m_localFlgs; /** Segments used to fill the zone (#m_FillMode ==1 ), when fill zone by segment is used. * In this case the segments have #m_ZoneMinThickness width. diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp index 03357376b8..93b7c96988 100644 --- a/pcbnew/drc.cpp +++ b/pcbnew/drc.cpp @@ -2,9 +2,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2014 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2015 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -564,6 +564,10 @@ void DRC::testZones() // if a netcode is < 0 the netname was not found when reading a netlist // if a netcode is == 0 the netname is void, and the zone is not connected. // This is allowed, but i am not sure this is a good idea + // + // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name + // is stored, and initalized from the file or the zone properpies editor. + // if it differs from the net name from net code, there is a DRC issue for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* test_area = m_pcb->GetArea( ii ); @@ -571,13 +575,21 @@ void DRC::testZones() if( !test_area->IsOnCopperLayer() ) continue; - if( test_area->GetNetCode() < 0 ) + int netcode = test_area->GetNetCode(); + + // a netcode < 0 or > 0 and no pad in net is a error or strange + // perhaps a "dead" net, which happens when all pads in this net were removed + // Remark: a netcode < 0 should not happen (this is more a bug somewhere) + int pads_in_net = (test_area->GetNetCode() > 0) ? + test_area->GetNet()->GetNodesCount() : 1; + + if( ( netcode < 0 ) || pads_in_net == 0 ) { m_currentMarker = fillMarker( test_area, - DRCE_NON_EXISTANT_NET_FOR_ZONE_OUTLINE, m_currentMarker ); + DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE, m_currentMarker ); m_pcb->Add( m_currentMarker ); m_mainWindow->GetGalCanvas()->GetView()->Add( m_currentMarker ); - m_currentMarker = 0; + m_currentMarker = NULL; } } diff --git a/pcbnew/drc_stuff.h b/pcbnew/drc_stuff.h index d8f4e7dfe5..6b4b98dec3 100644 --- a/pcbnew/drc_stuff.h +++ b/pcbnew/drc_stuff.h @@ -6,7 +6,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2015 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -60,7 +60,7 @@ #define DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR 21 ///< micro via's layer pair incorrect (layers must be adjacent) #define COPPERAREA_INSIDE_COPPERAREA 22 ///< copper area outlines intersect #define COPPERAREA_CLOSE_TO_COPPERAREA 23 ///< copper area outlines are too close -#define DRCE_NON_EXISTANT_NET_FOR_ZONE_OUTLINE 24 ///< copper area outline has an incorrect netcode due to a netname not found +#define DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE 24 ///< copper area has a net but no pads in nets, which is suspicious #define DRCE_HOLE_NEAR_PAD 25 ///< hole too close to pad #define DRCE_HOLE_NEAR_TRACK 26 ///< hole too close to track #define DRCE_TOO_SMALL_TRACK_WIDTH 27 ///< Too small track width diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 1cfc1fb08e..a4c8785f3e 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -112,6 +112,17 @@ void PCB_PARSER::init() } +void PCB_PARSER::pushValueIntoMap( int aIndex, int aValue ) +{ + // Add aValue in netcode mapping (m_netCodes) at index aNetCode + // ensure there is room in m_netCodes for that, and add room if needed. + + if( (int)m_netCodes.size() <= aIndex ) + m_netCodes.resize( aIndex+1 ); + + m_netCodes[aIndex] = aValue; +} + double PCB_PARSER::parseDouble() throw( IO_ERROR ) { char* tmp; @@ -1194,7 +1205,7 @@ void PCB_PARSER::parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR ) m_board->AppendNet( net ); // Store the new code mapping - m_netCodes[netCode] = net->GetNet(); + pushValueIntoMap( netCode, net->GetNet() ); } } @@ -2526,6 +2537,8 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ) int hatchPitch = Mils2iu( CPolyLine::GetDefaultHatchPitchMils() ); wxPoint pt; T token; + int tmp; + wxString netnameFromfile; // the zone net name find in file // bigger scope since each filled_polygon is concatenated in here CPOLYGONS_LIST pts; @@ -2545,20 +2558,19 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ) // Init the net code only, not the netname, to be sure // the zone net name is the name read in file. // (When mismatch, the user will be prompted in DRC, to fix the actual name) - zone->SetNetCode( getNetCode( parseInt( "net number" ) ) ); + tmp = getNetCode( parseInt( "net number" ) ); + + if( tmp < 0 ) + tmp = 0; + + zone->SetNetCode( tmp ); + NeedRIGHT(); break; case T_net_name: NeedSYMBOLorNUMBER(); - if( zone->GetNet()->GetNetname() != FromUTF8() ) - { - wxString msg; - msg.Printf( _( "There is a zone that belongs to a not existing net" - "(%s), you should verify it." ), GetChars( FromUTF8() ) ); - DisplayError( NULL, msg ); - zone->SetNetCode( NETINFO_LIST::UNCONNECTED ); - } + netnameFromfile = FromUTF8(); NeedRIGHT(); break; @@ -2829,10 +2841,45 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ) if( pts.GetCornersCount() ) zone->AddFilledPolysList( pts ); - // Ensure keepout does not have a net (which have no sense for a keepout zone) - if( zone->GetIsKeepout() ) + // Ensure keepout and non copper zones do not have a net + // (which have no sense for these zones) + // the netcode 0 is used for these zones + bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsKeepout(); + + if( !zone_has_net ) zone->SetNetCode( NETINFO_LIST::UNCONNECTED ); + // Ensure the zone net name is valid, and matches the net code, for copper zones + if( zone_has_net && ( zone->GetNet()->GetNetname() != netnameFromfile ) ) + { + // Can happens which old boards, with nonexistent nets ... + // or after being edited by hand + // We try to fix the mismatch. + NETINFO_ITEM* net = m_board->FindNet( netnameFromfile ); + + if( net ) // An existing net has the same net name. use it for the zone + zone->SetNetCode( net->GetNet() ); + else // Not existing net: add a new net to keep trace of the zone netname + { + int newnetcode = m_board->GetNetCount(); + net = new NETINFO_ITEM( m_board, netnameFromfile, newnetcode ); + m_board->AppendNet( net ); + + // Store the new code mapping + pushValueIntoMap( newnetcode, net->GetNet() ); + // and update the zone netcode + zone->SetNetCode( net->GetNet() ); + + // Prompt the user + wxString msg; + msg.Printf( _( "There is a zone that belongs to a not existing net\n" + "\"%s\"\n" + "you should verify and edit it (run DRC test)." ), + GetChars( netnameFromfile ) ); + DisplayError( NULL, msg ); + } + } + return zone.release(); } diff --git a/pcbnew/pcb_parser.h b/pcbnew/pcb_parser.h index 0e2514bc57..d42081e409 100644 --- a/pcbnew/pcb_parser.h +++ b/pcbnew/pcb_parser.h @@ -69,15 +69,24 @@ class PCB_PARSER : public PCB_LEXER std::vector m_netCodes; ///< net codes mapping for boards being loaded ///> Converts net code using the mapping table if available, - ///> otherwise returns unchanged net code + ///> otherwise returns unchanged net code if < 0 or if is is out of range inline int getNetCode( int aNetCode ) { - if( aNetCode < (int) m_netCodes.size() ) + if( ( aNetCode >= 0 ) && ( aNetCode < (int) m_netCodes.size() ) ) return m_netCodes[aNetCode]; return aNetCode; } + /** + * function pushValueIntoMap + * Add aValue value in netcode mapping (m_netCodes) at index aIndex + * ensure there is room in m_netCodes for that, and add room if needed. + * @param aIndex = the index ( expected >=0 )of the location to use in m_netCodes + * @param aValue = the netcode value to map + */ + void pushValueIntoMap( int aIndex, int aValue ); + /** * Function init * clears and re-establishes m_layerMap with the default layer names. diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index 76ae549a9e..4a24ba3017 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -1,10 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2012 Wayne Stambaugh - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License