Move pin table checks to new connectivity system

This commit is contained in:
Jon Evans 2020-08-30 15:25:31 -04:00
parent a52e3fc87a
commit 48d7c46a53
5 changed files with 163 additions and 90 deletions

View File

@ -2421,7 +2421,11 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
{ {
for( SCH_PIN* testPin : pins ) 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<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_PIN_NOT_CONNECTED ); std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_PIN_NOT_CONNECTED );
ercItem->SetItems( testPin ); ercItem->SetItems( testPin );

View File

@ -272,90 +272,14 @@ void DIALOG_ERC::TestErc( REPORTER& aReporter )
// Reset the connection type indicator // Reset the connection type indicator
objectsConnectedList->ResetConnectionsType(); objectsConnectedList->ResetConnectionsType();
unsigned lastItemIdx = 0; aReporter.ReportTail( _( "Checking pins...\n" ), RPT_SEVERITY_INFO );
unsigned nextItemIdx = 0;
int MinConn = NOC;
// Check that a pin appears in only one net. This check is necessary because multi-unit if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_NET ) )
// components that have shared pins could be wired to different nets. tester.TestMultUnitPinConflicts();
std::unordered_map<wxString, wxString> pin_to_net_map;
// The netlist generated by SCH_EDIT_FRAME::BuildNetListBase is sorted by net number, which // Test pins on each net against the pin connection table
// means we can group netlist items into ranges that live in the same net. The range from if( settings.IsTestEnabled( ERCE_PIN_TO_PIN_ERROR ) )
// nextItem to the current item (exclusive) needs to be checked against the current item. tester.TestPinToPin();
// 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<ERC_ITEM> 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 similar labels (i;e. labels which are identical when // Test similar labels (i;e. labels which are identical when
// using case insensitive comparisons) // using case insensitive comparisons)
@ -604,7 +528,7 @@ void DIALOG_ERC::deleteAllMarkers( bool aIncludeExclusions )
// Clear current selection list to avoid selection of deleted items // Clear current selection list to avoid selection of deleted items
m_parent->GetToolManager()->RunAction( EE_ACTIONS::clearSelection, true ); m_parent->GetToolManager()->RunAction( EE_ACTIONS::clearSelection, true );
m_markerTreeModel->DeleteItems( false, true, aIncludeExclusions ); m_markerTreeModel->DeleteItems( false, aIncludeExclusions, true );
} }

View File

@ -28,19 +28,20 @@
* @brief Electrical Rules Check implementation. * @brief Electrical Rules Check implementation.
*/ */
#include "connection_graph.h"
#include <erc.h>
#include <fctsys.h> #include <fctsys.h>
#include <kicad_string.h> #include <kicad_string.h>
#include <sch_edit_frame.h>
#include <netlist_object.h>
#include <lib_pin.h> #include <lib_pin.h>
#include <erc.h> #include <netlist_object.h>
#include <sch_edit_frame.h>
#include <sch_marker.h> #include <sch_marker.h>
#include <sch_sheet.h>
#include <sch_reference_list.h> #include <sch_reference_list.h>
#include <sch_sheet.h>
#include <schematic.h> #include <schematic.h>
#include <wx/ffile.h>
#include <ws_draw_item.h> #include <ws_draw_item.h>
#include <ws_proxy_view_item.h> #include <ws_proxy_view_item.h>
#include <wx/ffile.h>
/* ERC tests : /* 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_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
{
std::vector<SCH_PIN*> pins;
std::unordered_map<EDA_ITEM*, SCH_SCREEN*> 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<SCH_PIN*>( item ) );
pinToScreenMap[item] = subgraph->m_sheet.LastScreen();
}
}
}
// Single-pin nets are handled elsewhere
if( pins.size() < 2 )
continue;
std::set<std::pair<SCH_PIN*, SCH_PIN*>> tested;
for( SCH_PIN* refPin : pins )
{
ELECTRICAL_PINTYPE refType = refPin->GetType();
for( SCH_PIN* testPin : pins )
{
if( testPin == refPin )
continue;
std::pair<SCH_PIN*, SCH_PIN*> pair1 = std::make_pair( refPin, testPin );
std::pair<SCH_PIN*, SCH_PIN*> 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<ERC_ITEM> 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<wxString, std::pair<wxString, SCH_PIN*>> pinToNetMap;
for( const std::pair<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> net : nets )
{
const wxString& netName = net.first.first;
std::vector<SCH_PIN*> 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<SCH_PIN*>( 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<ERC_ITEM> 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 // this code try to detect similar labels, i.e. labels which are identical
// when they are compared using case insensitive coparisons. // when they are compared using case insensitive coparisons.

View File

@ -106,6 +106,18 @@ public:
*/ */
int TestNoConnectPins(); 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: private:
/** /**
* Performs ERC testing and creates an ERC marker to show the ERC problem for aNetItemRef * Performs ERC testing and creates an ERC marker to show the ERC problem for aNetItemRef

View File

@ -114,7 +114,7 @@ public:
bool IsTestEnabled( int aErrorCode ) const bool IsTestEnabled( int aErrorCode ) const
{ {
return m_Severities.at( aErrorCode ) != RPT_SEVERITY_IGNORE; return GetSeverity( aErrorCode ) != RPT_SEVERITY_IGNORE;
} }
int GetSeverity( int aErrorCode ) const; int GetSeverity( int aErrorCode ) const;