Move pin table checks to new connectivity system
This commit is contained in:
parent
a52e3fc87a
commit
48d7c46a53
|
@ -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 );
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
143
eeschema/erc.cpp
143
eeschema/erc.cpp
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue