mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-21 00:21:25 +00:00
Clean up redundant component classes on netlist update
This commit is contained in:
parent
045c1f347f
commit
f4e5ae0514
pcbnew
@ -95,9 +95,17 @@ COMPONENT_CLASS_MANAGER::GetEffectiveComponentClass( std::unordered_set<wxString
|
||||
if( classNames.size() == 0 )
|
||||
return m_noneClass.get();
|
||||
|
||||
// Lambda to handle finding constituent component classes. This first checks the cache,
|
||||
// and if found moves the class to the primary classes map. If not found, it either returns
|
||||
// an existing class in the primary list or creates a new class.
|
||||
auto getOrCreateClass = [this]( const wxString& className )
|
||||
{
|
||||
if( !m_classes.count( className ) )
|
||||
if( m_classesCache.count( className ) )
|
||||
{
|
||||
auto existingClass = m_classesCache.extract( className );
|
||||
m_classes.insert( std::move( existingClass ) );
|
||||
}
|
||||
else if( !m_classes.count( className ) )
|
||||
{
|
||||
std::unique_ptr<COMPONENT_CLASS> newClass =
|
||||
std::make_unique<COMPONENT_CLASS>( className );
|
||||
@ -108,11 +116,11 @@ COMPONENT_CLASS_MANAGER::GetEffectiveComponentClass( std::unordered_set<wxString
|
||||
return m_classes[className].get();
|
||||
};
|
||||
|
||||
// Handle single-assignment component classes
|
||||
if( classNames.size() == 1 )
|
||||
{
|
||||
return getOrCreateClass( *classNames.begin() );
|
||||
}
|
||||
|
||||
// Handle composite component classes
|
||||
std::vector<wxString> sortedClassNames( classNames.begin(), classNames.end() );
|
||||
|
||||
std::sort( sortedClassNames.begin(), sortedClassNames.end(),
|
||||
@ -121,25 +129,82 @@ COMPONENT_CLASS_MANAGER::GetEffectiveComponentClass( std::unordered_set<wxString
|
||||
return str1.Cmp( str2 ) < 0;
|
||||
} );
|
||||
|
||||
wxString fullName = sortedClassNames[0];
|
||||
wxString fullName = GetFullClassNameForConstituents( sortedClassNames );
|
||||
|
||||
for( std::size_t i = 1; i < sortedClassNames.size(); ++i )
|
||||
if( m_effectiveClassesCache.count( fullName ) )
|
||||
{
|
||||
fullName += ",";
|
||||
fullName += sortedClassNames[i];
|
||||
// The effective class was previously constructed - copy it across to the new live map
|
||||
auto existingClass = m_effectiveClassesCache.extract( fullName );
|
||||
COMPONENT_CLASS* effClass = existingClass.mapped().get();
|
||||
m_effectiveClasses.insert( std::move( existingClass ) );
|
||||
|
||||
// Ensure that all constituent component classes are copied to the live map
|
||||
for( COMPONENT_CLASS* constClass : effClass->GetConstituentClasses() )
|
||||
{
|
||||
if( m_classesCache.count( constClass->GetFullName() ) )
|
||||
{
|
||||
auto constClassNode = m_classesCache.extract( constClass->GetFullName() );
|
||||
m_classes.insert( std::move( constClassNode ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_effectiveClasses.count( fullName ) )
|
||||
else if( !m_effectiveClasses.count( fullName ) )
|
||||
{
|
||||
// The effective class was not previously constructed
|
||||
std::unique_ptr<COMPONENT_CLASS> effClass = std::make_unique<COMPONENT_CLASS>( fullName );
|
||||
|
||||
for( const wxString& className : sortedClassNames )
|
||||
{
|
||||
effClass->AddConstituentClass( getOrCreateClass( className ) );
|
||||
}
|
||||
|
||||
m_effectiveClasses[fullName] = std::move( effClass );
|
||||
}
|
||||
|
||||
return m_effectiveClasses[fullName].get();
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_MANAGER::InitNetlistUpdate()
|
||||
{
|
||||
m_classesCache = std::move( m_classes );
|
||||
m_effectiveClassesCache = std::move( m_effectiveClasses );
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_MANAGER::FinishNetlistUpdate()
|
||||
{
|
||||
m_classesCache.clear();
|
||||
m_effectiveClassesCache.clear();
|
||||
}
|
||||
|
||||
|
||||
wxString
|
||||
COMPONENT_CLASS_MANAGER::GetFullClassNameForConstituents( std::unordered_set<wxString>& classNames )
|
||||
{
|
||||
std::vector<wxString> sortedClassNames( classNames.begin(), classNames.end() );
|
||||
|
||||
std::sort( sortedClassNames.begin(), sortedClassNames.end(),
|
||||
[]( const wxString& str1, const wxString& str2 )
|
||||
{
|
||||
return str1.Cmp( str2 ) < 0;
|
||||
} );
|
||||
|
||||
return GetFullClassNameForConstituents( sortedClassNames );
|
||||
}
|
||||
|
||||
|
||||
wxString
|
||||
COMPONENT_CLASS_MANAGER::GetFullClassNameForConstituents( std::vector<wxString>& classNames )
|
||||
{
|
||||
if( classNames.size() == 0 )
|
||||
return wxEmptyString;
|
||||
|
||||
wxString fullName = classNames[0];
|
||||
|
||||
for( std::size_t i = 1; i < classNames.size(); ++i )
|
||||
{
|
||||
fullName += ",";
|
||||
fullName += classNames[i];
|
||||
}
|
||||
|
||||
return fullName;
|
||||
}
|
||||
|
@ -73,11 +73,26 @@ private:
|
||||
std::vector<COMPONENT_CLASS*> m_constituentClasses;
|
||||
};
|
||||
|
||||
/*
|
||||
* A class to manage Component Classes in a board context
|
||||
*
|
||||
* This manager owns generated COMPONENT_CLASS objects, and guarantees that pointers to managed
|
||||
* objects are valid for the duration of the board lifetime. Note that, in order to maintain this
|
||||
* guarantee, there are two methods that must be called when updating the board from the netlist
|
||||
* (InitNetlistUpdate and FinishNetlistUpdate).
|
||||
*/
|
||||
class COMPONENT_CLASS_MANAGER
|
||||
{
|
||||
public:
|
||||
COMPONENT_CLASS_MANAGER();
|
||||
|
||||
/// @brief Gets the full effective class name for the given set of constituent classes
|
||||
static wxString GetFullClassNameForConstituents( std::unordered_set<wxString>& classNames );
|
||||
|
||||
/// @brief Gets the full effective class name for the given set of constituent classes
|
||||
/// @param classNames a sorted vector of consituent class names
|
||||
static wxString GetFullClassNameForConstituents( std::vector<wxString>& classNames );
|
||||
|
||||
/// @brief Gets an effective component class for the given constituent class names
|
||||
/// @param classes The names of the constituent component classes
|
||||
/// @return Effective COMPONENT_CLASS object
|
||||
@ -86,6 +101,18 @@ public:
|
||||
/// Returns the unassigned component class
|
||||
const COMPONENT_CLASS* GetNoneComponentClass() const { return m_noneClass.get(); }
|
||||
|
||||
/// Prepare the manager for a board update
|
||||
/// Must be called prior to updating the PCB from the netlist
|
||||
void InitNetlistUpdate();
|
||||
|
||||
/// Cleans up the manager after a board update
|
||||
/// Must be called after updating the PCB from the netlist
|
||||
void FinishNetlistUpdate();
|
||||
|
||||
/// Resets the contents of the manager
|
||||
// All pointers to COMPONENT_CLASS objects will being invalid
|
||||
void Reset();
|
||||
|
||||
protected:
|
||||
/// All individual component classes
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_classes;
|
||||
@ -93,6 +120,12 @@ protected:
|
||||
/// Generated effective component classes
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_effectiveClasses;
|
||||
|
||||
/// Cache of all individual component classes (for netlist updating)
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_classesCache;
|
||||
|
||||
/// Cache of all generated effective component classes (for netlist updating)
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_effectiveClassesCache;
|
||||
|
||||
/// The class to represent an unassigned component class
|
||||
std::unique_ptr<COMPONENT_CLASS> m_noneClass;
|
||||
};
|
||||
|
@ -205,16 +205,24 @@ FOOTPRINT* BOARD_NETLIST_UPDATER::addNewFootprint( COMPONENT* aComponent )
|
||||
|
||||
void BOARD_NETLIST_UPDATER::updateComponentClass( FOOTPRINT* aFootprint, COMPONENT* aNewComponent )
|
||||
{
|
||||
// Get the existing component class
|
||||
wxString curClassName;
|
||||
wxString curClassName, newClassName;
|
||||
COMPONENT_CLASS* newClass = nullptr;
|
||||
|
||||
if( const COMPONENT_CLASS* curClass = aFootprint->GetComponentClass() )
|
||||
curClassName = curClass->GetFullName();
|
||||
|
||||
// Calculate the new component class
|
||||
COMPONENT_CLASS* newClass = m_board->GetComponentClassManager().GetEffectiveComponentClass(
|
||||
aNewComponent->GetComponentClassNames() );
|
||||
wxString newClassName = newClass->GetFullName();
|
||||
if( m_isDryRun )
|
||||
{
|
||||
newClassName = COMPONENT_CLASS_MANAGER::GetFullClassNameForConstituents(
|
||||
aNewComponent->GetComponentClassNames() );
|
||||
}
|
||||
else
|
||||
{
|
||||
newClass = m_board->GetComponentClassManager().GetEffectiveComponentClass(
|
||||
aNewComponent->GetComponentClassNames() );
|
||||
newClassName = newClass->GetFullName();
|
||||
}
|
||||
|
||||
if( curClassName == newClassName )
|
||||
return;
|
||||
@ -228,6 +236,8 @@ void BOARD_NETLIST_UPDATER::updateComponentClass( FOOTPRINT* aFootprint, COMPONE
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT_MSG( newClass != nullptr, "Component class should not be nullptr" );
|
||||
|
||||
aFootprint->SetComponentClass( newClass );
|
||||
msg.Printf( _( "Changed %s component class from %s to %s." ), aFootprint->GetReference(),
|
||||
curClassName, newClassName );
|
||||
@ -1195,12 +1205,14 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
||||
cacheCopperZoneConnections();
|
||||
|
||||
// First mark all nets (except <no net>) as stale; we'll update those which are current
|
||||
// in the following two loops.
|
||||
// in the following two loops. Also prepare the component class manager for updates.
|
||||
//
|
||||
if( !m_isDryRun )
|
||||
{
|
||||
for( NETINFO_ITEM* net : m_board->GetNetInfo() )
|
||||
net->SetIsCurrent( net->GetNetCode() == 0 );
|
||||
|
||||
m_board->GetComponentClassManager().InitNetlistUpdate();
|
||||
}
|
||||
|
||||
// Next go through the netlist updating all board footprints which have matching component
|
||||
@ -1361,6 +1373,9 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
||||
|
||||
if( !m_isDryRun )
|
||||
{
|
||||
// Finalise the component class manager
|
||||
m_board->GetComponentClassManager().FinishNetlistUpdate();
|
||||
|
||||
m_board->BuildConnectivity();
|
||||
testConnectivity( aNetlist, footprintMap );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user