mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Implement Component Classes
- Adds Component Class field to SCH_DIRECTIVE_LABEL - Adds SCH_SYMBOLs to SCH_RULE_AREA item lists - SCH_SYMBOLs resolve Component Class directives - Netlist exporter / importer handles Component Class names - Adds DRC expressions and functions - Adds QA check for component class netlist export
This commit is contained in:
parent
ae96ac6d2e
commit
d64a112971
@ -745,6 +745,7 @@ set( PCB_COMMON_SRCS
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/teardrop/teardrop_parameters.cpp #needed by board_design_settings.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/router/pns_meander.cpp #needed by board_design_settings.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/board.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/component_class_manager.cpp #needed by board.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/board_item.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_dimension.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_shape.cpp
|
||||
|
@ -1,6 +1,8 @@
|
||||
class
|
||||
code
|
||||
comp
|
||||
components
|
||||
component_classes
|
||||
datasheet
|
||||
date
|
||||
description
|
||||
|
@ -65,6 +65,7 @@ center
|
||||
chamfer
|
||||
chamfer_ratio
|
||||
circle
|
||||
class
|
||||
clearance
|
||||
clearance_min
|
||||
color
|
||||
@ -73,6 +74,7 @@ column_count
|
||||
column_widths
|
||||
comment
|
||||
company
|
||||
component_classes
|
||||
connect
|
||||
connect_pads
|
||||
copperpour
|
||||
|
@ -414,6 +414,21 @@ XNODE* NETLIST_EXPORTER_XML::makeSymbols( unsigned aCtl )
|
||||
xsheetpath->AddAttribute( wxT( "names" ), sheet.PathHumanReadable() );
|
||||
xsheetpath->AddAttribute( wxT( "tstamps" ), sheet.PathAsString() );
|
||||
|
||||
// Node for component class
|
||||
std::vector<wxString> compClassNames =
|
||||
getComponentClassNamesForAllSymbolUnits( symbol, sheet, sheetList );
|
||||
|
||||
if( compClassNames.size() > 0 )
|
||||
{
|
||||
XNODE* xcompclasslist;
|
||||
xcomp->AddChild( xcompclasslist = node( wxT( "component_classes" ) ) );
|
||||
|
||||
for( const wxString& compClass : compClassNames )
|
||||
{
|
||||
xcompclasslist->AddChild( node( wxT( "class" ), UnescapeString( compClass ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
XNODE* xunits; // Node for extra units
|
||||
xcomp->AddChild( xunits = node( wxT( "tstamps" ) ) );
|
||||
|
||||
@ -445,6 +460,49 @@ XNODE* NETLIST_EXPORTER_XML::makeSymbols( unsigned aCtl )
|
||||
}
|
||||
|
||||
|
||||
std::vector<wxString> NETLIST_EXPORTER_XML::getComponentClassNamesForAllSymbolUnits(
|
||||
SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH& aSymbolSheet, const SCH_SHEET_LIST& aSheetList )
|
||||
{
|
||||
std::unordered_set<wxString> compClassNames = aSymbol->GetComponentClassNames( &aSymbolSheet );
|
||||
int primaryUnit = aSymbol->GetUnitSelection( &aSymbolSheet );
|
||||
|
||||
if( aSymbol->GetUnitCount() > 1 )
|
||||
{
|
||||
wxString ref = aSymbol->GetRef( &aSymbolSheet );
|
||||
|
||||
for( const SCH_SHEET_PATH& sheet : aSheetList )
|
||||
{
|
||||
for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
|
||||
{
|
||||
SCH_SYMBOL* symbol2 = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
wxString ref2 = symbol2->GetRef( &sheet );
|
||||
int otherUnit = symbol2->GetUnitSelection( &sheet );
|
||||
|
||||
if( ref2.CmpNoCase( ref ) != 0 )
|
||||
continue;
|
||||
|
||||
if( otherUnit == primaryUnit )
|
||||
continue;
|
||||
|
||||
std::unordered_set<wxString> otherClassNames =
|
||||
symbol2->GetComponentClassNames( &sheet );
|
||||
compClassNames.insert( otherClassNames.begin(), otherClassNames.end() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<wxString> sortedCompClassNames( compClassNames.begin(), compClassNames.end() );
|
||||
std::sort( sortedCompClassNames.begin(), sortedCompClassNames.end(),
|
||||
[]( const wxString& str1, const wxString& str2 )
|
||||
{
|
||||
return str1.Cmp( str2 ) < 0;
|
||||
} );
|
||||
|
||||
return sortedCompClassNames;
|
||||
}
|
||||
|
||||
|
||||
XNODE* NETLIST_EXPORTER_XML::makeDesignHeader()
|
||||
{
|
||||
SCH_SCREEN* screen;
|
||||
|
@ -133,6 +133,14 @@ protected:
|
||||
void addSymbolFields( XNODE* aNode, SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH& aSheet,
|
||||
const SCH_SHEET_LIST& aSheetList);
|
||||
|
||||
/**
|
||||
* Finds all component class names attached to any sub-unit of a given symbol
|
||||
*/
|
||||
std::vector<wxString>
|
||||
getComponentClassNamesForAllSymbolUnits( SCH_SYMBOL* aSymbol,
|
||||
const SCH_SHEET_PATH& aSymbolSheet,
|
||||
const SCH_SHEET_LIST& aSheetList );
|
||||
|
||||
bool m_resolveTextVars; // Export textVar references resolved
|
||||
|
||||
private:
|
||||
|
@ -183,13 +183,20 @@ void SCH_FIELD::SetId( int aId )
|
||||
// We can't use defined IDs for labels because there can be multiple net class
|
||||
// assignments.
|
||||
|
||||
if( GetCanonicalName() == wxT( "Netclass" ) )
|
||||
if( GetCanonicalName() == wxT( "Netclass" )
|
||||
|| GetCanonicalName() == wxT( "Component Class" ) )
|
||||
{
|
||||
SetLayer( LAYER_NETCLASS_REFS );
|
||||
}
|
||||
else if( GetCanonicalName() == wxT( "Intersheetrefs" ) )
|
||||
{
|
||||
SetLayer( LAYER_INTERSHEET_REFS );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLayer( LAYER_FIELDS );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1002,7 +1002,7 @@ const BOX2I SCH_LABEL_BASE::GetBoundingBox() const
|
||||
|
||||
for( const SCH_FIELD& field : m_fields )
|
||||
{
|
||||
if( field.IsVisible() )
|
||||
if( field.IsVisible() && field.GetText() != wxEmptyString )
|
||||
{
|
||||
BOX2I fieldBBox = field.GetBoundingBox();
|
||||
|
||||
@ -1734,6 +1734,9 @@ void SCH_DIRECTIVE_LABEL::AutoplaceFields( SCH_SCREEN* aScreen, bool aManual )
|
||||
|
||||
for( SCH_FIELD& field : m_fields )
|
||||
{
|
||||
if( field.GetText() == wxEmptyString )
|
||||
continue;
|
||||
|
||||
switch( GetSpinStyle() )
|
||||
{
|
||||
default:
|
||||
|
@ -267,6 +267,10 @@ void SCH_RULE_AREA::RefreshContainedItemsAndDirectives(
|
||||
addContainedItem( areaItem );
|
||||
}
|
||||
}
|
||||
else if( areaItem->IsType( { SCH_SYMBOL_T } ) )
|
||||
{
|
||||
addContainedItem( areaItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,7 +320,7 @@ const std::unordered_set<SCH_ITEM*>& SCH_RULE_AREA::GetContainedItems() const
|
||||
}
|
||||
|
||||
|
||||
const std::unordered_set<SCH_DIRECTIVE_LABEL*> SCH_RULE_AREA::GetDirectives() const
|
||||
const std::unordered_set<SCH_DIRECTIVE_LABEL*>& SCH_RULE_AREA::GetDirectives() const
|
||||
{
|
||||
return m_directives;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
const std::unordered_set<SCH_ITEM*>& GetContainedItems() const;
|
||||
|
||||
/// @brief Returns the set of all directive labels attached to the rule area border
|
||||
const std::unordered_set<SCH_DIRECTIVE_LABEL*> GetDirectives() const;
|
||||
const std::unordered_set<SCH_DIRECTIVE_LABEL*>& GetDirectives() const;
|
||||
|
||||
/// @brief Resolves the netclass of this rule area from connected directive labels
|
||||
/// @returns The resolved netclass (if any), and the SCH_ITEM providing the declaration
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <settings/settings_manager.h>
|
||||
#include <sch_plotter.h>
|
||||
#include <string_utils.h>
|
||||
#include <sch_rule_area.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
@ -2872,6 +2873,38 @@ bool SCH_SYMBOL::IsNormal() const
|
||||
}
|
||||
|
||||
|
||||
std::unordered_set<wxString> SCH_SYMBOL::GetComponentClassNames( const SCH_SHEET_PATH* aPath ) const
|
||||
{
|
||||
std::unordered_set<wxString> componentClass;
|
||||
|
||||
auto getComponentClassFields = [&]( const auto& fields )
|
||||
{
|
||||
for( const SCH_FIELD& field : fields )
|
||||
{
|
||||
if( field.GetCanonicalName() == wxT( "Component Class" ) )
|
||||
{
|
||||
if( field.GetShownText( aPath, false ) != wxEmptyString )
|
||||
componentClass.insert( field.GetShownText( aPath, false ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// First get component classes set on the symbol itself
|
||||
getComponentClassFields( m_fields );
|
||||
|
||||
// Now get component classes set on any enclosing rule areas
|
||||
for( const SCH_RULE_AREA* ruleArea : m_rule_areas_cache )
|
||||
{
|
||||
for( const SCH_DIRECTIVE_LABEL* label : ruleArea->GetDirectives() )
|
||||
{
|
||||
getComponentClassFields( label->GetFields() );
|
||||
}
|
||||
}
|
||||
|
||||
return componentClass;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::operator==( const SCH_ITEM& aOther ) const
|
||||
{
|
||||
if( Type() != aOther.Type() )
|
||||
|
@ -901,6 +901,9 @@ public:
|
||||
|
||||
double Similarity( const SCH_ITEM& aOther ) const override;
|
||||
|
||||
/// Returns the component classes this symbol belongs in
|
||||
std::unordered_set<wxString> GetComponentClassNames( const SCH_SHEET_PATH* aPath ) const;
|
||||
|
||||
bool operator==( const SCH_ITEM& aOther ) const override;
|
||||
|
||||
private:
|
||||
|
@ -481,10 +481,11 @@ TOOL_ACTION EE_ACTIONS::placeLabel( TOOL_ACTION_ARGS()
|
||||
.Icon( BITMAPS::add_label )
|
||||
.Flags( AF_ACTIVATE ) );
|
||||
|
||||
TOOL_ACTION EE_ACTIONS::placeClassLabel( TOOL_ACTION_ARGS()
|
||||
TOOL_ACTION
|
||||
EE_ACTIONS::placeClassLabel( TOOL_ACTION_ARGS()
|
||||
.Name( "eeschema.InteractiveDrawing.placeClassLabel" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Place Net Class Directives" ) )
|
||||
.FriendlyName( _( "Place Directive Labels" ) )
|
||||
.Icon( BITMAPS::add_class_flag )
|
||||
.Flags( AF_ACTIVATE ) );
|
||||
|
||||
|
@ -1546,6 +1546,8 @@ SCH_TEXT* SCH_DRAWING_TOOLS::createNewText( const VECTOR2I& aPosition, int aType
|
||||
labelItem = new SCH_DIRECTIVE_LABEL( aPosition );
|
||||
labelItem->SetShape( m_lastNetClassFlagShape );
|
||||
labelItem->GetFields().emplace_back( SCH_FIELD( {0,0}, 0, labelItem, wxT( "Netclass" ) ) );
|
||||
labelItem->GetFields().emplace_back(
|
||||
SCH_FIELD( { 0, 0 }, 0, labelItem, wxT( "Component Class" ) ) );
|
||||
labelItem->GetFields().back().SetItalic( true );
|
||||
labelItem->GetFields().back().SetVisible( true );
|
||||
textItem = labelItem;
|
||||
|
@ -37,6 +37,7 @@
|
||||
class BOARD;
|
||||
class BOARD_DESIGN_SETTINGS;
|
||||
class BOARD_ITEM_CONTAINER;
|
||||
class COMPONENT_CLASS;
|
||||
class SHAPE_POLY_SET;
|
||||
class SHAPE_SEGMENT;
|
||||
class PCB_BASE_FRAME;
|
||||
@ -79,11 +80,8 @@ class BOARD_ITEM : public EDA_ITEM
|
||||
{
|
||||
public:
|
||||
BOARD_ITEM( BOARD_ITEM* aParent, KICAD_T idtype, PCB_LAYER_ID aLayer = F_Cu ) :
|
||||
EDA_ITEM( aParent, idtype, false, true ),
|
||||
m_layer( aLayer ),
|
||||
m_isKnockout( false ),
|
||||
m_isLocked( false ),
|
||||
m_group( nullptr )
|
||||
EDA_ITEM( aParent, idtype, false, true ), m_layer( aLayer ), m_isKnockout( false ),
|
||||
m_isLocked( false ), m_group( nullptr ), m_componentClass( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
@ -419,6 +417,12 @@ public:
|
||||
bool operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b ) const;
|
||||
};
|
||||
|
||||
void SetComponentClass( const COMPONENT_CLASS* aClass ) { m_componentClass = aClass; }
|
||||
|
||||
const COMPONENT_CLASS* GetComponentClass() const { return m_componentClass; }
|
||||
|
||||
wxString GetComponentClassAsString() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Return a string (to be shown to the user) describing a layer mask.
|
||||
@ -434,6 +438,8 @@ protected:
|
||||
bool m_isLocked;
|
||||
|
||||
PCB_GROUP* m_group;
|
||||
|
||||
const COMPONENT_CLASS* m_componentClass;
|
||||
};
|
||||
|
||||
#ifndef SWIG
|
||||
|
@ -316,6 +316,7 @@ set( PCBNEW_CLASS_SRCS
|
||||
array_pad_number_provider.cpp
|
||||
build_BOM_from_board.cpp
|
||||
cleanup_item.cpp
|
||||
component_class_manager.cpp
|
||||
convert_shape_list_to_polygon.cpp
|
||||
cross-probing.cpp
|
||||
edit.cpp
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <board_item_container.h>
|
||||
#include <board_stackup_manager/board_stackup.h>
|
||||
#include <component_class_manager.h>
|
||||
#include <embedded_files.h>
|
||||
#include <common.h> // Needed for stl hash extensions
|
||||
#include <convert_shape_list_to_polygon.h> // for OUTLINE_ERROR_HANDLER
|
||||
@ -1262,6 +1263,11 @@ public:
|
||||
*/
|
||||
void EmbedFonts() override;
|
||||
|
||||
/**
|
||||
* Gets the component class manager
|
||||
*/
|
||||
COMPONENT_CLASS_MANAGER& GetComponentClassManager() { return m_componentClassManager; }
|
||||
|
||||
// --------- Item order comparators ---------
|
||||
|
||||
struct cmp_items
|
||||
@ -1377,6 +1383,8 @@ private:
|
||||
std::vector<BOARD_LISTENER*> m_listeners;
|
||||
|
||||
bool m_embedFonts;
|
||||
|
||||
COMPONENT_CLASS_MANAGER m_componentClassManager;
|
||||
};
|
||||
|
||||
|
||||
|
@ -374,6 +374,17 @@ wxString BOARD_ITEM::GetParentAsString() const
|
||||
}
|
||||
|
||||
|
||||
wxString BOARD_ITEM::GetComponentClassAsString() const
|
||||
{
|
||||
if( m_componentClass )
|
||||
{
|
||||
return m_componentClass->GetFullName();
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
static struct BOARD_ITEM_DESC
|
||||
{
|
||||
BOARD_ITEM_DESC()
|
||||
@ -413,6 +424,13 @@ static struct BOARD_ITEM_DESC
|
||||
BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItem );
|
||||
return item && item->GetBoard() && !item->GetBoard()->IsFootprintHolder();
|
||||
} );
|
||||
|
||||
// Used only in DRC engine
|
||||
propMgr.AddProperty( new PROPERTY<BOARD_ITEM, wxString>(
|
||||
_HKI( "ComponentClass" ), NO_SETTER( BOARD_ITEM, wxString ),
|
||||
&BOARD_ITEM::GetComponentClassAsString ) )
|
||||
.SetIsHiddenFromLibraryEditors()
|
||||
.SetIsHiddenFromPropertiesManager();
|
||||
}
|
||||
} _BOARD_ITEM_DESC;
|
||||
|
||||
|
145
pcbnew/component_class_manager.cpp
Normal file
145
pcbnew/component_class_manager.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <component_class_manager.h>
|
||||
|
||||
|
||||
void COMPONENT_CLASS::AddConstituentClass( COMPONENT_CLASS* componentClass )
|
||||
{
|
||||
m_constituentClasses.push_back( componentClass );
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS::ContainsClassName( const wxString& className ) const
|
||||
{
|
||||
if( m_constituentClasses.size() == 0 )
|
||||
return false;
|
||||
|
||||
if( m_constituentClasses.size() == 1 )
|
||||
return m_name == className;
|
||||
|
||||
return std::any_of( m_constituentClasses.begin(), m_constituentClasses.end(),
|
||||
[&className]( const COMPONENT_CLASS* testClass )
|
||||
{
|
||||
return testClass->GetFullName() == className;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
wxString COMPONENT_CLASS::GetName() const
|
||||
{
|
||||
if( m_constituentClasses.size() == 0 )
|
||||
return wxT( "<None>" );
|
||||
|
||||
if( m_constituentClasses.size() == 1 )
|
||||
return m_name;
|
||||
|
||||
wxASSERT( m_constituentClasses.size() >= 2 );
|
||||
|
||||
wxString name;
|
||||
|
||||
if( m_constituentClasses.size() == 2 )
|
||||
{
|
||||
name.Printf( _( "%s and %s" ), m_constituentClasses[0]->GetName(),
|
||||
m_constituentClasses[1]->GetName() );
|
||||
}
|
||||
else if( m_constituentClasses.size() == 3 )
|
||||
{
|
||||
name.Printf( _( "%s, %s and %s" ), m_constituentClasses[0]->GetName(),
|
||||
m_constituentClasses[1]->GetName(), m_constituentClasses[2]->GetName() );
|
||||
}
|
||||
else if( m_constituentClasses.size() > 3 )
|
||||
{
|
||||
name.Printf( _( "%s, %s and %d more" ), m_constituentClasses[0]->GetName(),
|
||||
m_constituentClasses[1]->GetName(),
|
||||
static_cast<int>( m_constituentClasses.size() - 2 ) );
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS::IsEmpty() const
|
||||
{
|
||||
return m_constituentClasses.size() == 0;
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS_MANAGER::COMPONENT_CLASS_MANAGER()
|
||||
{
|
||||
m_noneClass = std::make_unique<COMPONENT_CLASS>( wxEmptyString );
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS*
|
||||
COMPONENT_CLASS_MANAGER::GetEffectiveComponentClass( std::unordered_set<wxString>& classNames )
|
||||
{
|
||||
if( classNames.size() == 0 )
|
||||
return m_noneClass.get();
|
||||
|
||||
auto getOrCreateClass = [this]( const wxString& className )
|
||||
{
|
||||
if( !m_classes.count( className ) )
|
||||
{
|
||||
std::unique_ptr<COMPONENT_CLASS> newClass =
|
||||
std::make_unique<COMPONENT_CLASS>( className );
|
||||
newClass->AddConstituentClass( newClass.get() );
|
||||
m_classes[className] = std::move( newClass );
|
||||
}
|
||||
|
||||
return m_classes[className].get();
|
||||
};
|
||||
|
||||
if( classNames.size() == 1 )
|
||||
{
|
||||
return getOrCreateClass( *classNames.begin() );
|
||||
}
|
||||
|
||||
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;
|
||||
} );
|
||||
|
||||
wxString fullName = sortedClassNames[0];
|
||||
|
||||
for( std::size_t i = 1; i < sortedClassNames.size(); ++i )
|
||||
{
|
||||
fullName += ",";
|
||||
fullName += sortedClassNames[i];
|
||||
}
|
||||
|
||||
if( !m_effectiveClasses.count( fullName ) )
|
||||
{
|
||||
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();
|
||||
}
|
100
pcbnew/component_class_manager.h
Normal file
100
pcbnew/component_class_manager.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PCBNEW_COMPONENT_CLASS_MANAGER_H
|
||||
#define PCBNEW_COMPONENT_CLASS_MANAGER_H
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <board_item.h>
|
||||
|
||||
/*
|
||||
* A lightweight representation of a component class. The membership within
|
||||
* m_consituentClasses allows determination of the type of class this is:
|
||||
*
|
||||
* m_constituentClasses.size() == 0: This is a null class (no assigment).
|
||||
* m_name is empty.
|
||||
* m_constituentClasses.size() == 1: This is an atomic class. The constituent class
|
||||
* pointer refers to itself. m_name contains the name of the atomic class
|
||||
* m_constituentClasses.size() > 1: This is a composite class. The constituent class
|
||||
* pointers refer to all atomic members. m_name contains a comma-delimited list of
|
||||
* all atomic member class names.
|
||||
*/
|
||||
class COMPONENT_CLASS
|
||||
{
|
||||
public:
|
||||
COMPONENT_CLASS( const wxString& name ) : m_name( name ) {}
|
||||
|
||||
/// Fetches the display name of this component class
|
||||
wxString GetName() const;
|
||||
|
||||
/// Fetches the full name of this component class
|
||||
const wxString& GetFullName() const { return m_name; }
|
||||
|
||||
/// Adds a constituent component class to an effective component class
|
||||
void AddConstituentClass( COMPONENT_CLASS* componentClass );
|
||||
|
||||
/// Determines if this (effective) component class contains a specific sub-class
|
||||
bool ContainsClassName( const wxString& className ) const;
|
||||
|
||||
/// Determines if this (effective) component class is empty (i.e. no classes defined)
|
||||
bool IsEmpty() const;
|
||||
|
||||
/// Fetches a vector of the constituent classes for this (effective) class
|
||||
const std::vector<COMPONENT_CLASS*>& GetConstituentClasses() const
|
||||
{
|
||||
return m_constituentClasses;
|
||||
}
|
||||
|
||||
private:
|
||||
/// The full name of the component class
|
||||
wxString m_name;
|
||||
|
||||
/// The COMPONENT_CLASS objects contributing to this complete component class
|
||||
std::vector<COMPONENT_CLASS*> m_constituentClasses;
|
||||
};
|
||||
|
||||
class COMPONENT_CLASS_MANAGER
|
||||
{
|
||||
public:
|
||||
COMPONENT_CLASS_MANAGER();
|
||||
|
||||
/// @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
|
||||
COMPONENT_CLASS* GetEffectiveComponentClass( std::unordered_set<wxString>& classNames );
|
||||
|
||||
/// Returns the unassigned component class
|
||||
const COMPONENT_CLASS* GetNoneComponentClass() const { return m_noneClass.get(); }
|
||||
|
||||
protected:
|
||||
/// All individual component classes
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_classes;
|
||||
|
||||
/// Generated effective component classes
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_effectiveClasses;
|
||||
|
||||
/// The class to represent an unassigned component class
|
||||
std::unique_ptr<COMPONENT_CLASS> m_noneClass;
|
||||
};
|
||||
|
||||
#endif
|
@ -1584,6 +1584,11 @@ void FOOTPRINT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
|
||||
aList.emplace_back( _( "Rotation" ), wxString::Format( wxT( "%.4g" ),
|
||||
GetOrientation().AsDegrees() ) );
|
||||
|
||||
if( m_componentClass )
|
||||
{
|
||||
aList.emplace_back( _( "Component Class" ), m_componentClass->GetName() );
|
||||
}
|
||||
|
||||
msg.Printf( _( "Footprint: %s" ), m_fpid.GetUniStringLibId() );
|
||||
msg2.Printf( _( "3D-Shape: %s" ), m_3D_Drawings.empty() ? _( "<none>" )
|
||||
: m_3D_Drawings.front().m_Filename );
|
||||
|
@ -147,6 +147,7 @@ FOOTPRINT* BOARD_NETLIST_UPDATER::addNewFootprint( COMPONENT* aComponent )
|
||||
}
|
||||
|
||||
FOOTPRINT* footprint = m_frame->LoadFootprint( aComponent->GetFPID() );
|
||||
footprint->SetComponentClass( m_board->GetComponentClassManager().GetNoneComponentClass() );
|
||||
|
||||
if( footprint == nullptr )
|
||||
{
|
||||
@ -201,6 +202,40 @@ FOOTPRINT* BOARD_NETLIST_UPDATER::addNewFootprint( COMPONENT* aComponent )
|
||||
}
|
||||
|
||||
|
||||
void BOARD_NETLIST_UPDATER::updateComponentClass( FOOTPRINT* aFootprint, COMPONENT* aNewComponent )
|
||||
{
|
||||
// Get the existing component class
|
||||
wxString curClassName;
|
||||
|
||||
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( curClassName == newClassName )
|
||||
return;
|
||||
|
||||
wxString msg;
|
||||
|
||||
if( m_isDryRun )
|
||||
{
|
||||
msg.Printf( _( "Change %s component class from %s to %s." ), aFootprint->GetReference(),
|
||||
curClassName, newClassName );
|
||||
}
|
||||
else
|
||||
{
|
||||
aFootprint->SetComponentClass( newClass );
|
||||
msg.Printf( _( "Changed %s component class from %s to %s." ), aFootprint->GetReference(),
|
||||
curClassName, newClassName );
|
||||
}
|
||||
|
||||
m_reporter->Report( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
|
||||
|
||||
FOOTPRINT* BOARD_NETLIST_UPDATER::replaceFootprint( NETLIST& aNetlist, FOOTPRINT* aFootprint,
|
||||
COMPONENT* aNewComponent )
|
||||
{
|
||||
@ -395,8 +430,11 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
|
||||
for( PCB_FIELD* field : aPcbFootprint->GetFields() )
|
||||
{
|
||||
// These fields are individually checked above
|
||||
if( field->IsReference() || field->IsValue() || field->IsFootprint() )
|
||||
if( field->IsReference() || field->IsValue() || field->IsFootprint()
|
||||
|| field->IsComponentClass() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fpFieldsAsMap[field->GetName()] = field->GetText();
|
||||
}
|
||||
@ -407,6 +445,9 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
|
||||
compFields.erase( GetCanonicalFieldName( VALUE_FIELD ) );
|
||||
compFields.erase( GetCanonicalFieldName( FOOTPRINT_FIELD ) );
|
||||
|
||||
// Remove any component class fields - these are not editable in the pcb editor
|
||||
compFields.erase( wxT( "Component Class" ) );
|
||||
|
||||
// Fields are stored as an ordered map, but we don't (yet) support reordering
|
||||
// the footprint fields to match the symbol, so we manually check the fields
|
||||
// in the order they are stored in the symbol.
|
||||
@ -1214,6 +1255,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
||||
|
||||
updateFootprintParameters( tmp, component );
|
||||
updateComponentPadConnections( tmp, component );
|
||||
updateComponentClass( tmp, component );
|
||||
}
|
||||
|
||||
matchCount++;
|
||||
@ -1236,6 +1278,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
||||
|
||||
updateFootprintParameters( footprint, component );
|
||||
updateComponentPadConnections( footprint, component );
|
||||
updateComponentClass( footprint, component );
|
||||
}
|
||||
}
|
||||
else if( matchCount > 1 )
|
||||
|
@ -111,6 +111,8 @@ private:
|
||||
|
||||
bool updateComponentPadConnections( FOOTPRINT* aFootprint, COMPONENT* aNewComponent );
|
||||
|
||||
void updateComponentClass( FOOTPRINT* aFootprint, COMPONENT* aNewComponent );
|
||||
|
||||
void cacheCopperZoneConnections();
|
||||
|
||||
bool updateCopperZoneNets( NETLIST& aNetlist );
|
||||
|
@ -287,6 +287,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
|
||||
* (libsource (lib conn) (part DB25))
|
||||
* (property (name PINCOUNT) (value 25))
|
||||
* (sheetpath (names /) (tstamps /))
|
||||
* (component_classes (class (name "CLASS")))
|
||||
* (tstamp 68183921-93a5-49ac-91b0-49d05a0e1647))
|
||||
*
|
||||
* other fields (unused) are skipped
|
||||
@ -305,6 +306,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
|
||||
std::vector<KIID> uuids;
|
||||
std::map<wxString, wxString> properties;
|
||||
nlohmann::ordered_map<wxString, wxString> fields;
|
||||
std::unordered_set<wxString> componentClasses;
|
||||
|
||||
// The token comp was read, so the next data is (ref P1)
|
||||
while( (token = NextTok() ) != T_RIGHT )
|
||||
@ -469,6 +471,24 @@ void KICAD_NETLIST_PARSER::parseComponent()
|
||||
|
||||
break;
|
||||
|
||||
case T_component_classes:
|
||||
{
|
||||
while( ( token = NextTok() ) != T_RIGHT )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
|
||||
if( ( token = NextTok() ) != T_class )
|
||||
Expecting( T_class );
|
||||
|
||||
NeedSYMBOLorNUMBER();
|
||||
componentClasses.insert( From_UTF8( CurText() ) );
|
||||
NeedRIGHT();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Skip not used data (i.e all other tokens)
|
||||
skipCurrent();
|
||||
@ -491,6 +511,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
|
||||
component->SetProperties( properties );
|
||||
component->SetFields( fields );
|
||||
component->SetHumanReadablePath( humanSheetPath );
|
||||
component->SetComponentClassNames( componentClasses );
|
||||
m_netlist->AddComponent( component );
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
#include <wx/arrstr.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <lib_id.h>
|
||||
#include <footprint.h>
|
||||
@ -175,6 +176,13 @@ public:
|
||||
void SetHumanReadablePath( const wxString& aPath ) { m_humanReadablePath = aPath; }
|
||||
const wxString& GetHumanReadablePath() const { return m_humanReadablePath; }
|
||||
|
||||
void SetComponentClassNames( const std::unordered_set<wxString>& aClassNames )
|
||||
{
|
||||
m_componentClassNames = aClassNames;
|
||||
}
|
||||
|
||||
std::unordered_set<wxString>& GetComponentClassNames() { return m_componentClassNames; }
|
||||
|
||||
private:
|
||||
std::vector<COMPONENT_NET> m_nets; ///< list of nets shared by the component pins
|
||||
|
||||
@ -215,6 +223,9 @@ private:
|
||||
/// Component-specific user fields found in the netlist.
|
||||
nlohmann::ordered_map<wxString, wxString> m_fields;
|
||||
|
||||
/// Component classes for this footprint
|
||||
std::unordered_set<wxString> m_componentClassNames;
|
||||
|
||||
static COMPONENT_NET m_emptyNet;
|
||||
};
|
||||
|
||||
|
@ -2484,6 +2484,7 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
|
||||
aNew->SetSheetfile( aExisting->GetSheetfile() );
|
||||
aNew->SetSheetname( aExisting->GetSheetname() );
|
||||
aNew->SetFilters( aExisting->GetFilters() );
|
||||
aNew->SetComponentClass( aExisting->GetComponentClass() );
|
||||
|
||||
aCommit.Remove( aExisting );
|
||||
aCommit.Add( aNew );
|
||||
|
@ -71,6 +71,7 @@ public:
|
||||
bool IsValue() const { return m_id == VALUE_FIELD; }
|
||||
bool IsFootprint() const { return m_id == FOOTPRINT_FIELD; }
|
||||
bool IsDatasheet() const { return m_id == DATASHEET_FIELD; }
|
||||
bool IsComponentClass() const { return GetName() == wxT( "Component Class" ); }
|
||||
|
||||
bool IsMandatoryField() const { return m_id < MANDATORY_FIELDS; }
|
||||
|
||||
|
@ -1214,6 +1214,22 @@ void PCB_IO_KICAD_SEXPR::format( const FOOTPRINT* aFootprint, int aNestLevel ) c
|
||||
m_out->Print( aNestLevel + 1, ")\n" );
|
||||
}
|
||||
|
||||
if( const COMPONENT_CLASS* compClass = aFootprint->GetComponentClass() )
|
||||
{
|
||||
if( !compClass->IsEmpty() )
|
||||
{
|
||||
m_out->Print( aNestLevel + 1, "(component_classes\n" );
|
||||
|
||||
for( const COMPONENT_CLASS* constituent : compClass->GetConstituentClasses() )
|
||||
{
|
||||
m_out->Print( aNestLevel + 2, "(class %s)\n",
|
||||
m_out->Quotew( constituent->GetFullName() ).c_str() );
|
||||
}
|
||||
|
||||
m_out->Print( aNestLevel + 1, ")\n" );
|
||||
}
|
||||
}
|
||||
|
||||
if( !aFootprint->GetFilters().empty() )
|
||||
{
|
||||
m_out->Print( aNestLevel + 1, "(property ki_fp_filters %s)\n",
|
||||
|
@ -161,7 +161,8 @@ class PCB_IO_KICAD_SEXPR; // forward decl
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20240617 // Table angles
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20240703 // User layer types
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20240706 // Embedded Files
|
||||
#define SEXPR_BOARD_FILE_VERSION 20240819 // Embedded Files - Update hash algorithm to Murmur3
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20240819 // Embedded Files - Update hash algorithm to Murmur3
|
||||
#define SEXPR_BOARD_FILE_VERSION 20240928 // Component classes
|
||||
|
||||
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
|
||||
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting
|
||||
|
@ -4281,6 +4281,11 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a
|
||||
|
||||
footprint->SetInitialComments( aInitialComments );
|
||||
|
||||
if( m_board )
|
||||
{
|
||||
footprint->SetComponentClass( m_board->GetComponentClassManager().GetNoneComponentClass() );
|
||||
}
|
||||
|
||||
token = NextTok();
|
||||
|
||||
if( !IsSymbol( token ) && token != T_NUMBER )
|
||||
@ -4773,13 +4778,41 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a
|
||||
break;
|
||||
}
|
||||
|
||||
case T_component_classes:
|
||||
{
|
||||
std::unordered_set<wxString> componentClassNames;
|
||||
|
||||
while( ( token = NextTok() ) != T_RIGHT )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
|
||||
if( ( token = NextTok() ) != T_class )
|
||||
Expecting( T_class );
|
||||
|
||||
NeedSYMBOLorNUMBER();
|
||||
componentClassNames.insert( From_UTF8( CurText() ) );
|
||||
NeedRIGHT();
|
||||
}
|
||||
|
||||
if( m_board )
|
||||
{
|
||||
const COMPONENT_CLASS* componentClass =
|
||||
m_board->GetComponentClassManager().GetEffectiveComponentClass(
|
||||
componentClassNames );
|
||||
footprint->SetComponentClass( componentClass );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Expecting( "at, descr, locked, placed, tedit, tstamp, uuid, "
|
||||
"autoplace_cost90, autoplace_cost180, attr, clearance, "
|
||||
"embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
|
||||
"fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
|
||||
"solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
|
||||
"version, zone, or zone_connect" );
|
||||
"version, zone, zone_connect, or component_classes" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,6 +165,65 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class PCBEXPR_COMPONENT_CLASS_VALUE : public LIBEVAL::VALUE
|
||||
{
|
||||
public:
|
||||
PCBEXPR_COMPONENT_CLASS_VALUE( BOARD_ITEM* aItem ) :
|
||||
LIBEVAL::VALUE( wxEmptyString ), m_item( aItem ){};
|
||||
|
||||
const wxString& AsString() const override
|
||||
{
|
||||
const COMPONENT_CLASS* compClass = m_item->GetComponentClass();
|
||||
|
||||
if( compClass )
|
||||
{
|
||||
const_cast<PCBEXPR_COMPONENT_CLASS_VALUE*>( this )->Set( compClass->GetFullName() );
|
||||
}
|
||||
|
||||
return LIBEVAL::VALUE::AsString();
|
||||
}
|
||||
|
||||
bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override
|
||||
{
|
||||
if( const PCBEXPR_COMPONENT_CLASS_VALUE* bValue =
|
||||
dynamic_cast<const PCBEXPR_COMPONENT_CLASS_VALUE*>( b ) )
|
||||
{
|
||||
const COMPONENT_CLASS* aClass = m_item->GetComponentClass();
|
||||
const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
|
||||
|
||||
// Note this depends on COMPONENT_CLASS_MANAGER maintaining ownership
|
||||
// of all unique component class objects
|
||||
return aClass == bClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LIBEVAL::VALUE::EqualTo( aCtx, b );
|
||||
}
|
||||
}
|
||||
|
||||
bool NotEqualTo( LIBEVAL::CONTEXT* aCtx, const LIBEVAL::VALUE* b ) const override
|
||||
{
|
||||
if( const PCBEXPR_COMPONENT_CLASS_VALUE* bValue =
|
||||
dynamic_cast<const PCBEXPR_COMPONENT_CLASS_VALUE*>( b ) )
|
||||
{
|
||||
const COMPONENT_CLASS* aClass = m_item->GetComponentClass();
|
||||
const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
|
||||
|
||||
// Note this depends on COMPONENT_CLASS_MANAGER maintaining ownership
|
||||
// of all unique component class objects
|
||||
return aClass != bClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LIBEVAL::VALUE::NotEqualTo( aCtx, b );
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
BOARD_ITEM* m_item;
|
||||
};
|
||||
|
||||
|
||||
class PCBEXPR_NET_VALUE : public LIBEVAL::VALUE
|
||||
{
|
||||
public:
|
||||
@ -279,6 +338,17 @@ LIBEVAL::VALUE* PCBEXPR_NETCLASS_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
||||
}
|
||||
|
||||
|
||||
LIBEVAL::VALUE* PCBEXPR_COMPONENT_CLASS_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
||||
{
|
||||
BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( GetObject( aCtx ) );
|
||||
|
||||
if( !item || item->Type() != PCB_FOOTPRINT_T )
|
||||
return new LIBEVAL::VALUE();
|
||||
|
||||
return new PCBEXPR_COMPONENT_CLASS_VALUE( item );
|
||||
}
|
||||
|
||||
|
||||
LIBEVAL::VALUE* PCBEXPR_NETNAME_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
||||
{
|
||||
BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( GetObject( aCtx ) );
|
||||
@ -326,6 +396,15 @@ std::unique_ptr<LIBEVAL::VAR_REF> PCBEXPR_UCODE::CreateVarRef( const wxString& a
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
else if( aField.CmpNoCase( wxT( "ComponentClass" ) ) == 0 )
|
||||
{
|
||||
if( aVar == wxT( "A" ) )
|
||||
return std::make_unique<PCBEXPR_COMPONENT_CLASS_REF>( 0 );
|
||||
else if( aVar == wxT( "B" ) )
|
||||
return std::make_unique<PCBEXPR_COMPONENT_CLASS_REF>( 1 );
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
else if( aField.CmpNoCase( wxT( "NetName" ) ) == 0 )
|
||||
{
|
||||
if( aVar == wxT( "A" ) )
|
||||
|
@ -127,6 +127,19 @@ public:
|
||||
};
|
||||
|
||||
|
||||
// "Object code" version of a component class reference (for performance).
|
||||
class PCBEXPR_COMPONENT_CLASS_REF : public PCBEXPR_VAR_REF
|
||||
{
|
||||
public:
|
||||
PCBEXPR_COMPONENT_CLASS_REF( int aItemIndex ) : PCBEXPR_VAR_REF( aItemIndex )
|
||||
{
|
||||
SetType( LIBEVAL::VT_STRING );
|
||||
}
|
||||
|
||||
LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override;
|
||||
};
|
||||
|
||||
|
||||
// "Object code" version of a netname reference (for performance).
|
||||
class PCBEXPR_NETNAME_REF : public PCBEXPR_VAR_REF
|
||||
{
|
||||
|
@ -1208,6 +1208,42 @@ static void hasNetclassFunc( LIBEVAL::CONTEXT* aCtx, void* self )
|
||||
} );
|
||||
}
|
||||
|
||||
static void hasComponentClassFunc( LIBEVAL::CONTEXT* aCtx, void* self )
|
||||
{
|
||||
LIBEVAL::VALUE* arg = aCtx->Pop();
|
||||
LIBEVAL::VALUE* result = aCtx->AllocValue();
|
||||
|
||||
result->Set( 0.0 );
|
||||
aCtx->Push( result );
|
||||
|
||||
if( !arg || arg->AsString().IsEmpty() )
|
||||
{
|
||||
if( aCtx->HasErrorCallback() )
|
||||
aCtx->ReportError(
|
||||
_( "Missing component class name argument to hasComponentClass()" ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PCBEXPR_VAR_REF* vref = static_cast<PCBEXPR_VAR_REF*>( self );
|
||||
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
|
||||
|
||||
if( !item )
|
||||
return;
|
||||
|
||||
result->SetDeferredEval(
|
||||
[item, arg]() -> double
|
||||
{
|
||||
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
|
||||
const COMPONENT_CLASS* compClass = boardItem->GetComponentClass();
|
||||
|
||||
if( compClass && compClass->ContainsClassName( arg->AsString() ) )
|
||||
return 1.0;
|
||||
|
||||
return 0.0;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
PCBEXPR_BUILTIN_FUNCTIONS::PCBEXPR_BUILTIN_FUNCTIONS()
|
||||
{
|
||||
@ -1249,4 +1285,5 @@ void PCBEXPR_BUILTIN_FUNCTIONS::RegisterAllFunctions()
|
||||
RegisterFunc( wxT( "getField('x')" ), getFieldFunc );
|
||||
|
||||
RegisterFunc( wxT( "hasNetclass('x')" ), hasNetclassFunc );
|
||||
RegisterFunc( wxT( "hasComponentClass('x')" ), hasComponentClassFunc );
|
||||
}
|
||||
|
@ -0,0 +1,2 @@
|
||||
(kicad_pcb (version 20240928) (generator "pcbnew") (generator_version "8.99")
|
||||
)
|
@ -0,0 +1,428 @@
|
||||
{
|
||||
"board": {
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {},
|
||||
"diff_pair_dimensions": [],
|
||||
"drc_exclusions": [],
|
||||
"rules": {},
|
||||
"track_widths": [],
|
||||
"via_dimensions": []
|
||||
},
|
||||
"ipc2581": {
|
||||
"dist": "",
|
||||
"distpn": "",
|
||||
"internal_id": "",
|
||||
"mfg": "",
|
||||
"mpn": ""
|
||||
},
|
||||
"layer_pairs": [],
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"endpoint_off_grid": "warning",
|
||||
"extra_units": "error",
|
||||
"footprint_filter": "ignore",
|
||||
"footprint_link_issues": "warning",
|
||||
"four_way_junction": "ignore",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_multiple_wires": "warning",
|
||||
"lib_symbol_issues": "warning",
|
||||
"lib_symbol_mismatch": "warning",
|
||||
"missing_bidi_pin": "warning",
|
||||
"missing_input_pin": "warning",
|
||||
"missing_power_pin": "error",
|
||||
"missing_unit": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "warning",
|
||||
"no_connect_dangling": "warning",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "warning",
|
||||
"power_pin_not_driven": "error",
|
||||
"same_local_global_label": "warning",
|
||||
"similar_label_and_power": "warning",
|
||||
"similar_labels": "warning",
|
||||
"similar_power": "warning",
|
||||
"simulation_model_issue": "ignore",
|
||||
"single_global_label": "ignore",
|
||||
"unannotated": "error",
|
||||
"unconnected_wire_endpoint": "warning",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "component_classes.kicad_pro",
|
||||
"version": 1
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.2,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"priority": -1,
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.2,
|
||||
"via_diameter": 0.6,
|
||||
"via_drill": 0.3,
|
||||
"wire_width": 6
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 4
|
||||
},
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": []
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "",
|
||||
"plot": "",
|
||||
"pos_files": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "",
|
||||
"svg": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"bom_export_filename": "${PROJECTNAME}.csv",
|
||||
"bom_fmt_presets": [],
|
||||
"bom_fmt_settings": {
|
||||
"field_delimiter": ",",
|
||||
"keep_line_breaks": false,
|
||||
"keep_tabs": false,
|
||||
"name": "CSV",
|
||||
"ref_delimiter": ",",
|
||||
"ref_range_delimiter": "",
|
||||
"string_delimiter": "\""
|
||||
},
|
||||
"bom_presets": [],
|
||||
"bom_settings": {
|
||||
"exclude_dnp": false,
|
||||
"fields_ordered": [
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Reference",
|
||||
"name": "Reference",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Qty",
|
||||
"name": "${QUANTITY}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Value",
|
||||
"name": "Value",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "DNP",
|
||||
"name": "${DNP}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Exclude from BOM",
|
||||
"name": "${EXCLUDE_FROM_BOM}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Exclude from Board",
|
||||
"name": "${EXCLUDE_FROM_BOARD}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Footprint",
|
||||
"name": "Footprint",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Datasheet",
|
||||
"name": "Datasheet",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Description",
|
||||
"name": "Description",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "#",
|
||||
"name": "${ITEM_NUMBER}",
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"filter_string": "",
|
||||
"group_symbols": true,
|
||||
"include_excluded_from_bom": true,
|
||||
"name": "",
|
||||
"sort_asc": true,
|
||||
"sort_field": "Reference"
|
||||
},
|
||||
"connection_grid_size": 50.0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"field_names": [],
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.375,
|
||||
"operating_point_overlay_i_precision": 3,
|
||||
"operating_point_overlay_i_range": "~A",
|
||||
"operating_point_overlay_v_precision": 3,
|
||||
"operating_point_overlay_v_range": "~V",
|
||||
"overbar_offset_ratio": 1.23,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.15
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "KiCad",
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"space_save_all_events": true,
|
||||
"spice_current_sheet_as_root": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"spice_model_current_sheet_as_root": true,
|
||||
"spice_save_all_currents": false,
|
||||
"spice_save_all_dissipations": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd",
|
||||
"Root"
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
}
|
@ -0,0 +1,610 @@
|
||||
(kicad_sch
|
||||
(version 20240819)
|
||||
(generator "eeschema")
|
||||
(generator_version "8.99")
|
||||
(uuid "bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd")
|
||||
(paper "A4")
|
||||
(lib_symbols
|
||||
(symbol "Amplifier_Operational:TL072"
|
||||
(pin_names
|
||||
(offset 0.127)
|
||||
)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(property "Reference" "U"
|
||||
(at 0 5.08 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Value" "TL072"
|
||||
(at 0 -5.08 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Footprint" ""
|
||||
(at 0 0 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
|
||||
(at 0 0 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Description" "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
|
||||
(at 0 0 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "ki_locked" ""
|
||||
(at 0 0 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "ki_keywords" "dual opamp"
|
||||
(at 0 0 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "ki_fp_filters" "SOIC*3.9x4.9mm*P1.27mm* DIP*W7.62mm* TO*99* OnSemi*Micro8* TSSOP*3x3mm*P0.65mm* TSSOP*4.4x3mm*P0.65mm* MSOP*3x3mm*P0.65mm* SSOP*3.9x4.9mm*P0.635mm* LFCSP*2x2mm*P0.5mm* *SIP* SOIC*5.3x6.2mm*P1.27mm*"
|
||||
(at 0 0 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(symbol "TL072_1_1"
|
||||
(polyline
|
||||
(pts
|
||||
(xy -5.08 5.08) (xy 5.08 0) (xy -5.08 -5.08) (xy -5.08 5.08)
|
||||
)
|
||||
(stroke
|
||||
(width 0.254)
|
||||
(type default)
|
||||
)
|
||||
(fill
|
||||
(type background)
|
||||
)
|
||||
)
|
||||
(pin input line
|
||||
(at -7.62 2.54 0)
|
||||
(length 2.54)
|
||||
(name "+"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "3"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin input line
|
||||
(at -7.62 -2.54 0)
|
||||
(length 2.54)
|
||||
(name "-"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "2"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin output line
|
||||
(at 7.62 0 180)
|
||||
(length 2.54)
|
||||
(name "~"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "1"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "TL072_2_1"
|
||||
(polyline
|
||||
(pts
|
||||
(xy -5.08 5.08) (xy 5.08 0) (xy -5.08 -5.08) (xy -5.08 5.08)
|
||||
)
|
||||
(stroke
|
||||
(width 0.254)
|
||||
(type default)
|
||||
)
|
||||
(fill
|
||||
(type background)
|
||||
)
|
||||
)
|
||||
(pin input line
|
||||
(at -7.62 2.54 0)
|
||||
(length 2.54)
|
||||
(name "+"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "5"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin input line
|
||||
(at -7.62 -2.54 0)
|
||||
(length 2.54)
|
||||
(name "-"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "6"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin output line
|
||||
(at 7.62 0 180)
|
||||
(length 2.54)
|
||||
(name "~"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "7"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "TL072_3_1"
|
||||
(pin power_in line
|
||||
(at -2.54 7.62 270)
|
||||
(length 3.81)
|
||||
(name "V+"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "8"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin power_in line
|
||||
(at -2.54 -7.62 90)
|
||||
(length 3.81)
|
||||
(name "V-"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "4"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(embedded_fonts no)
|
||||
)
|
||||
)
|
||||
(text "U1A: Has a \"Component Class\" field\nU2A: Assigned a Component Class from the SCH_RULE_AREA\nU3A: No class assigned\n\nResult in netlist: U1 has two Component Class names: Class1 and Class2"
|
||||
(exclude_from_sim no)
|
||||
(at 107.442 98.298 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
(uuid "bfaf99ba-b9bc-483a-9a28-c01a662202e4")
|
||||
)
|
||||
(rule_area
|
||||
(polyline
|
||||
(pts
|
||||
(xy 104.14 45.72) (xy 139.7 45.72) (xy 139.7 80.01) (xy 104.14 80.01)
|
||||
)
|
||||
(stroke
|
||||
(width 0)
|
||||
(type dash)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
(uuid 25809b47-e826-4371-9b19-1a716050ff88)
|
||||
)
|
||||
)
|
||||
(netclass_flag ""
|
||||
(length 2.54)
|
||||
(shape round)
|
||||
(at 115.57 45.72 0)
|
||||
(fields_autoplaced yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left bottom)
|
||||
)
|
||||
(uuid "dec4e873-7ff9-4632-8b58-f929fe6629ca")
|
||||
(property "Netclass" ""
|
||||
(at -199.39 -15.24 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Component Class" "Class2"
|
||||
(at 116.2685 43.18 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
(italic yes)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol
|
||||
(lib_id "Amplifier_Operational:TL072")
|
||||
(at 74.93 62.23 0)
|
||||
(unit 1)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(dnp no)
|
||||
(fields_autoplaced yes)
|
||||
(uuid "521c74f6-a90a-4165-ba5b-74e4986fbfb5")
|
||||
(property "Reference" "U1"
|
||||
(at 74.93 52.07 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Value" "TL072"
|
||||
(at 74.93 54.61 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Footprint" "Package_SO:SO-8_5.3x6.2mm_P1.27mm"
|
||||
(at 74.93 62.23 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
|
||||
(at 74.93 62.23 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Description" "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
|
||||
(at 74.93 62.23 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Component Class" "Class1"
|
||||
(at 74.93 62.23 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(pin "3"
|
||||
(uuid "0a60a206-2dc8-4b92-a7be-126df13c85da")
|
||||
)
|
||||
(pin "2"
|
||||
(uuid "b8ab93b0-0173-432e-85ed-64d6e0b531e0")
|
||||
)
|
||||
(pin "1"
|
||||
(uuid "31022ebe-9ec7-4f79-9dd6-a320ec2cdc46")
|
||||
)
|
||||
(pin "5"
|
||||
(uuid "6e87584c-ea7d-4388-9198-d4f8e33418db")
|
||||
)
|
||||
(pin "6"
|
||||
(uuid "683f1791-0e09-4b93-863a-50f522c42231")
|
||||
)
|
||||
(pin "7"
|
||||
(uuid "3abeb01e-4937-4584-a986-3b6827ccb17b")
|
||||
)
|
||||
(pin "8"
|
||||
(uuid "153c2aa2-4642-461a-b93e-2375ef54c4f0")
|
||||
)
|
||||
(pin "4"
|
||||
(uuid "e09162f6-ff12-43f4-bcac-fffde8eda559")
|
||||
)
|
||||
(instances
|
||||
(project ""
|
||||
(path "/bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd"
|
||||
(reference "U1")
|
||||
(unit 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol
|
||||
(lib_id "Amplifier_Operational:TL072")
|
||||
(at 121.92 63.5 0)
|
||||
(unit 2)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(dnp no)
|
||||
(fields_autoplaced yes)
|
||||
(uuid "da40a256-1fbb-4db4-9c2c-275f5c1d0f3c")
|
||||
(property "Reference" "U1"
|
||||
(at 121.92 53.34 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Value" "TL072"
|
||||
(at 121.92 55.88 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Footprint" "Package_SO:SO-8_5.3x6.2mm_P1.27mm"
|
||||
(at 121.92 63.5 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
|
||||
(at 121.92 63.5 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Description" "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
|
||||
(at 121.92 63.5 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Component Class" "Class1"
|
||||
(at 121.92 63.5 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin "3"
|
||||
(uuid "0a60a206-2dc8-4b92-a7be-126df13c85da")
|
||||
)
|
||||
(pin "2"
|
||||
(uuid "b8ab93b0-0173-432e-85ed-64d6e0b531e0")
|
||||
)
|
||||
(pin "1"
|
||||
(uuid "31022ebe-9ec7-4f79-9dd6-a320ec2cdc46")
|
||||
)
|
||||
(pin "5"
|
||||
(uuid "6e87584c-ea7d-4388-9198-d4f8e33418db")
|
||||
)
|
||||
(pin "6"
|
||||
(uuid "683f1791-0e09-4b93-863a-50f522c42231")
|
||||
)
|
||||
(pin "7"
|
||||
(uuid "3abeb01e-4937-4584-a986-3b6827ccb17b")
|
||||
)
|
||||
(pin "8"
|
||||
(uuid "153c2aa2-4642-461a-b93e-2375ef54c4f0")
|
||||
)
|
||||
(pin "4"
|
||||
(uuid "e09162f6-ff12-43f4-bcac-fffde8eda559")
|
||||
)
|
||||
(instances
|
||||
(project ""
|
||||
(path "/bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd"
|
||||
(reference "U1")
|
||||
(unit 2)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol
|
||||
(lib_id "Amplifier_Operational:TL072")
|
||||
(at 176.53 66.04 0)
|
||||
(unit 3)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(dnp no)
|
||||
(fields_autoplaced yes)
|
||||
(uuid "ec280545-6554-44ce-b281-8b6027100352")
|
||||
(property "Reference" "U1"
|
||||
(at 175.26 64.77 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Value" "TL072"
|
||||
(at 175.26 67.31 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Footprint" "Package_SO:SO-8_5.3x6.2mm_P1.27mm"
|
||||
(at 176.53 66.04 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
|
||||
(at 176.53 66.04 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Description" "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
|
||||
(at 176.53 66.04 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "Component Class" "Class1"
|
||||
(at 176.53 66.04 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin "3"
|
||||
(uuid "0a60a206-2dc8-4b92-a7be-126df13c85da")
|
||||
)
|
||||
(pin "2"
|
||||
(uuid "b8ab93b0-0173-432e-85ed-64d6e0b531e0")
|
||||
)
|
||||
(pin "1"
|
||||
(uuid "31022ebe-9ec7-4f79-9dd6-a320ec2cdc46")
|
||||
)
|
||||
(pin "5"
|
||||
(uuid "6e87584c-ea7d-4388-9198-d4f8e33418db")
|
||||
)
|
||||
(pin "6"
|
||||
(uuid "683f1791-0e09-4b93-863a-50f522c42231")
|
||||
)
|
||||
(pin "7"
|
||||
(uuid "3abeb01e-4937-4584-a986-3b6827ccb17b")
|
||||
)
|
||||
(pin "8"
|
||||
(uuid "153c2aa2-4642-461a-b93e-2375ef54c4f0")
|
||||
)
|
||||
(pin "4"
|
||||
(uuid "e09162f6-ff12-43f4-bcac-fffde8eda559")
|
||||
)
|
||||
(instances
|
||||
(project ""
|
||||
(path "/bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd"
|
||||
(reference "U1")
|
||||
(unit 3)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(sheet_instances
|
||||
(path "/"
|
||||
(page "1")
|
||||
)
|
||||
)
|
||||
(embedded_fonts no)
|
||||
)
|
@ -0,0 +1,94 @@
|
||||
(export (version "E")
|
||||
(design
|
||||
(source "/component_classes/component_classes.kicad_sch")
|
||||
(date "2024-09-29T22:57:25+0100")
|
||||
(tool "Eeschema 8.99.0-2480-g2270f03d8e-dirty")
|
||||
(sheet (number "1") (name "/") (tstamps "/")
|
||||
(title_block
|
||||
(title)
|
||||
(company)
|
||||
(rev)
|
||||
(date)
|
||||
(source "component_classes.kicad_sch")
|
||||
(comment (number "1") (value ""))
|
||||
(comment (number "2") (value ""))
|
||||
(comment (number "3") (value ""))
|
||||
(comment (number "4") (value ""))
|
||||
(comment (number "5") (value ""))
|
||||
(comment (number "6") (value ""))
|
||||
(comment (number "7") (value ""))
|
||||
(comment (number "8") (value ""))
|
||||
(comment (number "9") (value "")))))
|
||||
(components
|
||||
(comp (ref "U1")
|
||||
(value "TL072")
|
||||
(footprint "Package_SO:SO-8_5.3x6.2mm_P1.27mm")
|
||||
(datasheet "http://www.ti.com/lit/ds/symlink/tl071.pdf")
|
||||
(description "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8")
|
||||
(fields
|
||||
(field (name "Component Class") "Class1")
|
||||
(field (name "Footprint") "Package_SO:SO-8_5.3x6.2mm_P1.27mm")
|
||||
(field (name "Datasheet") "http://www.ti.com/lit/ds/symlink/tl071.pdf")
|
||||
(field (name "Description") "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"))
|
||||
(libsource (lib "Amplifier_Operational") (part "TL072") (description "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"))
|
||||
(property (name "Component Class") (value "Class1"))
|
||||
(property (name "Sheetname") (value "Root"))
|
||||
(property (name "Sheetfile") (value "component_classes.kicad_sch"))
|
||||
(property (name "ki_keywords") (value "dual opamp"))
|
||||
(property (name "ki_fp_filters") (value "SOIC*3.9x4.9mm*P1.27mm* DIP*W7.62mm* TO*99* OnSemi*Micro8* TSSOP*3x3mm*P0.65mm* TSSOP*4.4x3mm*P0.65mm* MSOP*3x3mm*P0.65mm* SSOP*3.9x4.9mm*P0.635mm* LFCSP*2x2mm*P0.5mm* *SIP* SOIC*5.3x6.2mm*P1.27mm*"))
|
||||
(sheetpath (names "/") (tstamps "/"))
|
||||
(component_classes
|
||||
(class "Class1")
|
||||
(class "Class2"))
|
||||
(tstamps "ec280545-6554-44ce-b281-8b6027100352" "da40a256-1fbb-4db4-9c2c-275f5c1d0f3c" "521c74f6-a90a-4165-ba5b-74e4986fbfb5")))
|
||||
(libparts
|
||||
(libpart (lib "Amplifier_Operational") (part "TL072")
|
||||
(description "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8")
|
||||
(docs "http://www.ti.com/lit/ds/symlink/tl071.pdf")
|
||||
(footprints
|
||||
(fp "SOIC*3.9x4.9mm*P1.27mm*")
|
||||
(fp "DIP*W7.62mm*")
|
||||
(fp "TO*99*")
|
||||
(fp "OnSemi*Micro8*")
|
||||
(fp "TSSOP*3x3mm*P0.65mm*")
|
||||
(fp "TSSOP*4.4x3mm*P0.65mm*")
|
||||
(fp "MSOP*3x3mm*P0.65mm*")
|
||||
(fp "SSOP*3.9x4.9mm*P0.635mm*")
|
||||
(fp "LFCSP*2x2mm*P0.5mm*")
|
||||
(fp "*SIP*")
|
||||
(fp "SOIC*5.3x6.2mm*P1.27mm*"))
|
||||
(fields
|
||||
(field (name "Reference") "U")
|
||||
(field (name "Value") "TL072")
|
||||
(field (name "Footprint"))
|
||||
(field (name "Datasheet") "http://www.ti.com/lit/ds/symlink/tl071.pdf")
|
||||
(field (name "Description") "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"))
|
||||
(pins
|
||||
(pin (num "1") (name "") (type "output"))
|
||||
(pin (num "2") (name "-") (type "input"))
|
||||
(pin (num "3") (name "+") (type "input"))
|
||||
(pin (num "4") (name "V-") (type "power_in"))
|
||||
(pin (num "5") (name "+") (type "input"))
|
||||
(pin (num "6") (name "-") (type "input"))
|
||||
(pin (num "7") (name "") (type "output"))
|
||||
(pin (num "8") (name "V+") (type "power_in")))))
|
||||
(libraries
|
||||
(library (logical "Amplifier_Operational")
|
||||
(uri "/kicad/KiCad.app/Contents/SharedSupport/symbols//Amplifier_Operational.kicad_sym")))
|
||||
(nets
|
||||
(net (code "1") (name "unconnected-(U1-Pad1)")
|
||||
(node (ref "U1") (pin "1") (pintype "output")))
|
||||
(net (code "2") (name "unconnected-(U1-Pad7)")
|
||||
(node (ref "U1") (pin "7") (pintype "output")))
|
||||
(net (code "3") (name "unconnected-(U1A-+-Pad3)")
|
||||
(node (ref "U1") (pin "3") (pinfunction "+") (pintype "input")))
|
||||
(net (code "4") (name "unconnected-(U1A---Pad2)")
|
||||
(node (ref "U1") (pin "2") (pinfunction "-") (pintype "input")))
|
||||
(net (code "5") (name "unconnected-(U1B-+-Pad5)")
|
||||
(node (ref "U1") (pin "5") (pinfunction "+") (pintype "input")))
|
||||
(net (code "6") (name "unconnected-(U1B---Pad6)")
|
||||
(node (ref "U1") (pin "6") (pinfunction "-") (pintype "input")))
|
||||
(net (code "7") (name "unconnected-(U1C-V+-Pad8)")
|
||||
(node (ref "U1") (pin "8") (pinfunction "V+") (pintype "power_in")))
|
||||
(net (code "8") (name "unconnected-(U1C-V--Pad4)")
|
||||
(node (ref "U1") (pin "4") (pinfunction "V-") (pintype "power_in")))))
|
@ -87,6 +87,10 @@ public:
|
||||
BOOST_REQUIRE_EQUAL( goldenNet.GetPinName(), testNet.GetPinName() );
|
||||
BOOST_REQUIRE_EQUAL( goldenNet.GetPinType(), testNet.GetPinType() );
|
||||
}
|
||||
|
||||
// And the the resolved component class is the same
|
||||
BOOST_REQUIRE( goldenComp->GetComponentClassNames()
|
||||
== refComp->GetComponentClassNames() );
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -209,5 +213,10 @@ BOOST_AUTO_TEST_CASE( Issue16439 )
|
||||
TestNetlist( "issue16439" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( ComponentClasses )
|
||||
{
|
||||
TestNetlist( "component_classes" );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
x
Reference in New Issue
Block a user