Add ERC check for dangling wire endpoints

This commit is contained in:
JamesJCode 2024-07-22 23:16:08 +01:00
parent b4c365b464
commit 559854ec0f
10 changed files with 451 additions and 1 deletions

View File

@ -3221,6 +3221,12 @@ int CONNECTION_GRAPH::RunERC()
error_count++;
}
if( settings.IsTestEnabled( ERCE_UNCONNECTED_WIRE_ENDPOINT ) )
{
if( !ercCheckDanglingWireEndpoints( subgraph ) )
error_count++;
}
if( settings.IsTestEnabled( ERCE_NOCONNECT_CONNECTED )
|| settings.IsTestEnabled( ERCE_NOCONNECT_NOT_CONNECTED )
|| settings.IsTestEnabled( ERCE_PIN_NOT_CONNECTED ) )
@ -3846,6 +3852,46 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
}
bool CONNECTION_GRAPH::ercCheckDanglingWireEndpoints( const CONNECTION_SUBGRAPH* aSubgraph )
{
int err_count = 0;
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
for( SCH_ITEM* item : aSubgraph->m_items )
{
if( item->Type() != SCH_LINE_T || item->GetLayer() != LAYER_WIRE )
continue;
SCH_LINE* line = static_cast<SCH_LINE*>( item );
if( line->IsGraphicLine() )
continue;
auto report_error = [&]( VECTOR2I& location )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNCONNECTED_WIRE_ENDPOINT );
ercItem->SetItems( line );
ercItem->SetSheetSpecificPath( sheet );
ercItem->SetErrorMessage( _( "Unconnected wire endpoint" ) );
SCH_MARKER* marker = new SCH_MARKER( ercItem, location );
sheet.LastScreen()->Append( marker );
err_count++;
};
if( line->IsStartDangling() )
report_error( line->GetConnectionPoints()[0] );
if( line->IsEndDangling() )
report_error( line->GetConnectionPoints()[1] );
}
return err_count > 0;
}
bool CONNECTION_GRAPH::ercCheckFloatingWires( const CONNECTION_SUBGRAPH* aSubgraph )
{
if( aSubgraph->m_driver )

View File

@ -701,6 +701,16 @@ private:
*/
bool ercCheckFloatingWires( const CONNECTION_SUBGRAPH* aSubgraph );
/**
* Check one subgraph for dangling wire endpoints.
*
* Will throw an error for any subgraph that has wires with only one endpoing
*
* @param aSubgraph is the subgraph to examine.
* @return true for no errors, false for errors.
*/
bool ercCheckDanglingWireEndpoints( const CONNECTION_SUBGRAPH* aSubgraph );
/**
* Check one subgraph for proper connection of labels.
*

View File

@ -232,6 +232,10 @@ ERC_ITEM ERC_ITEM::busEntryNeeded( ERCE_BUS_ENTRY_NEEDED,
_( "Bus Entry needed" ),
wxT( "bus_entry_needed" ) );
ERC_ITEM ERC_ITEM::unconnectedWireEndpoint( ERCE_UNCONNECTED_WIRE_ENDPOINT,
_( "Unconnected wire endpoint" ),
wxT( "unconnected_wire_endpoint" ) );
std::vector<std::reference_wrapper<RC_ITEM>> ERC_ITEM::allItemTypes(
{
ERC_ITEM::heading_connections,
@ -249,6 +253,7 @@ std::vector<std::reference_wrapper<RC_ITEM>> ERC_ITEM::allItemTypes(
ERC_ITEM::fourWayJunction,
ERC_ITEM::duplicatePinError,
ERC_ITEM::labelMultipleWires,
ERC_ITEM::unconnectedWireEndpoint,
ERC_ITEM::heading_conflicts,
ERC_ITEM::duplicateReference,
@ -346,6 +351,7 @@ std::shared_ptr<ERC_ITEM> ERC_ITEM::Create( int aErrorCode )
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_UNCONNECTED_WIRE_ENDPOINT: return std::make_shared<ERC_ITEM>( unconnectedWireEndpoint );
case ERCE_UNSPECIFIED:
default:
wxFAIL_MSG( wxS( "Unknown ERC error code" ) );

View File

@ -244,6 +244,7 @@ private:
static ERC_ITEM differentUnitValue;
static ERC_ITEM duplicateReference;
static ERC_ITEM busEntryNeeded;
static ERC_ITEM unconnectedWireEndpoint;
/// True if this item is specific to a sheet instance (as opposed to applying to all instances)
std::optional<SCH_SHEET_PATH> m_sheetSpecificPath;

View File

@ -115,6 +115,7 @@ ERC_SETTINGS::ERC_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
m_ERCSeverities[ERCE_SIMULATION_MODEL] = RPT_SEVERITY_IGNORE;
m_ERCSeverities[ERCE_FOUR_WAY_JUNCTION] = RPT_SEVERITY_IGNORE;
m_ERCSeverities[ERCE_LABEL_MULTIPLE_WIRES] = RPT_SEVERITY_WARNING;
m_ERCSeverities[ERCE_UNCONNECTED_WIRE_ENDPOINT] = RPT_SEVERITY_WARNING;
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
[&]() -> nlohmann::json

View File

@ -87,9 +87,10 @@ enum ERCE_T
ERCE_BUS_ENTRY_NEEDED, ///< Importer failed to auto-place a bus entry.
ERCE_FOUR_WAY_JUNCTION, ///< A four-way junction was found.
ERCE_LABEL_MULTIPLE_WIRES, ///< A label is connected to more than one wire.
ERCE_UNCONNECTED_WIRE_ENDPOINT, ///< A label is connected to more than one wire.
ERCE_LAST = ERCE_LABEL_MULTIPLE_WIRES,
ERCE_LAST = ERCE_UNCONNECTED_WIRE_ENDPOINT,
// Errors after this point will not automatically appear in the Severities Panel

View File

@ -0,0 +1,307 @@
(kicad_sch
(version 20240620)
(generator "eeschema")
(generator_version "8.99")
(uuid "513e765f-34fa-43aa-ba9d-42d9cdbd1bee")
(paper "A4")
(lib_symbols
(symbol "Device:R"
(pin_numbers hide)
(pin_names
(offset 0)
)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(property "Reference" "R"
(at 2.032 0 90)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Value" "R"
(at 0 0 90)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Footprint" ""
(at -1.778 0 90)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Datasheet" "~"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Description" "Resistor"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "ki_keywords" "R res resistor"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "ki_fp_filters" "R_*"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(symbol "R_0_1"
(rectangle
(start -1.016 -2.54)
(end 1.016 2.54)
(stroke
(width 0.254)
(type default)
)
(fill
(type none)
)
)
)
(symbol "R_1_1"
(pin passive line
(at 0 3.81 270)
(length 1.27)
(name "~"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "1"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin passive line
(at 0 -3.81 90)
(length 1.27)
(name "~"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "2"
(effects
(font
(size 1.27 1.27)
)
)
)
)
)
(embedded_fonts no)
)
)
(junction
(at 125.73 57.15)
(diameter 0)
(color 0 0 0 0)
(uuid "48674fa2-874f-423a-b81e-9bb9ae23192a")
)
(junction
(at 113.03 105.41)
(diameter 0)
(color 0 0 0 0)
(uuid "a3301b84-2cb1-4146-8ff7-764516302115")
)
(wire
(pts
(xy 97.79 105.41) (xy 113.03 105.41)
)
(stroke
(width 0)
(type default)
)
(uuid "20a703fc-44d4-4868-875e-0720a60631a9")
)
(wire
(pts
(xy 113.03 97.79) (xy 113.03 105.41)
)
(stroke
(width 0)
(type default)
)
(uuid "7a769a1a-85db-462d-8ae9-5902204c8bf3")
)
(wire
(pts
(xy 113.03 105.41) (xy 130.81 105.41)
)
(stroke
(width 0)
(type default)
)
(uuid "7d42cdb1-f27f-42d4-8633-b9054b67dee2")
)
(wire
(pts
(xy 125.73 57.15) (xy 119.38 57.15)
)
(stroke
(width 0)
(type default)
)
(uuid "9efd37f4-7829-41f1-8758-dde8dec8bf81")
)
(wire
(pts
(xy 125.73 67.31) (xy 125.73 57.15)
)
(stroke
(width 0)
(type default)
)
(uuid "a823e5c0-a148-4c04-8361-754d66a77ced")
)
(wire
(pts
(xy 111.76 57.15) (xy 106.68 57.15)
)
(stroke
(width 0)
(type default)
)
(uuid "d97648b7-dcd4-4c1b-be47-f2301daa6e9f")
)
(wire
(pts
(xy 106.68 57.15) (xy 106.68 67.31)
)
(stroke
(width 0)
(type default)
)
(uuid "dcbdf50d-73aa-4a18-8b79-ba4e84351943")
)
(wire
(pts
(xy 125.73 57.15) (xy 133.35 57.15)
)
(stroke
(width 0)
(type default)
)
(uuid "ddca24db-e3db-4e30-9cfb-809a995b7364")
)
(wire
(pts
(xy 106.68 67.31) (xy 125.73 67.31)
)
(stroke
(width 0)
(type default)
)
(uuid "fc7e679c-96d9-4648-bd8f-24574d45f42b")
)
(symbol
(lib_id "Device:R")
(at 115.57 57.15 90)
(unit 1)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(dnp no)
(fields_autoplaced yes)
(uuid "8b70c705-1884-4502-b257-3440e9648eca")
(property "Reference" "R1"
(at 115.57 50.8 90)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Value" "R"
(at 115.57 53.34 90)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Footprint" ""
(at 115.57 58.928 90)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Datasheet" "~"
(at 115.57 57.15 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Description" "Resistor"
(at 115.57 57.15 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(pin "1"
(uuid "5362910d-1aed-4eb1-ab99-2b5c12c2596f")
)
(pin "2"
(uuid "a5e610c4-3ed9-4115-ae17-c24f648ccde4")
)
(instances
(project ""
(path "/513e765f-34fa-43aa-ba9d-42d9cdbd1bee"
(reference "R1")
(unit 1)
)
)
)
)
(sheet_instances
(path "/"
(page "1")
)
)
(embedded_fonts no)
)

View File

@ -60,6 +60,7 @@ set( QA_EESCHEMA_SRCS
erc/test_erc_hierarchical_schematics.cpp
erc/test_erc_label_multiple_wires.cpp
erc/test_erc_rule_areas.cpp
erc/test_erc_unconnected_wire_endpoints.cpp
test_eagle_plugin.cpp
test_junction_helpers.cpp

View File

@ -61,6 +61,9 @@ BOOST_FIXTURE_TEST_CASE( ERCGlobalLabels, ERC_REGRESSION_TEST_FIXTURE )
settings.m_ERCSeverities[ERCE_LIB_SYMBOL_ISSUES] = RPT_SEVERITY_IGNORE;
settings.m_ERCSeverities[ERCE_LIB_SYMBOL_MISMATCH] = RPT_SEVERITY_IGNORE;
// Skip the unconnected wire endpoints warning
settings.m_ERCSeverities[ERCE_UNCONNECTED_WIRE_ENDPOINT] = RPT_SEVERITY_IGNORE;
SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
m_schematic->ConnectionGraph()->Recalculate( sheets, true );
m_schematic->ConnectionGraph()->RunERC();

View File

@ -0,0 +1,74 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 KiCad Developers, see AUTHORS.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one at
* http://www.gnu.org/licenses/
*/
#include <qa_utils/wx_utils/unit_test_utils.h>
#include <schematic_utils/schematic_file_util.h>
#include <connection_graph.h>
#include <schematic.h>
#include <erc/erc_settings.h>
#include <erc/erc.h>
#include <erc/erc_report.h>
#include <settings/settings_manager.h>
#include <locale_io.h>
struct ERC_REGRESSION_TEST_FIXTURE
{
ERC_REGRESSION_TEST_FIXTURE() : m_settingsManager( true /* headless */ ) {}
SETTINGS_MANAGER m_settingsManager;
std::unique_ptr<SCHEMATIC> m_schematic;
};
BOOST_FIXTURE_TEST_CASE( ERCUnconnectedWireEndpoints, ERC_REGRESSION_TEST_FIXTURE )
{
LOCALE_IO dummy;
// Check for Errors when using rule area netclass directives
std::vector<std::pair<wxString, int>> tests = { { "erc_wire_endpoints", 4 } };
for( const std::pair<wxString, int>& test : tests )
{
KI_TEST::LoadSchematic( m_settingsManager, test.first, m_schematic );
ERC_SETTINGS& settings = m_schematic->ErcSettings();
SHEETLIST_ERC_ITEMS_PROVIDER errors( m_schematic.get() );
// Skip the "Modified symbol" warning
settings.m_ERCSeverities[ERCE_LIB_SYMBOL_ISSUES] = RPT_SEVERITY_IGNORE;
settings.m_ERCSeverities[ERCE_LIB_SYMBOL_MISMATCH] = RPT_SEVERITY_IGNORE;
// Configure the rules under test
settings.m_ERCSeverities[ERCE_UNCONNECTED_WIRE_ENDPOINT] = RPT_SEVERITY_ERROR;
settings.m_ERCSeverities[ERCE_WIRE_DANGLING] = RPT_SEVERITY_IGNORE;
m_schematic->ConnectionGraph()->RunERC();
errors.SetSeverities( RPT_SEVERITY_ERROR | RPT_SEVERITY_WARNING );
ERC_REPORT reportWriter( m_schematic.get(), EDA_UNITS::MILLIMETRES );
BOOST_CHECK_MESSAGE( errors.GetCount() == test.second,
"Expected " << test.second << " errors in " << test.first.ToStdString()
<< " but got " << errors.GetCount() << "\n"
<< reportWriter.GetTextReport() );
}
}