Pcbnew: fix issues and potential issues when reading board files and mainly old board files, and enhance the DRC tests and Delete Single Pad Net option when reading a netlist:

* Delete Single Pad Net option does not delete the net if a zone use this net (i.e. is attached to this pad).
* pcb_parser accept now negative netcodes in zones (can happen with old files, which previously could crash Pcbnew)
* pcb_parser accept now files with incorrect or missing net count  (can happen with old files, which previously could crash Pcbnew)
* if a zone has a non-existent net name it now keep this net name, and DRC detect it (previously, the net name was lost, and the DRC did not tected this issue).
* Drc test: now detect a "dead" net, i.e. a net with 0 pads, but still used by a zone. It happens easily after a schematic modification, when a net disappears or is renamed.
This commit is contained in:
jean-pierre charras 2015-01-22 13:06:34 +01:00
parent 64dd1f7461
commit ebb967c46f
11 changed files with 172 additions and 65 deletions

View File

@ -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 <dick@softplc.com>
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
*
* 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<D_PAD*> padlist = GetPads();
// If needed, remove the single pad nets:
if( aDeleteSinglePadNets && !aNetlist.IsDryRun() )
{
BuildListOfNets();
std::vector<D_PAD*> 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 );
}
}
}
}

View File

@ -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 <dick@softplc.com>
* 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;

View File

@ -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:

View File

@ -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

View File

@ -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 <dick@softplc.com>
* 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( "<noname>" );
}
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 = _( "<unknown>" );
}
else // a netcode < 0 is an error
msg = wxT( "<error>" );
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() );

View File

@ -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.

View File

@ -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;
}
}

View File

@ -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

View File

@ -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();
}

View File

@ -69,15 +69,24 @@ class PCB_PARSER : public PCB_LEXER
std::vector<int> 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.

View File

@ -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 <dick@softplc.com>
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
* 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