diff --git a/eeschema/connection_graph.cpp b/eeschema/connection_graph.cpp index e806c8c4ce..a1b89fc62b 100644 --- a/eeschema/connection_graph.cpp +++ b/eeschema/connection_graph.cpp @@ -2421,7 +2421,11 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph { for( SCH_PIN* testPin : pins ) { - if( testPin->ConnectedItems( sheet ).empty() ) + // We only apply this test to power symbols, because other symbols have invisible + // pins that are meant to be dangling, but the KiCad standard library power symbols + // have invisible pins that are *not* meant to be dangling. + if( testPin->GetLibPin()->GetParent()->IsPower() && + testPin->ConnectedItems( sheet ).empty() ) { std::shared_ptr ercItem = ERC_ITEM::Create( ERCE_PIN_NOT_CONNECTED ); ercItem->SetItems( testPin ); diff --git a/eeschema/dialogs/dialog_erc.cpp b/eeschema/dialogs/dialog_erc.cpp index 9d61625e37..aecabff865 100644 --- a/eeschema/dialogs/dialog_erc.cpp +++ b/eeschema/dialogs/dialog_erc.cpp @@ -272,90 +272,14 @@ void DIALOG_ERC::TestErc( REPORTER& aReporter ) // Reset the connection type indicator objectsConnectedList->ResetConnectionsType(); - unsigned lastItemIdx = 0; - unsigned nextItemIdx = 0; - int MinConn = NOC; + aReporter.ReportTail( _( "Checking pins...\n" ), RPT_SEVERITY_INFO ); - // Check that a pin appears in only one net. This check is necessary because multi-unit - // components that have shared pins could be wired to different nets. - std::unordered_map pin_to_net_map; + if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_NET ) ) + tester.TestMultUnitPinConflicts(); - // The netlist generated by SCH_EDIT_FRAME::BuildNetListBase is sorted by net number, which - // means we can group netlist items into ranges that live in the same net. The range from - // nextItem to the current item (exclusive) needs to be checked against the current item. - // The lastItem variable is used as a helper to pass the last item's number from one loop - // iteration to the next, which simplifies the initial pass. - aReporter.ReportTail( _( "Checking connections...\n" ), RPT_SEVERITY_INFO ); - for( unsigned itemIdx = 0; itemIdx < objectsConnectedList->size(); itemIdx++ ) - { - auto item = objectsConnectedList->GetItem( itemIdx ); - auto lastItem = objectsConnectedList->GetItem( lastItemIdx ); - - auto lastNet = lastItem->GetNet(); - auto net = item->GetNet(); - - wxASSERT_MSG( lastNet <= net, wxT( "Netlist not correctly ordered" ) ); - - if( lastNet != net ) - { - // New net found: - MinConn = NOC; - nextItemIdx = itemIdx; - } - - switch( item->m_Type ) - { - // These items do not create erc problems - case NETLIST_ITEM::ITEM_UNSPECIFIED: - case NETLIST_ITEM::SEGMENT: - case NETLIST_ITEM::BUS: - case NETLIST_ITEM::JUNCTION: - case NETLIST_ITEM::LABEL: - case NETLIST_ITEM::BUSLABELMEMBER: - case NETLIST_ITEM::PINLABEL: - case NETLIST_ITEM::GLOBBUSLABELMEMBER: - break; - - // TODO(JE) Port this to the new system - case NETLIST_ITEM::PIN: - { - // Check if this pin has appeared before on a different net - if( item->m_Link && settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_NET ) ) - { - wxString ref = item->GetComponentParent()->GetRef( &item->m_SheetPath ); - wxString pin_name = ref + "_" + item->m_PinNum; - wxString msg; - - if( pin_to_net_map.count( pin_name ) == 0 ) - { - pin_to_net_map[pin_name] = item->GetNetName(); - } - else if( pin_to_net_map[pin_name] != item->GetNetName() ) - { - msg.Printf( _( "Pin %s is connected to both %s and %s" ), - item->m_PinNum, - pin_to_net_map[pin_name], - item->GetNetName() ); - - std::shared_ptr ercItem = ERC_ITEM::Create( ERCE_DIFFERENT_UNIT_NET ); - ercItem->SetErrorMessage( msg ); - ercItem->SetItems( item->m_Comp ); - - SCH_MARKER* marker = new SCH_MARKER( ercItem, item->m_Start ); - item->m_SheetPath.LastScreen()->Append( marker ); - } - } - - // Look for ERC problems between pins: - tester.TestOthersItems( objectsConnectedList.get(), itemIdx, nextItemIdx, &MinConn ); - break; - } - default: - break; - } - - lastItemIdx = itemIdx; - } + // Test pins on each net against the pin connection table + if( settings.IsTestEnabled( ERCE_PIN_TO_PIN_ERROR ) ) + tester.TestPinToPin(); // Test similar labels (i;e. labels which are identical when // using case insensitive comparisons) @@ -604,7 +528,7 @@ void DIALOG_ERC::deleteAllMarkers( bool aIncludeExclusions ) // Clear current selection list to avoid selection of deleted items m_parent->GetToolManager()->RunAction( EE_ACTIONS::clearSelection, true ); - m_markerTreeModel->DeleteItems( false, true, aIncludeExclusions ); + m_markerTreeModel->DeleteItems( false, aIncludeExclusions, true ); } diff --git a/eeschema/erc.cpp b/eeschema/erc.cpp index 5e098fefd9..611b1a58da 100644 --- a/eeschema/erc.cpp +++ b/eeschema/erc.cpp @@ -28,19 +28,20 @@ * @brief Electrical Rules Check implementation. */ +#include "connection_graph.h" +#include #include #include -#include -#include #include -#include +#include +#include #include -#include #include +#include #include -#include #include #include +#include /* ERC tests : @@ -580,6 +581,138 @@ int ERC_TESTER::TestNoConnectPins() } +int ERC_TESTER::TestPinToPin() +{ + ERC_SETTINGS& settings = m_schematic->ErcSettings(); + const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap(); + + int errors = 0; + + for( const std::pair> net : nets ) + { + std::vector pins; + std::unordered_map pinToScreenMap; + + for( CONNECTION_SUBGRAPH* subgraph: net.second ) + { + for( EDA_ITEM* item : subgraph->m_items ) + { + if( item->Type() == SCH_PIN_T ) + { + pins.emplace_back( static_cast( item ) ); + pinToScreenMap[item] = subgraph->m_sheet.LastScreen(); + } + } + } + + // Single-pin nets are handled elsewhere + if( pins.size() < 2 ) + continue; + + std::set> tested; + + for( SCH_PIN* refPin : pins ) + { + ELECTRICAL_PINTYPE refType = refPin->GetType(); + + for( SCH_PIN* testPin : pins ) + { + if( testPin == refPin ) + continue; + + std::pair pair1 = std::make_pair( refPin, testPin ); + std::pair pair2 = std::make_pair( testPin, refPin ); + + if( tested.count( pair1 ) || tested.count( pair2 ) ) + continue; + + tested.insert( pair1 ); + tested.insert( pair2 ); + + ELECTRICAL_PINTYPE testType = testPin->GetType(); + + PIN_ERROR erc = settings.GetPinMapValue( refType, testType ); + + if( erc != PIN_ERROR::OK ) + { + std::shared_ptr ercItem = + ERC_ITEM::Create( erc == PIN_ERROR::WARNING ? ERCE_PIN_TO_PIN_WARNING : + ERCE_PIN_TO_PIN_ERROR ); + ercItem->SetItems( refPin, testPin ); + + ercItem->SetErrorMessage( + wxString::Format( _( "Pins of type %s and %s are connected" ), + ElectricalPinTypeGetText( refType ), + ElectricalPinTypeGetText( testType ) ) ); + + SCH_MARKER* marker = + new SCH_MARKER( ercItem, refPin->GetTransformedPosition() ); + pinToScreenMap[refPin]->Append( marker ); + errors++; + } + } + } + } + + return errors; +} + + +int ERC_TESTER::TestMultUnitPinConflicts() +{ + const NET_MAP& nets = m_schematic->ConnectionGraph()->GetNetMap(); + + int errors = 0; + + std::unordered_map> pinToNetMap; + + for( const std::pair> net : nets ) + { + const wxString& netName = net.first.first; + std::vector pins; + + for( CONNECTION_SUBGRAPH* subgraph : net.second ) + { + for( EDA_ITEM* item : subgraph->m_items ) + { + if( item->Type() == SCH_PIN_T ) + { + SCH_PIN* pin = static_cast( item ); + + if( !pin->GetLibPin()->GetParent()->IsMulti() ) + continue; + + wxString name = ( pin->GetParentComponent()->GetRef( &subgraph->m_sheet ) + + ":" + pin->GetName() ); + + if( !pinToNetMap.count( name ) ) + { + pinToNetMap[name] = std::make_pair( netName, pin ); + } + else if( pinToNetMap[name].first != netName ) + { + std::shared_ptr ercItem = + ERC_ITEM::Create( ERCE_DIFFERENT_UNIT_NET ); + + ercItem->SetErrorMessage( wxString::Format( + _( "Pin %s is connected to both %s and %s" ), + pin->GetNumber(), netName, pinToNetMap[name].first ) ); + + ercItem->SetItems( pin, pinToNetMap[name].second ); + + SCH_MARKER* marker = new SCH_MARKER( ercItem, + pin->GetTransformedPosition() ); + subgraph->m_sheet.LastScreen()->Append( marker ); + } + } + } + } + } + + return errors; +} + + // this code try to detect similar labels, i.e. labels which are identical // when they are compared using case insensitive coparisons. diff --git a/eeschema/erc.h b/eeschema/erc.h index 6bb6d8c4cd..273f818e55 100644 --- a/eeschema/erc.h +++ b/eeschema/erc.h @@ -106,6 +106,18 @@ public: */ int TestNoConnectPins(); + /** + * Checks the full netlist against the pin-to-pin connectivity requirements + * @return the error count + */ + int TestPinToPin(); + + /** + * Checks if shared pins on multi-unit components have been connected to different nets + * @return the error count + */ + int TestMultUnitPinConflicts(); + private: /** * Performs ERC testing and creates an ERC marker to show the ERC problem for aNetItemRef diff --git a/eeschema/erc_settings.h b/eeschema/erc_settings.h index 73f89c412c..f28f93e7c9 100644 --- a/eeschema/erc_settings.h +++ b/eeschema/erc_settings.h @@ -114,7 +114,7 @@ public: bool IsTestEnabled( int aErrorCode ) const { - return m_Severities.at( aErrorCode ) != RPT_SEVERITY_IGNORE; + return GetSeverity( aErrorCode ) != RPT_SEVERITY_IGNORE; } int GetSeverity( int aErrorCode ) const;