Throw duplicate pin error as it prevents other checks.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14761
This commit is contained in:
Jeff Young 2024-05-26 16:18:23 +01:00
parent becc0232b4
commit 8204577fba
7 changed files with 101 additions and 57 deletions

View File

@ -131,6 +131,9 @@ const std::set<ELECTRICAL_PINTYPE> DrivenPinTypes =
ELECTRICAL_PINTYPE::PT_POWER_IN
};
extern void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
UNITS_PROVIDER* aUnitsProvider );
int ERC_TESTER::TestDuplicateSheetNames( bool aCreateMarker )
{
SCH_SCREEN* screen;
@ -1063,17 +1066,34 @@ int ERC_TESTER::TestLibSymbolIssues()
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
constexpr int flags = SCH_ITEM::COMPARE_FLAGS::EQUALITY | SCH_ITEM::COMPARE_FLAGS::ERC;
if( settings.IsTestEnabled( ERCE_LIB_SYMBOL_MISMATCH )
&& flattenedSymbol->Compare( *libSymbolInSchematic, flags ) != 0 )
if( settings.IsTestEnabled( ERCE_LIB_SYMBOL_MISMATCH ) )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_MISMATCH );
ercItem->SetItems( symbol );
msg.Printf( _( "Symbol '%s' doesn't match copy in library '%s'" ),
UnescapeString( symbolName ),
UnescapeString( libName ) );
ercItem->SetErrorMessage( msg );
// We have to check for duplicate pins first as they will cause Compare() to fail.
std::vector<wxString> messages;
UNITS_PROVIDER unitsProvider( schIUScale, EDA_UNITS::MILS );
CheckDuplicatePins( libSymbolInSchematic, messages, &unitsProvider );
markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
if( !messages.empty() )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_DUPLICATE_PIN_ERROR );
ercItem->SetItems( symbol );
msg.Printf( _( "Symbol '%s' has multiple pins with the same pin number" ),
UnescapeString( symbolName ) );
ercItem->SetErrorMessage( msg );
markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
}
else if( flattenedSymbol->Compare( *libSymbolInSchematic, flags ) != 0 )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_MISMATCH );
ercItem->SetItems( symbol );
msg.Printf( _( "Symbol '%s' doesn't match copy in library '%s'" ),
UnescapeString( symbolName ),
UnescapeString( libName ) );
ercItem->SetErrorMessage( msg );
markers.emplace_back( new SCH_MARKER( ercItem, symbol->GetPosition() ) );
}
}
}

View File

@ -63,6 +63,10 @@ ERC_ITEM ERC_ITEM::powerpinNotDriven( ERCE_POWERPIN_NOT_DRIVEN,
_( "Input Power pin not driven by any Output Power pins" ),
wxT( "power_pin_not_driven" ) );
ERC_ITEM ERC_ITEM::duplicatePinError( ERCE_DUPLICATE_PIN_ERROR,
_( "Multiple pins with the same pin numbers" ),
wxT( "duplicate_pins" ) );
ERC_ITEM ERC_ITEM::pinTableWarning( ERCE_PIN_TO_PIN_WARNING,
_( "Conflict problem between pins" ),
wxT( "pin_to_pin" ) );
@ -263,6 +267,7 @@ std::shared_ptr<ERC_ITEM> ERC_ITEM::Create( int aErrorCode )
case ERCE_PIN_NOT_CONNECTED: return std::make_shared<ERC_ITEM>( pinNotConnected );
case ERCE_PIN_NOT_DRIVEN: return std::make_shared<ERC_ITEM>( pinNotDriven );
case ERCE_POWERPIN_NOT_DRIVEN: return std::make_shared<ERC_ITEM>( powerpinNotDriven );
case ERCE_DUPLICATE_PIN_ERROR: return std::make_shared<ERC_ITEM>( duplicatePinError );
case ERCE_PIN_TO_PIN_WARNING: return std::make_shared<ERC_ITEM>( pinTableWarning );
case ERCE_PIN_TO_PIN_ERROR: return std::make_shared<ERC_ITEM>( pinTableError );
case ERCE_HIERACHICAL_LABEL: return std::make_shared<ERC_ITEM>( hierLabelMismatch );

View File

@ -188,6 +188,7 @@ private:
static ERC_ITEM pinNotConnected;
static ERC_ITEM pinNotDriven;
static ERC_ITEM powerpinNotDriven;
static ERC_ITEM duplicatePinError;
static ERC_ITEM pinTableWarning;
static ERC_ITEM pinTableError;
static ERC_ITEM hierLabelMismatch;

View File

@ -241,10 +241,16 @@ ERC_SETTINGS::~ERC_SETTINGS()
SEVERITY ERC_SETTINGS::GetSeverity( int aErrorCode ) const
{
// Special-case duplicate pin error. Unique pin names are required by KiCad, so this
// is always an error.
if( aErrorCode == ERCE_DUPLICATE_PIN_ERROR )
{
return RPT_SEVERITY_ERROR;
}
// Special-case pin-to-pin errors:
// Ignore-or-not is controlled by ERCE_PIN_TO_PIN_WARNING (for both)
// Warning-or-error is controlled by which errorCode it is
if( aErrorCode == ERCE_PIN_TO_PIN_ERROR )
else if( aErrorCode == ERCE_PIN_TO_PIN_ERROR )
{
wxASSERT( m_ERCSeverities.count( ERCE_PIN_TO_PIN_WARNING ) );

View File

@ -89,6 +89,7 @@ enum ERCE_T
// Errors after this point will not automatically appear in the Severities Panel
ERCE_DUPLICATE_PIN_ERROR,
ERCE_PIN_TO_PIN_WARNING, // pin connected to an other pin: warning level
ERCE_PIN_TO_PIN_ERROR, // pin connected to an other pin: error level
ERCE_ANNOTATION_ACTION // Not actually an error; just an action performed during

View File

@ -31,45 +31,12 @@
static bool sort_by_pin_number( const SCH_PIN* ref, const SCH_PIN* tst );
static void CheckLibSymbolGraphics( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
EDA_DRAW_FRAME* aUnitsProvider );
UNITS_PROVIDER* aUnitsProvider );
/**
* Check a lib symbol to find incorrect settings
* Pins not on a valid grid
* Pins duplicated
* Conflict with pins at same location
* Incorrect Power Symbols
* illegal reference prefix (cannot ends by a digit or a '?')
* @param aSymbol is the library symbol to check
* @param aMessages is a room to store error messages
* @param aGridForPins (in IU) is the grid to test pin positions ( >= 25 mils )
* should be 25, 50 or 100 mils (convered to IUs)
* @param aUnitsProvider a frame to format coordinates in messages
*/
void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
int aGridForPins, EDA_DRAW_FRAME* aUnitsProvider )
void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
UNITS_PROVIDER* aUnitsProvider )
{
if( !aSymbol )
return;
wxString msg;
// Test reference prefix validity:
// if the symbol is saved in a library, the prefix should not ends by a digit or a '?'
// but it is acceptable if the symbol is saved to aschematic
wxString reference_base = aSymbol->GetReferenceField().GetText();
wxString illegal_end( wxT( "0123456789?" ) );
wxUniChar last_char = reference_base.Last();
if( illegal_end.Find( last_char ) != wxNOT_FOUND )
{
msg.Printf( _( "<b>Warning: reference prefix</b><br>prefix ending by '%s' can create"
" issues if saved in a symbol library" ),
illegal_end );
msg += wxT( "<br><br>" );
aMessages.push_back( msg );
}
wxString msg;
std::vector<SCH_PIN*> pinList = aSymbol->GetPins();
// Test for duplicates:
@ -77,14 +44,6 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
// (pins with the same number) will be consecutive in list
sort( pinList.begin(), pinList.end(), sort_by_pin_number );
// The minimal grid size allowed to place a pin is 25 mils
// the best grid size is 50 mils, but 25 mils is still usable
// this is because all aSymbols are using a 50 mils grid to place pins, and therefore
// the wires must be on the 50 mils grid
// So raise an error if a pin is not on a 25 (or bigger :50 or 100) mils grid
const int min_grid_size = schIUScale.MilsToIU( 25 );
const int clamped_grid_size = ( aGridForPins < min_grid_size ) ? min_grid_size : aGridForPins;
for( unsigned ii = 1; ii < pinList.size(); ii++ )
{
SCH_PIN* pin = pinList[ii - 1];
@ -181,6 +140,58 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
msg += wxT( "<br><br>" );
aMessages.push_back( msg );
}
}
/**
* Check a lib symbol to find incorrect settings
* Pins not on a valid grid
* Pins duplicated
* Conflict with pins at same location
* Incorrect Power Symbols
* illegal reference prefix (cannot ends by a digit or a '?')
* @param aSymbol is the library symbol to check
* @param aMessages is a room to store error messages
* @param aGridForPins (in IU) is the grid to test pin positions ( >= 25 mils )
* should be 25, 50 or 100 mils (convered to IUs)
* @param aUnitsProvider a frame to format coordinates in messages
*/
void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
int aGridForPins, UNITS_PROVIDER* aUnitsProvider )
{
if( !aSymbol )
return;
wxString msg;
// Test reference prefix validity:
// if the symbol is saved in a library, the prefix should not ends by a digit or a '?'
// but it is acceptable if the symbol is saved to aschematic
wxString reference_base = aSymbol->GetReferenceField().GetText();
wxString illegal_end( wxT( "0123456789?" ) );
wxUniChar last_char = reference_base.Last();
if( illegal_end.Find( last_char ) != wxNOT_FOUND )
{
msg.Printf( _( "<b>Warning: reference prefix</b><br>prefix ending by '%s' can create"
" issues if saved in a symbol library" ),
illegal_end );
msg += wxT( "<br><br>" );
aMessages.push_back( msg );
}
CheckDuplicatePins( aSymbol, aMessages, aUnitsProvider );
std::vector<SCH_PIN*> pinList = aSymbol->GetPins();
sort( pinList.begin(), pinList.end(), sort_by_pin_number );
// The minimal grid size allowed to place a pin is 25 mils
// the best grid size is 50 mils, but 25 mils is still usable
// this is because all aSymbols are using a 50 mils grid to place pins, and therefore
// the wires must be on the 50 mils grid
// So raise an error if a pin is not on a 25 (or bigger :50 or 100) mils grid
const int min_grid_size = schIUScale.MilsToIU( 25 );
const int clamped_grid_size = ( aGridForPins < min_grid_size ) ? min_grid_size : aGridForPins;
// Test for a valid power aSymbol.
// A valid power aSymbol has only one unit, no alternate body styles and one pin.
@ -353,7 +364,7 @@ void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
void CheckLibSymbolGraphics( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
EDA_DRAW_FRAME* aUnitsProvider )
UNITS_PROVIDER* aUnitsProvider )
{
if( !aSymbol )
return;

View File

@ -293,7 +293,7 @@ int EE_INSPECTION_TOOL::ExcludeMarker( const TOOL_EVENT& aEvent )
extern void CheckLibSymbol( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
int aGridForPins, EDA_DRAW_FRAME* aUnitsProvider );
int aGridForPins, UNITS_PROVIDER* aUnitsProvider );
int EE_INSPECTION_TOOL::CheckSymbol( const TOOL_EVENT& aEvent )
{