ADDED: ERC for missing units
Reports a warning (by default) for missing units Reports an error for missing units with power input pins Reports a warning for missing units with input pins Reports a warning for missing units with bidi pins Fixes https://gitlab.com/kicad/code/kicad/issues/1922
This commit is contained in:
parent
458935bb5a
commit
09cc6decaf
|
@ -485,6 +485,8 @@ void DIALOG_ERC::testErc()
|
||||||
m_parent->RecalculateConnections( NO_CLEANUP );
|
m_parent->RecalculateConnections( NO_CLEANUP );
|
||||||
sch->ConnectionGraph()->RunERC();
|
sch->ConnectionGraph()->RunERC();
|
||||||
|
|
||||||
|
AdvancePhase( _( "Checking units..." ) );
|
||||||
|
|
||||||
// Test is all units of each multiunit symbol have the same footprint assigned.
|
// Test is all units of each multiunit symbol have the same footprint assigned.
|
||||||
if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_FP ) )
|
if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_FP ) )
|
||||||
{
|
{
|
||||||
|
@ -492,6 +494,14 @@ void DIALOG_ERC::testErc()
|
||||||
tester.TestMultiunitFootprints();
|
tester.TestMultiunitFootprints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( settings.IsTestEnabled( ERCE_MISSING_UNIT )
|
||||||
|
|| settings.IsTestEnabled( ERCE_MISSING_INPUT_PIN )
|
||||||
|
|| settings.IsTestEnabled( ERCE_MISSING_POWER_INPUT_PIN )
|
||||||
|
|| settings.IsTestEnabled( ERCE_MISSING_BIDI_PIN ) )
|
||||||
|
{
|
||||||
|
tester.TestMissingUnits();
|
||||||
|
}
|
||||||
|
|
||||||
AdvancePhase( _( "Checking pins..." ) );
|
AdvancePhase( _( "Checking pins..." ) );
|
||||||
|
|
||||||
if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_NET ) )
|
if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_NET ) )
|
||||||
|
|
143
eeschema/erc.cpp
143
eeschema/erc.cpp
|
@ -23,6 +23,9 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
#include "connection_graph.h"
|
#include "connection_graph.h"
|
||||||
#include <common.h> // for ExpandEnvVarSubstitutions
|
#include <common.h> // for ExpandEnvVarSubstitutions
|
||||||
#include <erc.h>
|
#include <erc.h>
|
||||||
|
@ -407,6 +410,146 @@ int ERC_TESTER::TestMultiunitFootprints()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ERC_TESTER::TestMissingUnits()
|
||||||
|
{
|
||||||
|
ERC_SETTINGS& settings = m_schematic->ErcSettings();
|
||||||
|
SCH_SHEET_LIST sheets = m_schematic->GetSheets();
|
||||||
|
|
||||||
|
int errors = 0;
|
||||||
|
SCH_MULTI_UNIT_REFERENCE_MAP refMap;
|
||||||
|
sheets.GetMultiUnitSymbols( refMap, true );
|
||||||
|
|
||||||
|
for( std::pair<const wxString, SCH_REFERENCE_LIST>& symbol : refMap )
|
||||||
|
{
|
||||||
|
SCH_REFERENCE_LIST& refList = symbol.second;
|
||||||
|
|
||||||
|
wxCHECK2( refList.GetCount(), continue );
|
||||||
|
|
||||||
|
// Reference unit
|
||||||
|
SCH_REFERENCE& base_ref = refList.GetItem( 0 );
|
||||||
|
SCH_SYMBOL* unit = base_ref.GetSymbol();
|
||||||
|
LIB_SYMBOL* libSymbol = base_ref.GetLibPart();
|
||||||
|
|
||||||
|
if( static_cast<ssize_t>( refList.GetCount() ) == libSymbol->GetUnitCount() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::set<int> lib_units;
|
||||||
|
std::set<int> instance_units;
|
||||||
|
std::set<int> missing_units;
|
||||||
|
|
||||||
|
auto report_missing = [&]( std::set<int>& aMissingUnits, wxString aErrorMsg, int aErrorCode )
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
wxString missing_pin_units = wxT( "[ " );
|
||||||
|
int ii = 0;
|
||||||
|
|
||||||
|
for( int missing_unit : aMissingUnits )
|
||||||
|
{
|
||||||
|
if( ii++ == 3 )
|
||||||
|
{
|
||||||
|
missing_pin_units += wxT( "....." );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
missing_pin_units += libSymbol->GetUnitDisplayName( missing_unit ) + ", " ;
|
||||||
|
}
|
||||||
|
|
||||||
|
missing_pin_units.Truncate( missing_pin_units.length() - 2 );
|
||||||
|
missing_pin_units += wxT( " ]" );
|
||||||
|
|
||||||
|
msg.Printf( aErrorMsg, symbol.first, missing_pin_units );
|
||||||
|
|
||||||
|
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( aErrorCode );
|
||||||
|
ercItem->SetErrorMessage( msg );
|
||||||
|
ercItem->SetItems( unit );
|
||||||
|
|
||||||
|
SCH_MARKER* marker = new SCH_MARKER( ercItem, unit->GetPosition() );
|
||||||
|
base_ref.GetSheetPath().LastScreen()->Append( marker );
|
||||||
|
|
||||||
|
++errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
for( int ii = 1; ii <= libSymbol->GetUnitCount(); ++ii )
|
||||||
|
lib_units.insert( lib_units.end(), ii );
|
||||||
|
|
||||||
|
for( size_t ii = 0; ii < refList.GetCount(); ++ii )
|
||||||
|
instance_units.insert( instance_units.end(), refList.GetItem( ii ).GetUnit() );
|
||||||
|
|
||||||
|
std::set_difference( lib_units.begin(), lib_units.end(),
|
||||||
|
instance_units.begin(), instance_units.end(),
|
||||||
|
std::inserter( missing_units, missing_units.begin() ) );
|
||||||
|
|
||||||
|
if( !missing_units.empty() && settings.IsTestEnabled( ERCE_MISSING_UNIT ) )
|
||||||
|
{
|
||||||
|
report_missing( missing_units, _( "Symbol %s has unplaced units %s" ),
|
||||||
|
ERCE_MISSING_UNIT );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<int> missing_power;
|
||||||
|
std::set<int> missing_input;
|
||||||
|
std::set<int> missing_bidi;
|
||||||
|
|
||||||
|
for( int missing_unit : missing_units )
|
||||||
|
{
|
||||||
|
LIB_PINS pins;
|
||||||
|
int convert = 0;
|
||||||
|
|
||||||
|
for( size_t ii = 0; ii < refList.GetCount(); ++ii )
|
||||||
|
{
|
||||||
|
if( refList.GetItem( ii ).GetUnit() == missing_unit )
|
||||||
|
{
|
||||||
|
convert = refList.GetItem( ii ).GetSymbol()->GetConvert();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
libSymbol->GetPins( pins, missing_unit, convert );
|
||||||
|
|
||||||
|
for( auto pin : pins )
|
||||||
|
{
|
||||||
|
switch( pin->GetType() )
|
||||||
|
{
|
||||||
|
case ELECTRICAL_PINTYPE::PT_POWER_IN:
|
||||||
|
missing_power.insert( missing_unit );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ELECTRICAL_PINTYPE::PT_BIDI:
|
||||||
|
missing_bidi.insert( missing_unit );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ELECTRICAL_PINTYPE::PT_INPUT:
|
||||||
|
missing_input.insert( missing_unit );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !missing_power.empty() && settings.IsTestEnabled( ERCE_MISSING_POWER_INPUT_PIN ) )
|
||||||
|
{
|
||||||
|
report_missing( missing_power, _( "Symbol %s has input power pins in units %s that are not placed." ),
|
||||||
|
ERCE_MISSING_POWER_INPUT_PIN );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !missing_input.empty() && settings.IsTestEnabled( ERCE_MISSING_INPUT_PIN ) )
|
||||||
|
{
|
||||||
|
report_missing( missing_input, _( "Symbol %s has input pins in units %s that are not placed." ),
|
||||||
|
ERCE_MISSING_INPUT_PIN );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !missing_bidi.empty() && settings.IsTestEnabled( ERCE_MISSING_BIDI_PIN ) )
|
||||||
|
{
|
||||||
|
report_missing( missing_bidi, _( "Symbol %s has bidirectional pins in units %s that are not placed." ),
|
||||||
|
ERCE_MISSING_BIDI_PIN );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int ERC_TESTER::TestNoConnectPins()
|
int ERC_TESTER::TestNoConnectPins()
|
||||||
{
|
{
|
||||||
int err_count = 0;
|
int err_count = 0;
|
||||||
|
|
|
@ -139,6 +139,10 @@ public:
|
||||||
*/
|
*/
|
||||||
int TestSimModelIssues();
|
int TestSimModelIssues();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for uninstantiated units of multi unit symbols
|
||||||
|
*/
|
||||||
|
int TestMissingUnits();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SCHEMATIC* m_schematic;
|
SCHEMATIC* m_schematic;
|
||||||
|
|
|
@ -154,6 +154,22 @@ ERC_ITEM ERC_ITEM::extraUnits( ERCE_EXTRA_UNITS,
|
||||||
_( "Symbol has more units than are defined" ),
|
_( "Symbol has more units than are defined" ),
|
||||||
wxT( "extra_units" ) );
|
wxT( "extra_units" ) );
|
||||||
|
|
||||||
|
ERC_ITEM ERC_ITEM::missingUnits( ERCE_MISSING_UNIT,
|
||||||
|
_( "Symbol has units that are not placed" ),
|
||||||
|
wxT( "missing_unit" ) );
|
||||||
|
|
||||||
|
ERC_ITEM ERC_ITEM::missingInputPin( ERCE_MISSING_INPUT_PIN,
|
||||||
|
_( "Symbol has input pins that are not placed" ),
|
||||||
|
wxT( "missing_input_pin" ) );
|
||||||
|
|
||||||
|
ERC_ITEM ERC_ITEM::missingBidiPin( ERCE_MISSING_BIDI_PIN,
|
||||||
|
_( "Symbol has bidirectional pins that are not placed" ),
|
||||||
|
wxT( "missing_bidi_pin" ) );
|
||||||
|
|
||||||
|
ERC_ITEM ERC_ITEM::missingPowerInputPin( ERCE_MISSING_POWER_INPUT_PIN,
|
||||||
|
_( "Symbol has power input pins that are not placed" ),
|
||||||
|
wxT( "missing_power_pin" ) );
|
||||||
|
|
||||||
ERC_ITEM ERC_ITEM::differentUnitValue( ERCE_DIFFERENT_UNIT_VALUE,
|
ERC_ITEM ERC_ITEM::differentUnitValue( ERCE_DIFFERENT_UNIT_VALUE,
|
||||||
_( "Units of same symbol have different values" ),
|
_( "Units of same symbol have different values" ),
|
||||||
wxT( "unit_value_mismatch" ) );
|
wxT( "unit_value_mismatch" ) );
|
||||||
|
@ -200,6 +216,10 @@ std::vector<std::reference_wrapper<RC_ITEM>> ERC_ITEM::allItemTypes( {
|
||||||
ERC_ITEM::busLabelSyntax,
|
ERC_ITEM::busLabelSyntax,
|
||||||
ERC_ITEM::libSymbolIssues,
|
ERC_ITEM::libSymbolIssues,
|
||||||
ERC_ITEM::extraUnits,
|
ERC_ITEM::extraUnits,
|
||||||
|
ERC_ITEM::missingUnits,
|
||||||
|
ERC_ITEM::missingInputPin,
|
||||||
|
ERC_ITEM::missingBidiPin,
|
||||||
|
ERC_ITEM::missingPowerInputPin
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,6 +259,10 @@ std::shared_ptr<ERC_ITEM> ERC_ITEM::Create( int aErrorCode )
|
||||||
case ERCE_DIFFERENT_UNIT_VALUE: return std::make_shared<ERC_ITEM>( differentUnitValue );
|
case ERCE_DIFFERENT_UNIT_VALUE: return std::make_shared<ERC_ITEM>( differentUnitValue );
|
||||||
case ERCE_DUPLICATE_REFERENCE: return std::make_shared<ERC_ITEM>( duplicateReference );
|
case ERCE_DUPLICATE_REFERENCE: return std::make_shared<ERC_ITEM>( duplicateReference );
|
||||||
case ERCE_BUS_ENTRY_NEEDED: return std::make_shared<ERC_ITEM>( busEntryNeeded );
|
case ERCE_BUS_ENTRY_NEEDED: return std::make_shared<ERC_ITEM>( busEntryNeeded );
|
||||||
|
case ERCE_MISSING_UNIT: return std::make_shared<ERC_ITEM>( missingUnits );
|
||||||
|
case ERCE_MISSING_INPUT_PIN: return std::make_shared<ERC_ITEM>( missingInputPin );
|
||||||
|
case ERCE_MISSING_POWER_INPUT_PIN: return std::make_shared<ERC_ITEM>( missingPowerInputPin );
|
||||||
|
case ERCE_MISSING_BIDI_PIN: return std::make_shared<ERC_ITEM>( missingBidiPin );
|
||||||
case ERCE_UNSPECIFIED:
|
case ERCE_UNSPECIFIED:
|
||||||
default:
|
default:
|
||||||
wxFAIL_MSG( "Unknown ERC error code" );
|
wxFAIL_MSG( "Unknown ERC error code" );
|
||||||
|
|
|
@ -99,6 +99,10 @@ private:
|
||||||
static ERC_ITEM libSymbolIssues;
|
static ERC_ITEM libSymbolIssues;
|
||||||
static ERC_ITEM unannotated;
|
static ERC_ITEM unannotated;
|
||||||
static ERC_ITEM extraUnits;
|
static ERC_ITEM extraUnits;
|
||||||
|
static ERC_ITEM missingUnits;
|
||||||
|
static ERC_ITEM missingInputPin;
|
||||||
|
static ERC_ITEM missingBidiPin;
|
||||||
|
static ERC_ITEM missingPowerInputPin;
|
||||||
static ERC_ITEM differentUnitValue;
|
static ERC_ITEM differentUnitValue;
|
||||||
static ERC_ITEM duplicateReference;
|
static ERC_ITEM duplicateReference;
|
||||||
static ERC_ITEM busEntryNeeded;
|
static ERC_ITEM busEntryNeeded;
|
||||||
|
|
|
@ -103,6 +103,9 @@ ERC_SETTINGS::ERC_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
|
||||||
m_ERCSeverities[ERCE_LIB_SYMBOL_ISSUES] = RPT_SEVERITY_WARNING;
|
m_ERCSeverities[ERCE_LIB_SYMBOL_ISSUES] = RPT_SEVERITY_WARNING;
|
||||||
m_ERCSeverities[ERCE_NOCONNECT_CONNECTED] = RPT_SEVERITY_WARNING;
|
m_ERCSeverities[ERCE_NOCONNECT_CONNECTED] = RPT_SEVERITY_WARNING;
|
||||||
m_ERCSeverities[ERCE_NOCONNECT_NOT_CONNECTED] = RPT_SEVERITY_WARNING;
|
m_ERCSeverities[ERCE_NOCONNECT_NOT_CONNECTED] = RPT_SEVERITY_WARNING;
|
||||||
|
m_ERCSeverities[ERCE_MISSING_UNIT] = RPT_SEVERITY_WARNING;
|
||||||
|
m_ERCSeverities[ERCE_MISSING_INPUT_PIN] = RPT_SEVERITY_WARNING;
|
||||||
|
m_ERCSeverities[ERCE_MISSING_BIDI_PIN] = RPT_SEVERITY_WARNING;
|
||||||
|
|
||||||
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
|
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
|
||||||
[&]() -> nlohmann::json
|
[&]() -> nlohmann::json
|
||||||
|
|
|
@ -51,6 +51,10 @@ enum ERCE_T
|
||||||
ERCE_SIMILAR_LABELS, ///< 2 labels are equal for case insensitive comparisons.
|
ERCE_SIMILAR_LABELS, ///< 2 labels are equal for case insensitive comparisons.
|
||||||
ERCE_DIFFERENT_UNIT_FP, ///< Different units of the same symbol have different
|
ERCE_DIFFERENT_UNIT_FP, ///< Different units of the same symbol have different
|
||||||
///< footprints assigned.
|
///< footprints assigned.
|
||||||
|
ERCE_MISSING_POWER_INPUT_PIN, ///< Symbol has power input pins that are not placed on the schematic
|
||||||
|
ERCE_MISSING_INPUT_PIN, ///< Symbol has input pins that are not placed
|
||||||
|
ERCE_MISSING_BIDI_PIN, ///< Symbol has bi-directional pins that are not placed
|
||||||
|
ERCE_MISSING_UNIT, ///< Symbol has units that are not placed on the schematic
|
||||||
ERCE_DIFFERENT_UNIT_NET, ///< Shared pin in a multi-unit symbol is connected to
|
ERCE_DIFFERENT_UNIT_NET, ///< Shared pin in a multi-unit symbol is connected to
|
||||||
///< more than one net.
|
///< more than one net.
|
||||||
ERCE_BUS_ALIAS_CONFLICT, ///< Conflicting bus alias definitions across sheets.
|
ERCE_BUS_ALIAS_CONFLICT, ///< Conflicting bus alias definitions across sheets.
|
||||||
|
|
Loading…
Reference in New Issue