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:
Seth Hillbrand 2022-11-25 20:40:01 -08:00
parent 458935bb5a
commit 09cc6decaf
7 changed files with 192 additions and 0 deletions

View File

@ -485,6 +485,8 @@ void DIALOG_ERC::testErc()
m_parent->RecalculateConnections( NO_CLEANUP );
sch->ConnectionGraph()->RunERC();
AdvancePhase( _( "Checking units..." ) );
// Test is all units of each multiunit symbol have the same footprint assigned.
if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_FP ) )
{
@ -492,6 +494,14 @@ void DIALOG_ERC::testErc()
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..." ) );
if( settings.IsTestEnabled( ERCE_DIFFERENT_UNIT_NET ) )

View File

@ -23,6 +23,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <algorithm>
#include <numeric>
#include "connection_graph.h"
#include <common.h> // for ExpandEnvVarSubstitutions
#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 err_count = 0;

View File

@ -139,6 +139,10 @@ public:
*/
int TestSimModelIssues();
/**
* Test for uninstantiated units of multi unit symbols
*/
int TestMissingUnits();
private:
SCHEMATIC* m_schematic;

View File

@ -154,6 +154,22 @@ ERC_ITEM ERC_ITEM::extraUnits( ERCE_EXTRA_UNITS,
_( "Symbol has more units than are defined" ),
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,
_( "Units of same symbol have different values" ),
wxT( "unit_value_mismatch" ) );
@ -200,6 +216,10 @@ std::vector<std::reference_wrapper<RC_ITEM>> ERC_ITEM::allItemTypes( {
ERC_ITEM::busLabelSyntax,
ERC_ITEM::libSymbolIssues,
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_DUPLICATE_REFERENCE: return std::make_shared<ERC_ITEM>( duplicateReference );
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:
default:
wxFAIL_MSG( "Unknown ERC error code" );

View File

@ -99,6 +99,10 @@ private:
static ERC_ITEM libSymbolIssues;
static ERC_ITEM unannotated;
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 duplicateReference;
static ERC_ITEM busEntryNeeded;

View File

@ -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_NOCONNECT_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",
[&]() -> nlohmann::json

View File

@ -51,6 +51,10 @@ enum ERCE_T
ERCE_SIMILAR_LABELS, ///< 2 labels are equal for case insensitive comparisons.
ERCE_DIFFERENT_UNIT_FP, ///< Different units of the same symbol have different
///< 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
///< more than one net.
ERCE_BUS_ALIAS_CONFLICT, ///< Conflicting bus alias definitions across sheets.