diff --git a/eeschema/class_drc_erc_item.cpp b/eeschema/class_drc_erc_item.cpp index 9071dc89d4..5b013e7858 100644 --- a/eeschema/class_drc_erc_item.cpp +++ b/eeschema/class_drc_erc_item.cpp @@ -54,6 +54,10 @@ wxString DRC_ITEM::GetErrorText() const return wxString( _("A no connect symbol is connected to more than 1 pin")); case ERCE_GLOBLABEL: return wxString( _("Global label not connected to any other global label") ); + case ERCE_SIMILAR_LABELS: + return wxString( _("Labels are similar (lower/upper case difference only)") ); + case ERCE_SIMILAR_GLBL_LABELS: + return wxString( _("Global labels are similar (lower/upper case difference only)") ); default: return wxString( wxT("Unkown.") ); diff --git a/eeschema/class_netlist_object.h b/eeschema/class_netlist_object.h index f97fe77de4..68dc2b80fb 100644 --- a/eeschema/class_netlist_object.h +++ b/eeschema/class_netlist_object.h @@ -369,6 +369,32 @@ public: */ void SortListbySheet(); + /** + * Counts number of pins connected on the same net. + * Used to count all pins connected to a no connect symbol + * @return the pin count of the net starting at aNetStart + * @param aNetStart = index in list of net objects of the first item + */ + int CountPinsInNet( unsigned aNetStart ); + + /** + * Function TestforNonOrphanLabel + * Sheet labels are expected to be connected to a hierarchical label. + * Hierarchical labels are expected to be connected to a sheet label. + * Global labels are expected to be not orphan (connected to at least one other global label. + * this function tests the connection to an other suitable label + */ + void TestforNonOrphanLabel( unsigned aNetItemRef, unsigned aStartNet ); + + /** + * Function TestforSimilarLabels + * detects labels which are different when using case sensitive comparisons + * but are equal when using case insensitive comparisons + * It can be due to a mistake from designer, so this kind of labels + * is reported by TestforSimilarLabels + */ + void TestforSimilarLabels(); + #if defined(DEBUG) void DumpNetTable() @@ -403,7 +429,7 @@ private: return Objet1->GetNet() < Objet2->GetNet(); } - /* Comparison routine to sort items by Sheet Number + /* Comparison routine to sort items by Sheet path */ static bool sortItemsBySheet( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 ) { diff --git a/eeschema/dialogs/dialog_erc.cpp b/eeschema/dialogs/dialog_erc.cpp index c6792eae58..87acb30d5f 100644 --- a/eeschema/dialogs/dialog_erc.cpp +++ b/eeschema/dialogs/dialog_erc.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 Wayne Stambaugh * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -48,10 +49,19 @@ #include #include +extern int DiagErc[PIN_NMAX][PIN_NMAX]; +extern int DefaultDiagErc[PIN_NMAX][PIN_NMAX]; -bool DIALOG_ERC::m_writeErcFile = false; +bool DIALOG_ERC::m_writeErcFile = false; // saved only for the current session +bool DIALOG_ERC::m_TestSimilarLabels = true; // Save in project config +bool DIALOG_ERC::m_diagErcTableInit = false; // saved only for the current session +bool DIALOG_ERC::m_tstUniqueGlobalLabels = true; // saved only for the current session + +// Control identifiers for events +#define ID_MATRIX_0 1800 + BEGIN_EVENT_TABLE( DIALOG_ERC, DIALOG_ERC_BASE ) EVT_COMMAND_RANGE( ID_MATRIX_0, ID_MATRIX_0 + ( PIN_NMAX * PIN_NMAX ) - 1, wxEVT_COMMAND_BUTTON_CLICKED, DIALOG_ERC::ChangeErrorLevel ) @@ -72,6 +82,8 @@ DIALOG_ERC::DIALOG_ERC( SCH_EDIT_FRAME* parent ) : DIALOG_ERC::~DIALOG_ERC() { + m_TestSimilarLabels = m_cbTestSimilarLabels->GetValue(); + m_tstUniqueGlobalLabels = m_cbTestUniqueGlbLabels->GetValue(); } @@ -86,6 +98,8 @@ void DIALOG_ERC::Init() } m_WriteResultOpt->SetValue( m_writeErcFile ); + m_cbTestSimilarLabels->SetValue( m_TestSimilarLabels ); + m_cbTestUniqueGlbLabels->SetValue( m_tstUniqueGlobalLabels ); SCH_SCREENS screens; updateMarkerCounts( &screens ); @@ -232,7 +246,7 @@ void DIALOG_ERC::OnLeftClickMarkersList( wxHtmlLinkEvent& event ) void DIALOG_ERC::OnLeftDblClickMarkersList( wxMouseEvent& event ) { - // Remember: OnLeftClickMarkersList was called just berfore + // Remember: OnLeftClickMarkersList was called just before // and therefore m_lastMarkerFound was initialized. // (NULL if not found) if( m_lastMarkerFound ) @@ -257,10 +271,10 @@ void DIALOG_ERC::ReBuildMatrixPanel() wxSize bitmap_size = dummy->GetSize(); delete dummy; - if( !DiagErcTableInit ) + if( !m_diagErcTableInit ) { memcpy( DiagErc, DefaultDiagErc, sizeof(DefaultDiagErc) ); - DiagErcTableInit = true; + m_diagErcTableInit = true; } wxPoint pos; @@ -389,6 +403,10 @@ void DIALOG_ERC::ResetDefaultERCDiag( wxCommandEvent& event ) { memcpy( DiagErc, DefaultDiagErc, sizeof( DiagErc ) ); ReBuildMatrixPanel(); + m_TestSimilarLabels = true; + m_cbTestSimilarLabels->SetValue( m_TestSimilarLabels ); + m_tstUniqueGlobalLabels = true; + m_cbTestUniqueGlbLabels->SetValue( m_tstUniqueGlobalLabels ); } @@ -432,13 +450,9 @@ void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) { wxFileName fn; - if( !DiagErcTableInit ) - { - memcpy( DiagErc, DefaultDiagErc, sizeof( DefaultDiagErc ) ); - DiagErcTableInit = true; - } - m_writeErcFile = m_WriteResultOpt->GetValue(); + m_TestSimilarLabels = m_cbTestSimilarLabels->GetValue(); + m_tstUniqueGlobalLabels = m_cbTestUniqueGlbLabels->GetValue(); // Build the whole sheet list in hierarchy (sheet, not screen) SCH_SHEET_LIST sheets; @@ -511,12 +525,14 @@ void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) case NET_HIERBUSLABELMEMBER: case NET_SHEETLABEL: case NET_SHEETBUSLABELMEMBER: - case NET_GLOBLABEL: - // ERC problems when pin sheets do not match hierarchical labels. // Each pin sheet must match a hierarchical label // Each hierarchical label must match a pin sheet - TestLabel( objectsConnectedList.get(), net, nextNet ); + objectsConnectedList->TestforNonOrphanLabel( net, nextNet ); + break; + case NET_GLOBLABEL: + if( m_tstUniqueGlobalLabels ) + objectsConnectedList->TestforNonOrphanLabel( net, nextNet ); break; case NET_NOCONNECT: @@ -524,7 +540,7 @@ void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) // ERC problems when a noconnect symbol is connected to more than one pin. MinConn = NET_NC; - if( CountPinsInNet( objectsConnectedList.get(), nextNet ) > 1 ) + if( objectsConnectedList->CountPinsInNet( nextNet ) > 1 ) Diagnose( objectsConnectedList->GetItem( net ), NULL, MinConn, UNC ); break; @@ -539,6 +555,11 @@ void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) lastNet = net; } + // Test similar labels (i;e. labels which are identical when + // using case insensitive comparisons) + if( m_TestSimilarLabels ) + objectsConnectedList->TestforSimilarLabels(); + // Displays global results: updateMarkerCounts( &screens ); diff --git a/eeschema/dialogs/dialog_erc.h b/eeschema/dialogs/dialog_erc.h index e086166cf1..d7d9ff869f 100644 --- a/eeschema/dialogs/dialog_erc.h +++ b/eeschema/dialogs/dialog_erc.h @@ -27,22 +27,12 @@ #include #include - +#include // For PIN_NMAX definition #include #include "dialog_erc_listbox.h" -/* Variable locales */ -extern int DiagErc[PIN_NMAX][PIN_NMAX]; -extern bool DiagErcTableInit; // go to true after DiagErc init -extern int DefaultDiagErc[PIN_NMAX][PIN_NMAX]; - -/* Control identifiers */ -#define ID_MATRIX_0 1800 - -/*! - * DIALOG_ERC class declaration - */ +// DIALOG_ERC class declaration class DIALOG_ERC : public DIALOG_ERC_BASE { @@ -54,6 +44,11 @@ private: bool m_initialized; const SCH_MARKER* m_lastMarkerFound; static bool m_writeErcFile; + static bool m_diagErcTableInit; // go to true after DiagErc init + static bool m_tstUniqueGlobalLabels; + +public: + static bool m_TestSimilarLabels; public: DIALOG_ERC( SCH_EDIT_FRAME* parent ); diff --git a/eeschema/dialogs/dialog_erc_base.cpp b/eeschema/dialogs/dialog_erc_base.cpp index c1ef861b2c..29cb5ab41c 100644 --- a/eeschema/dialogs/dialog_erc_base.cpp +++ b/eeschema/dialogs/dialog_erc_base.cpp @@ -56,6 +56,9 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin sdiagSizer->Add( gSizeDiag, 0, wxEXPAND, 5 ); + m_staticline1 = new wxStaticLine( sdiagSizer->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + sdiagSizer->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + m_WriteResultOpt = new wxCheckBox( sdiagSizer->GetStaticBox(), wxID_ANY, _("Create ERC file report"), wxDefaultPosition, wxDefaultSize, 0 ); sdiagSizer->Add( m_WriteResultOpt, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); @@ -83,7 +86,7 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin bercSizer->Add( m_textMarkers, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); m_MarkersList = new ERC_HTML_LISTFRAME( m_PanelERC, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO|wxSUNKEN_BORDER ); - bercSizer->Add( m_MarkersList, 1, wxALL|wxEXPAND, 5 ); + bercSizer->Add( m_MarkersList, 1, wxEXPAND|wxALL, 5 ); wxBoxSizer* bbuttonsSizer; bbuttonsSizer = new wxBoxSizer( wxHORIZONTAL ); @@ -113,9 +116,30 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin m_ResetOptButton = new wxButton( m_PanelERCOptions, ID_RESET_MATRIX, _("Initialize to Default"), wxDefaultPosition, wxDefaultSize, 0 ); m_panelMatrixSizer->Add( m_ResetOptButton, 0, wxALIGN_RIGHT|wxTOP|wxRIGHT|wxLEFT, 5 ); + m_staticText8 = new wxStaticText( m_PanelERCOptions, wxID_ANY, _("Pin to pin connections"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE ); + m_staticText8->Wrap( -1 ); + m_panelMatrixSizer->Add( m_staticText8, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 ); + m_matrixPanel = new wxPanel( m_PanelERCOptions, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_panelMatrixSizer->Add( m_matrixPanel, 1, wxEXPAND | wxALL, 5 ); + m_staticline2 = new wxStaticLine( m_PanelERCOptions, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + m_panelMatrixSizer->Add( m_staticline2, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + m_staticText9 = new wxStaticText( m_PanelERCOptions, wxID_ANY, _("Label to label connections"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE ); + m_staticText9->Wrap( -1 ); + m_panelMatrixSizer->Add( m_staticText9, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + m_cbTestSimilarLabels = new wxCheckBox( m_PanelERCOptions, wxID_ANY, _("Test similar labels"), wxDefaultPosition, wxDefaultSize, 0 ); + m_cbTestSimilarLabels->SetToolTip( _("Similar labels are labels (inside a sheet) which differs only by upper/lower case") ); + + m_panelMatrixSizer->Add( m_cbTestSimilarLabels, 0, wxALL, 5 ); + + m_cbTestUniqueGlbLabels = new wxCheckBox( m_PanelERCOptions, wxID_ANY, _("Test unique global labels"), wxDefaultPosition, wxDefaultSize, 0 ); + m_cbTestUniqueGlbLabels->SetToolTip( _("Global labels are used to connect signals across the full hierarchy.\nThey are expected to be at least two labels with the same name.") ); + + m_panelMatrixSizer->Add( m_cbTestUniqueGlbLabels, 0, wxALL, 5 ); + m_PanelERCOptions->SetSizer( m_panelMatrixSizer ); m_PanelERCOptions->Layout(); diff --git a/eeschema/dialogs/dialog_erc_base.fbp b/eeschema/dialogs/dialog_erc_base.fbp index aa6589a1e8..06d1db56a7 100644 --- a/eeschema/dialogs/dialog_erc_base.fbp +++ b/eeschema/dialogs/dialog_erc_base.fbp @@ -44,7 +44,7 @@ DIALOG_ERC_BASE - 519,457 + 519,464 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Electrical Rules Checker @@ -815,6 +815,87 @@ + + 5 + wxEXPAND|wxTOP|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline1 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 wxTOP|wxBOTTOM|wxRIGHT @@ -1177,7 +1258,7 @@ 5 - wxALL|wxEXPAND + wxEXPAND|wxALL 1 1 @@ -1708,6 +1789,89 @@ + + 5 + wxRIGHT|wxLEFT|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Pin to pin connections + + 0 + + + 0 + + 1 + m_staticText8 + 1 + + + protected + 1 + + Resizable + 1 + + wxALIGN_CENTRE + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + 5 wxEXPAND | wxALL @@ -1788,6 +1952,346 @@ + + 5 + wxEXPAND|wxTOP|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline2 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Label to label connections + + 0 + + + 0 + + 1 + m_staticText9 + 1 + + + protected + 1 + + Resizable + 1 + + wxALIGN_CENTRE + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Test similar labels + + 0 + + + 0 + + 1 + m_cbTestSimilarLabels + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Similar labels are labels (inside a sheet) which differs only by upper/lower case + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Test unique global labels + + 0 + + + 0 + + 1 + m_cbTestUniqueGlbLabels + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Global labels are used to connect signals across the full hierarchy. They are expected to be at least two labels with the same name. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eeschema/dialogs/dialog_erc_base.h b/eeschema/dialogs/dialog_erc_base.h index 007f9462af..1d1f67aeb3 100644 --- a/eeschema/dialogs/dialog_erc_base.h +++ b/eeschema/dialogs/dialog_erc_base.h @@ -23,6 +23,7 @@ class ERC_HTML_LISTFRAME; #include #include #include +#include #include #include #include @@ -56,6 +57,7 @@ class DIALOG_ERC_BASE : public DIALOG_SHIM wxTextCtrl* m_LastWarningCount; wxStaticText* m_LastErrCountText; wxTextCtrl* m_LastErrCount; + wxStaticLine* m_staticline1; wxCheckBox* m_WriteResultOpt; wxStaticText* m_titleMessages; wxTextCtrl* m_MessagesList; @@ -66,7 +68,12 @@ class DIALOG_ERC_BASE : public DIALOG_SHIM wxButton* m_buttonClose; wxPanel* m_PanelERCOptions; wxButton* m_ResetOptButton; + wxStaticText* m_staticText8; wxPanel* m_matrixPanel; + wxStaticLine* m_staticline2; + wxStaticText* m_staticText9; + wxCheckBox* m_cbTestSimilarLabels; + wxCheckBox* m_cbTestUniqueGlbLabels; // Virtual event handlers, overide them in your derived class virtual void OnCloseErcDialog( wxCloseEvent& event ) { event.Skip(); } @@ -80,7 +87,7 @@ class DIALOG_ERC_BASE : public DIALOG_SHIM public: - DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Electrical Rules Checker"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 519,457 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Electrical Rules Checker"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 519,464 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_ERC_BASE(); }; diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index 1b585dbf1e..804045e45c 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include @@ -438,16 +439,18 @@ PARAM_CFG_ARRAY& SCH_EDIT_FRAME::GetProjectFileParametersList() */ m_projectFileParams.push_back( new PARAM_CFG_WXSTRING( wxT( "NetFmtName" ), - &m_netListFormat) ); + &m_netListFormat) ); m_projectFileParams.push_back( new PARAM_CFG_BOOL( wxT( "SpiceForceRefPrefix" ), - &m_spiceNetlistAddReferencePrefix, false ) ); + &m_spiceNetlistAddReferencePrefix, false ) ); m_projectFileParams.push_back( new PARAM_CFG_BOOL( wxT( "SpiceUseNetNumbers" ), - &m_spiceNetlistUseNetcodeAsNetname, false ) ); + &m_spiceNetlistUseNetcodeAsNetname, false ) ); m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "LabSize" ), - &s_defaultTextSize, - DEFAULT_SIZE_TEXT, 5, - 1000 ) ); + &s_defaultTextSize, + DEFAULT_SIZE_TEXT, 5, 1000 ) ); + + m_projectFileParams.push_back( new PARAM_CFG_BOOL( wxT( "ERC_TestSimilarLabels" ), + &DIALOG_ERC::m_TestSimilarLabels, true ) ); return m_projectFileParams; } diff --git a/eeschema/erc.cpp b/eeschema/erc.cpp index 099249cf60..1105566086 100644 --- a/eeschema/erc.cpp +++ b/eeschema/erc.cpp @@ -119,9 +119,9 @@ const wxString CommentERC_V[] = /* Look up table which gives the diag for a pair of connected pins * Can be modified by ERC options. * at start up: must be loaded by DefaultDiagErc + * Can be modified in dialog ERC */ int DiagErc[PIN_NMAX][PIN_NMAX]; -bool DiagErcTableInit; // go to true after DiagErc init /** * Default Look up table which gives the ERC error level for a pair of connected pins @@ -196,6 +196,8 @@ int TestDuplicateSheetNames( bool aCreateMarker ) continue; // We have found a second sheet: compare names + // we are using case insensitive comparison to avoid mistakes between + // similar names like Mysheet and mysheet if( ( (SCH_SHEET*) item )->GetName().CmpNoCase( ( ( SCH_SHEET* ) test_item )->GetName() ) == 0 ) { @@ -502,20 +504,19 @@ void TestOthersItems( NETLIST_OBJECT_LIST* aList, } } - -int CountPinsInNet( NETLIST_OBJECT_LIST* aList, unsigned aNetStart ) +int NETLIST_OBJECT_LIST::CountPinsInNet( unsigned aNetStart ) { int count = 0; - int curr_net = aList->GetItemNet( aNetStart ); + int curr_net = GetItemNet( aNetStart ); /* Test pins connected to NetItemRef */ - for( unsigned item = aNetStart; item < aList->size(); item++ ) + for( unsigned item = aNetStart; item < size(); item++ ) { // We examine only a given net. We stop the search if the net changes - if( curr_net != aList->GetItemNet( item ) ) // End of net + if( curr_net != GetItemNet( item ) ) // End of net break; - if( aList->GetItemType( item ) == NET_PIN ) + if( GetItemType( item ) == NET_PIN ) count++; } @@ -571,7 +572,7 @@ bool WriteDiagnosticERC( const wxString& aFullFileName ) msg << wxString::Format( _( "\n ** ERC messages: %d Errors %d Warnings %d\n" ), total_count, err_count, warn_count ); - // Currently: write report unsing UTF8 (as usual in Kicad). + // Currently: write report using UTF8 (as usual in Kicad). // TODO: see if we can use the current encoding page (mainly for Windows users), // Or other format (HTML?) file.Write( msg ); @@ -582,7 +583,7 @@ bool WriteDiagnosticERC( const wxString& aFullFileName ) } -void TestLabel( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigned aStartNet ) +void NETLIST_OBJECT_LIST::TestforNonOrphanLabel( unsigned aNetItemRef, unsigned aStartNet ) { unsigned netItemTst = aStartNet; int erc = 1; @@ -594,24 +595,246 @@ void TestLabel( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigned aStar continue; /* Is always in the same net? */ - if( ( netItemTst == aList->size() ) - || ( aList->GetItemNet( aNetItemRef ) != aList->GetItemNet( netItemTst ) ) ) + if( ( netItemTst == size() ) + || ( GetItemNet( aNetItemRef ) != GetItemNet( netItemTst ) ) ) { /* End Netcode found. */ if( erc ) { /* Glabel or SheetLabel orphaned. */ - Diagnose( aList->GetItem( aNetItemRef ), NULL, -1, WAR ); + Diagnose( GetItem( aNetItemRef ), NULL, -1, WAR ); } return; } - if( aList->GetItem( aNetItemRef )->IsLabelConnected( aList->GetItem( netItemTst ) ) ) + if( GetItem( aNetItemRef )->IsLabelConnected( GetItem( netItemTst ) ) ) erc = 0; //same thing, different order. - if( aList->GetItem( netItemTst )->IsLabelConnected( aList->GetItem( aNetItemRef ) ) ) + if( GetItem( netItemTst )->IsLabelConnected( GetItem( aNetItemRef ) ) ) erc = 0; } } + + +// this code try to detect similar labels, i.e. labels which are identical +// when they are compared using case insensitive coparisons. + + +// A helper struct to compare NETLIST_OBJECT items by sheetpath and label texts +// for a std::set container +// the full text is "sheetpath+label" for local labels and "label" for global labels +struct compare_labels +{ + bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) + { + wxString str1 = lab1->m_SheetPath.Path() + lab1->m_Label; + wxString str2 = lab2->m_SheetPath.Path() + lab2->m_Label; + + return str1.Cmp( str2 ) < 0; + } +}; + +struct compare_label_names +{ + bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) + { + return lab1->m_Label.Cmp( lab2->m_Label ) < 0; + } +}; + +struct compare_paths +{ + bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) + { + return lab1->m_SheetPath.Path().Cmp( lab2->m_SheetPath.Path() ) < 0; + } +}; + +// Helper functions to build the warning messages about Similar Labels: +static int countIndenticalLabels( std::vector& aList, NETLIST_OBJECT* aLabel ); +static void SimilarLabelsDiagnose( NETLIST_OBJECT* aItemA, NETLIST_OBJECT* aItemB ); + + +void NETLIST_OBJECT_LIST::TestforSimilarLabels() +{ + // Similar labels which are different when using case sensitive comparisons + // but are equal when using case insensitive comparisons + + // list of all labels (used the better item to build diag messages) + std::vector fullLabelList; + // list of all labels , each label appears only once (used to to detect similar labels) + std::set uniqueLabelList; + wxString msg; + + // Build a list of differents labels. If inside a given sheet there are + // more than one given label, only one label is stored. + // not also the sheet labels are not taken in account for 2 reasons: + // * they are in the root sheet but they are seen only from the child sheet + // * any mismatch between child sheet hierarchical labels and the sheet label + // already detected by ERC + for( unsigned netItem = 0; netItem < size(); ++netItem ) + { + switch( GetItemType( netItem ) ) + { + case NET_LABEL: + case NET_BUSLABELMEMBER: + case NET_PINLABEL: + case NET_GLOBBUSLABELMEMBER: + case NET_HIERLABEL: + case NET_HIERBUSLABELMEMBER: + case NET_GLOBLABEL: + // add this label in lists + uniqueLabelList.insert( GetItem( netItem ) ); + fullLabelList.push_back( GetItem( netItem ) ); + break; + + case NET_SHEETLABEL: + case NET_SHEETBUSLABELMEMBER: + default: + break; + } + } + + // build global labels and compare + std::set loc_labelList; + std::set::const_iterator it; + + for( it = uniqueLabelList.begin(); it != uniqueLabelList.end(); ++it ) + { + if( (*it)->IsLabelGlobal() ) + loc_labelList.insert( *it ); + } + + // compare global labels (same label names appears only once in list) + for( it = loc_labelList.begin(); it != loc_labelList.end(); ++it ) + { + std::set::const_iterator it_aux = it; + + for( ++it_aux; it_aux != loc_labelList.end(); ++it_aux ) + { + if( (*it)->m_Label.CmpNoCase( (*it_aux)->m_Label ) == 0 ) + { + // Create new marker for ERC. + int cntA = countIndenticalLabels( fullLabelList, *it ); + int cntB = countIndenticalLabels( fullLabelList, *it_aux ); + + if( cntA <= cntB ) + SimilarLabelsDiagnose( (*it), (*it_aux) ); + else + SimilarLabelsDiagnose( (*it_aux), (*it) ); + } + } + } + + // Build paths list + std::set pathsList; + + for( it = uniqueLabelList.begin(); it != uniqueLabelList.end(); ++it ) + pathsList.insert( *it ); + + // Examine each label inside a sheet path: + for( it = pathsList.begin(); it != pathsList.end(); ++it ) + { + loc_labelList.clear(); + + std::set::const_iterator it_aux = uniqueLabelList.begin(); + + for( ; it_aux != uniqueLabelList.end(); ++it_aux ) + { + if( (*it)->m_SheetPath.Path() == (*it_aux)->m_SheetPath.Path() ) + loc_labelList.insert( *it_aux ); + } + + // at this point, loc_labelList contains labels of the current sheet path. + // Detect similar labels (same label names appears only once in list) + std::set::const_iterator ref_it; + + for( ref_it = loc_labelList.begin(); ref_it != loc_labelList.end(); ++ref_it ) + { + NETLIST_OBJECT* ref_item = *ref_it; + it_aux = ref_it; + + for( ++it_aux; it_aux != loc_labelList.end(); ++it_aux ) + { + // global label versus global label was already examined. + // here, at least one label must be local + if( ref_item->IsLabelGlobal() && (*it_aux)->IsLabelGlobal() ) + continue; + + if( ref_item->m_Label.CmpNoCase( (*it_aux)->m_Label ) == 0 ) + { + // Create new marker for ERC. + int cntA = countIndenticalLabels( fullLabelList, ref_item ); + int cntB = countIndenticalLabels( fullLabelList, *it_aux ); + + if( cntA <= cntB ) + SimilarLabelsDiagnose( ref_item, (*it_aux) ); + else + SimilarLabelsDiagnose( (*it_aux), ref_item ); + } + } + } + } +} + +// Helper function: count the number of labels identical to aLabel +// for global label: global labels in the full project +// for local label: all labels in the current sheet +static int countIndenticalLabels( std::vector& aList, NETLIST_OBJECT* aLabel ) +{ + int count = 0; + + if( aLabel->IsLabelGlobal() ) + { + for( unsigned netItem = 0; netItem < aList.size(); ++netItem ) + { + NETLIST_OBJECT* item = aList[netItem]; + + if( item->IsLabelGlobal() && item->m_Label == aLabel->m_Label ) + count++; + } + } + else + { + for( unsigned netItem = 0; netItem < aList.size(); ++netItem ) + { + NETLIST_OBJECT* item = aList[netItem]; + + if( item->m_Label == aLabel->m_Label && + item->m_SheetPath.Path() == aLabel->m_SheetPath.Path() ) + count++; + } + } + + return count; +} + +// Helper function: creates a marker for similar labels ERC warning +static void SimilarLabelsDiagnose( NETLIST_OBJECT* aItemA, NETLIST_OBJECT* aItemB ) +{ + // Create new marker for ERC. + SCH_MARKER* marker = new SCH_MARKER(); + + marker->SetTimeStamp( GetNewTimeStamp() ); + marker->SetMarkerType( MARKER_BASE::MARKER_ERC ); + marker->SetErrorLevel( MARKER_BASE::MARKER_SEVERITY_WARNING ); + SCH_SCREEN* screen = aItemA->m_SheetPath.LastScreen(); + screen->Append( marker ); + + wxString fmt = aItemA->IsLabelGlobal() ? + _( "Global label '%s' (sheet '%s') looks like:" ) : + _( "Local label '%s' (sheet '%s') looks like:" ); + wxString msg; + + msg.Printf( fmt, GetChars( aItemA->m_Label ), GetChars( aItemA->m_SheetPath.PathHumanReadable() ) ); + marker->SetData( aItemA->IsLabelGlobal() && aItemB->IsLabelGlobal() ? + ERCE_SIMILAR_GLBL_LABELS : ERCE_SIMILAR_LABELS, + aItemA->m_Start, msg, aItemA->m_Start ); + + fmt = aItemB->IsLabelGlobal() ? _( "Global label '%s' (sheet '%s')" ) : + _( "Local label '%s' (sheet '%s')" ); + msg.Printf( fmt, GetChars( aItemB->m_Label ), GetChars( aItemB->m_SheetPath.PathHumanReadable() ) ); + marker->SetAuxiliaryData( msg, aItemB->m_Start ); +} diff --git a/eeschema/erc.h b/eeschema/erc.h index 708fb6a4d0..76cec12b98 100644 --- a/eeschema/erc.h +++ b/eeschema/erc.h @@ -31,7 +31,7 @@ #define _ERC_H -class EDA_DRAW_PANEL; +//class EDA_DRAW_PANEL; class NETLIST_OBJECT; class NETLIST_OBJECT_LIST; @@ -58,6 +58,8 @@ extern const wxString CommentERC_V[]; #define ERCE_HIERACHICAL_LABEL 6 // mismatch between hierarchical labels and pins sheets #define ERCE_NOCONNECT_CONNECTED 7 // a no connect symbol is connected to more than 1 pin #define ERCE_GLOBLABEL 8 // global label not connected to any other global label +#define ERCE_SIMILAR_LABELS 9 // 2 labels are equal fir case insensitive comparisons +#define ERCE_SIMILAR_GLBL_LABELS 10 // 2 labels are equal fir case insensitive comparisons /* Minimal connection table */ #define NPI 4 // Net with Pin isolated, this pin has type Not Connected and must be left N.C. @@ -73,14 +75,14 @@ extern const wxString CommentERC_V[]; * * @param aFullFileName A wxString object containing the file name and path. */ -extern bool WriteDiagnosticERC( const wxString& aFullFileName ); +bool WriteDiagnosticERC( const wxString& aFullFileName ); /** * Performs ERC testing and creates an ERC marker to show the ERC problem for aNetItemRef * or between aNetItemRef and aNetItemTst. * if MinConn < 0: this is an error on labels */ -extern void Diagnose( NETLIST_OBJECT* NetItemRef, NETLIST_OBJECT* NetItemTst, +void Diagnose( NETLIST_OBJECT* NetItemRef, NETLIST_OBJECT* NetItemTst, int MinConnexion, int Diag ); /** @@ -92,27 +94,10 @@ extern void Diagnose( NETLIST_OBJECT* NetItemRef, NETLIST_OBJECT* NetItemTst, * @param aMinConnexion = a pointer to a variable to store the minimal connection * found( NOD, DRV, NPI, NET_NC) */ -extern void TestOthersItems( NETLIST_OBJECT_LIST* aList, +void TestOthersItems( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigned aNetStart, int* aMinConnexion ); -/** - * Counts number of pins connected on the same net. - * Used to find all pins conected to a no connect symbol - * @return the pin count of the net starting at aNetStart - * @param aNetStart = index in list of net objects of the first item - * @param aList = a reference to the list of connected objects - */ -int CountPinsInNet( NETLIST_OBJECT_LIST* aList, unsigned aNetStart ); - - -/** - * Function TestLabel - * performs an ERC on a sheet labels to verify that it is connected to a corresponding - * sub sheet global label. - */ -extern void TestLabel( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigned aStartNet ); - /** * Function TestDuplicateSheetNames( ) * inside a given sheet, one cannot have sheets with duplicate names (file @@ -121,7 +106,7 @@ extern void TestLabel( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigne * @param aCreateMarker: true = create error markers in schematic, * false = calculate error count only */ -extern int TestDuplicateSheetNames( bool aCreateMarker ); +int TestDuplicateSheetNames( bool aCreateMarker ); #endif // _ERC_H diff --git a/eeschema/netlist.cpp b/eeschema/netlist.cpp index c7a3aada51..ebc324570a 100644 --- a/eeschema/netlist.cpp +++ b/eeschema/netlist.cpp @@ -52,19 +52,12 @@ /** @brief Kicad can use case sensitive or case insensitive comparisons for labels * Currently, it uses case insensitive. - * Can be changed by defining LABEL_CASE_SENSITIVE (uncomment next line). + * Can be changed by comment/uncomment next lines. */ -//#define LABEL_CASE_SENSITIVE -/// Compiler controlled string compare function, either case independent or not: inline int CmpLabel_KEEPCASE( const wxString& aString1, const wxString& aString2 ) { -#ifdef LABEL_CASE_SENSITIVE - // case specificity, the normal behavior: - return aString1.Cmp( aString2 ); -#else - // case independence (only for guys who want that: not recommended) - return aString1.CmpNoCase( aString2 ); -#endif + return aString1.Cmp( aString2 ); // case sensitive + //return aString1.CmpNoCase( aString2 ); // case insensitive }