Extract generic item connectivity update and add QA

This commit is contained in:
Seth Hillbrand 2025-08-03 08:08:32 -07:00
parent 15ca4b1ba2
commit b21e3e45d9
4 changed files with 184 additions and 58 deletions

View File

@ -1232,6 +1232,63 @@ void CONNECTION_GRAPH::updateSymbolConnectivity( const SCH_SHEET_PATH& aSheet,
}
void CONNECTION_GRAPH::updatePinConnectivity( const SCH_SHEET_PATH& aSheet, SCH_PIN* aPin, SCH_CONNECTION* aConn )
{
aConn->SetType( CONNECTION_TYPE::NET );
// because calling the first time is not thread-safe
wxString name = aPin->GetDefaultNetName( aSheet );
aPin->ClearConnectedItems( aSheet );
if( aPin->IsGlobalPower() )
{
aConn->SetName( name );
m_global_power_pins.emplace_back( std::make_pair( aSheet, aPin ) );
}
}
void CONNECTION_GRAPH::updateGenericItemConnectivity( const SCH_SHEET_PATH& aSheet, SCH_ITEM* aItem,
std::map<VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap )
{
std::vector<VECTOR2I> points = aItem->GetConnectionPoints();
aItem->ClearConnectedItems( aSheet );
m_items.emplace_back( aItem );
SCH_CONNECTION* conn = aItem->InitializeConnection( aSheet, this );
switch( aItem->Type() )
{
case SCH_LINE_T:
conn->SetType( aItem->GetLayer() == LAYER_BUS ? CONNECTION_TYPE::BUS : CONNECTION_TYPE::NET );
break;
case SCH_BUS_BUS_ENTRY_T:
conn->SetType( CONNECTION_TYPE::BUS );
static_cast<SCH_BUS_BUS_ENTRY*>( aItem )->m_connected_bus_items[0] = nullptr;
static_cast<SCH_BUS_BUS_ENTRY*>( aItem )->m_connected_bus_items[1] = nullptr;
break;
case SCH_PIN_T:
if( points.empty() )
points = { static_cast<SCH_PIN*>( aItem )->GetPosition() };
updatePinConnectivity( aSheet, static_cast<SCH_PIN*>( aItem ), conn );
break;
case SCH_BUS_WIRE_ENTRY_T:
conn->SetType( CONNECTION_TYPE::NET );
static_cast<SCH_BUS_WIRE_ENTRY*>( aItem )->m_connected_bus_item = nullptr;
break;
default: break;
}
for( const VECTOR2I& point : points )
aConnectionMap[point].push_back( aItem );
}
void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
const std::vector<SCH_ITEM*>& aItemList )
{
@ -1239,22 +1296,6 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
aSheet.Last()->GetFileName(), aItemList.size() );
std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
auto updatePin = [&]( SCH_PIN* aPin, SCH_CONNECTION* aConn )
{
aConn->SetType( CONNECTION_TYPE::NET );
// because calling the first time is not thread-safe
wxString name = aPin->GetDefaultNetName( aSheet );
aPin->ClearConnectedItems( aSheet );
// power symbol pins need to be post-processed later
if( aPin->IsGlobalPower() )
{
aConn->SetName( name );
m_global_power_pins.emplace_back( std::make_pair( aSheet, aPin ) );
}
};
for( SCH_ITEM* item : aItemList )
{
std::vector<VECTOR2I> points = item->GetConnectionPoints();
@ -1278,45 +1319,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
}
else
{
m_items.emplace_back( item );
SCH_CONNECTION* conn = item->InitializeConnection( aSheet, this );
// Set bus/net property here so that the propagation code uses it
switch( item->Type() )
{
case SCH_LINE_T:
conn->SetType( item->GetLayer() == LAYER_BUS ? CONNECTION_TYPE::BUS :
CONNECTION_TYPE::NET );
break;
case SCH_BUS_BUS_ENTRY_T:
conn->SetType( CONNECTION_TYPE::BUS );
// clean previous (old) links:
static_cast<SCH_BUS_BUS_ENTRY*>( item )->m_connected_bus_items[0] = nullptr;
static_cast<SCH_BUS_BUS_ENTRY*>( item )->m_connected_bus_items[1] = nullptr;
break;
case SCH_PIN_T:
if( points.empty() )
points = { static_cast<SCH_PIN*>( item )->GetPosition() };
updatePin( static_cast<SCH_PIN*>( item ), conn );
break;
case SCH_BUS_WIRE_ENTRY_T:
conn->SetType( CONNECTION_TYPE::NET );
// clean previous (old) link:
static_cast<SCH_BUS_WIRE_ENTRY*>( item )->m_connected_bus_item = nullptr;
break;
default:
break;
}
for( const VECTOR2I& point : points )
connection_map[ point ].push_back( item );
updateGenericItemConnectivity( aSheet, item, connection_map );
}
}

View File

@ -377,6 +377,7 @@ public:
// Define QA friend functions to allow testing of private methods
friend void boost_test_update_symbol_connectivity();
friend void boost_test_update_generic_connectivity();
void Reset();
@ -513,6 +514,24 @@ private:
SCH_SYMBOL* aSymbol,
std::map<VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap );
/**
* Update the connectivity of a pin and its connections.
* This is called by updateItemConnectivity() for each pin
* in the schematic.
*/
void updatePinConnectivity( const SCH_SHEET_PATH& aSheet,
SCH_PIN* aPin,
SCH_CONNECTION* aConnection );
/**
* Update the connectivity of items that are not pins or symbols.
* This is called by updateItemConnectivity() for each item
* in the schematic that is not a symbol or pin.
*/
void updateGenericItemConnectivity( const SCH_SHEET_PATH& aSheet,
SCH_ITEM* aItem,
std::map<VECTOR2I, std::vector<SCH_ITEM*>>& aConnectionMap );
/**
* Update the graphical connectivity between items (i.e. where they touch)
* The items passed in must be on the same sheet.

View File

@ -88,7 +88,7 @@ set( QA_EESCHEMA_SRCS
test_schematic.cpp
test_symbol_library_manager.cpp
test_resolve_drivers.cpp
test_update_symbol_connectivity.cpp
test_update_items_connectivity.cpp
)
if( WIN32 )

View File

@ -22,15 +22,19 @@
#include <connection_graph.h>
#include <lib_symbol.h>
#include <pin_type.h>
#include <sch_bus_entry.h>
#include <sch_line.h>
#include <sch_pin.h>
#include <sch_symbol.h>
#include <sch_sheet.h>
#include <sch_sheet_path.h>
#include <sch_screen.h>
#include <algorithm>
#include <map>
#include <set>
void boost_test_update_symbol_connectivity()
{
// Create root sheet and screen
@ -131,9 +135,109 @@ void boost_test_update_symbol_connectivity()
delete sheet; // deletes screen
}
BOOST_AUTO_TEST_SUITE( UpdateSymbolConnectivity )
void boost_test_update_generic_connectivity()
{
std::map<VECTOR2I, std::vector<SCH_ITEM*>> cmap;
// Create root sheet and screen
SCH_SCREEN* screen = new SCH_SCREEN( nullptr );
SCH_SHEET* sheet = new SCH_SHEET( nullptr, VECTOR2I( 0, 0 ), VECTOR2I( 1000, 1000 ) );
sheet->SetScreen( screen );
SCH_SHEET_PATH sheetPath;
sheetPath.push_back( sheet );
CONNECTION_GRAPH graph;
// Wire line
SCH_LINE wire( VECTOR2I( 0, 0 ), LAYER_WIRE );
wire.SetEndPoint( VECTOR2I( 100, 0 ) );
graph.updateGenericItemConnectivity( sheetPath, &wire, cmap );
SCH_CONNECTION* wireConn = wire.Connection( &sheetPath );
BOOST_REQUIRE( wireConn );
BOOST_CHECK( wireConn->Type() == CONNECTION_TYPE::NET );
BOOST_CHECK( cmap.count( wire.GetStartPoint() ) );
BOOST_CHECK( cmap.count( wire.GetEndPoint() ) );
// Bus line
cmap.clear();
SCH_LINE bus( VECTOR2I( 0, 0 ), LAYER_BUS );
bus.SetEndPoint( VECTOR2I( 0, 100 ) );
graph.updateGenericItemConnectivity( sheetPath, &bus, cmap );
SCH_CONNECTION* busConn = bus.Connection( &sheetPath );
BOOST_REQUIRE( busConn );
BOOST_CHECK( busConn->Type() == CONNECTION_TYPE::BUS );
BOOST_CHECK( cmap.count( bus.GetStartPoint() ) );
BOOST_CHECK( cmap.count( bus.GetEndPoint() ) );
// Bus-to-bus entry
cmap.clear();
SCH_BUS_BUS_ENTRY busEntry( VECTOR2I( 0, 0 ), false );
SCH_LINE dummy1( VECTOR2I( 0, 0 ), LAYER_BUS );
SCH_LINE dummy2( VECTOR2I( 0, 0 ), LAYER_BUS );
busEntry.m_connected_bus_items[0] = &dummy1;
busEntry.m_connected_bus_items[1] = &dummy2;
graph.updateGenericItemConnectivity( sheetPath, &busEntry, cmap );
SCH_CONNECTION* bbConn = busEntry.Connection( &sheetPath );
BOOST_REQUIRE( bbConn );
BOOST_CHECK( bbConn->Type() == CONNECTION_TYPE::BUS );
BOOST_CHECK( busEntry.m_connected_bus_items[0] == nullptr );
BOOST_CHECK( busEntry.m_connected_bus_items[1] == nullptr );
auto ptsBB = busEntry.GetConnectionPoints();
BOOST_CHECK( cmap.count( ptsBB[0] ) );
BOOST_CHECK( cmap.count( ptsBB[1] ) );
// Bus-wire entry
cmap.clear();
SCH_BUS_WIRE_ENTRY bwEntry( VECTOR2I( 0, 0 ), false );
SCH_LINE dummyBus( VECTOR2I( 0, 0 ), LAYER_BUS );
bwEntry.m_connected_bus_item = &dummyBus;
graph.updateGenericItemConnectivity( sheetPath, &bwEntry, cmap );
SCH_CONNECTION* bwConn = bwEntry.Connection( &sheetPath );
BOOST_REQUIRE( bwConn );
BOOST_CHECK( bwConn->Type() == CONNECTION_TYPE::NET );
BOOST_CHECK( bwEntry.m_connected_bus_item == nullptr );
auto ptsBW = bwEntry.GetConnectionPoints();
BOOST_CHECK( cmap.count( ptsBW[0] ) );
BOOST_CHECK( cmap.count( ptsBW[1] ) );
// Pin
cmap.clear();
LIB_SYMBOL libSymbol( "PWR", nullptr );
SCH_PIN* libPin = new SCH_PIN( &libSymbol );
libPin->SetNumber( "1" );
libPin->SetName( "P" );
libPin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
libPin->SetPosition( VECTOR2I( 10, 10 ) );
libSymbol.AddDrawItem( libPin );
libSymbol.SetGlobalPower();
SCH_SYMBOL symbol( libSymbol, libSymbol.GetLibId(), &sheetPath, 0, 0, VECTOR2I( 0, 0 ) );
symbol.SetRef( &sheetPath, "U1" );
symbol.UpdatePins();
SCH_PIN* pin = symbol.GetPins( &sheetPath )[0];
graph.updateGenericItemConnectivity( sheetPath, pin, cmap );
SCH_CONNECTION* pinConn = pin->Connection( &sheetPath );
BOOST_REQUIRE( pinConn );
BOOST_CHECK( pinConn->Type() == CONNECTION_TYPE::NET );
BOOST_CHECK( graph.m_global_power_pins.size() == 1 );
BOOST_CHECK( cmap.count( pin->GetPosition() ) );
}
BOOST_AUTO_TEST_SUITE( UpdateItemsConnectivity )
BOOST_AUTO_TEST_CASE( SymbolConnectivityLinksPins )
{
boost_test_update_symbol_connectivity();
}
BOOST_AUTO_TEST_CASE( GenericItemConnectivity )
{
boost_test_update_generic_connectivity();
}
BOOST_AUTO_TEST_SUITE_END()