36#include <fmt/ranges.h> 
   46    m_exportPath = wxFileName( aOutFileName ).GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR )
 
   47                   + wxString( 
"devices" );
 
   52            wxString msg = wxString::Format( 
_( 
"Failed to create directory 'devices' ." ) );
 
   59    if( ( 
m_f = wxFopen( aOutFileName, wxT( 
"wt" ) ) ) == 
nullptr )
 
   61        wxString msg = wxString::Format( 
_( 
"Failed to create file '%s'." ), aOutFileName );
 
   68        fmt::print( 
m_f, 
"(NETLIST)\n" );
 
   88        fmt::print( 
m_f, 
"$END\n" );
 
 
  109    wxString refText1 = aItem1.first->GetRef( &aItem1.second );
 
  110    wxString refText2 = aItem2.first->GetRef( &aItem2.second );
 
  112    if( refText1 == refText2 )
 
  114        return aItem1.second.PathHumanReadable() < aItem2.second.PathHumanReadable();
 
 
  122                                                 const wxString& aRefText2 )
 
  129    return aRefText1 < aRefText2;
 
 
  153                                        b->GetRef( &sheet, 
false ), 
true ) < 0 );
 
  156        std::set<
SCH_SYMBOL*, 
decltype( cmp )> ordered_symbols( cmp );
 
  157        std::multiset<
SCH_SYMBOL*, 
decltype( cmp )> extra_units( cmp );
 
  162            auto        test = ordered_symbols.insert( symbol );
 
  166                if( ( *( 
test.first ) )->m_Uuid > symbol->
m_Uuid )
 
  168                    extra_units.insert( *( 
test.first ) );
 
  169                    ordered_symbols.erase( 
test.first );
 
  170                    ordered_symbols.insert( symbol );
 
  174                    extra_units.insert( symbol );
 
  179        for( 
EDA_ITEM* item : ordered_symbols )
 
  190                                        wxString>( sheet.PathHumanReadable(),
 
  191                                                   symbol->
GetRef( &sheet ) ) );
 
  199        NET_RECORD( 
const wxString& aName ) :
 
  204        std::vector<NET_NODE> m_Nodes;
 
  207    std::vector<NET_RECORD*> nets;
 
  209    for( 
const auto& it : 
m_schematic->ConnectionGraph()->GetNetMap() )
 
  211        wxString                                 net_name  = it.first.Name;
 
  212        const std::vector<CONNECTION_SUBGRAPH*>& subgraphs = it.second;
 
  213        NET_RECORD*                              net_record = 
nullptr;
 
  215        if( subgraphs.empty() )
 
  218        nets.emplace_back( 
new NET_RECORD( net_name ) );
 
  219        net_record = nets.back();
 
  223            bool nc = subgraph->GetNoConnect() &&
 
  227            for( 
SCH_ITEM* item : subgraph->GetItems() )
 
  237                    net_record->m_Nodes.emplace_back( 
pin, sheet, nc );
 
  244    std::sort( nets.begin(), nets.end(),
 
  245               []( 
const NET_RECORD* a, 
const NET_RECORD*b )
 
  247                   return StrNumCmp( a->m_Name, b->m_Name ) < 0;
 
  250    for( NET_RECORD* net_record : nets )
 
  253        std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
 
  256                       wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
 
  257                       wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
 
  260                           return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
 
  271                    wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
 
  272                    wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
 
  274                    return refA == refB && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
 
  277        for( 
const NET_NODE& netNode : net_record->m_Nodes )
 
  282            if( refText[0] == wxChar( 
'#' ) )
 
  287            m_netNameNodes.insert( std::pair<wxString, NET_NODE>( net_record->m_Name, netNode ) );
 
  291    for( NET_RECORD* record : nets )
 
 
  299    wxString deviceFileCreatingError = wxString( 
"" );
 
  312            if( it->first->GetValue( 
false, &it->second, 
false )
 
  313                != first_ele.first->GetValue( 
false, &first_ele.second, 
false ) )
 
  318            if( it->first->GetFootprintFieldText( 
false, &it->second, 
false )
 
  319                != first_ele.first->GetFootprintFieldText( 
false, &first_ele.second, 
false ) )
 
  324            wxString ref1 = it->first->GetRef( &it->second );
 
  325            wxString ref2 = first_ele.first->GetRef( &first_ele.second );
 
  342    struct COMP_PACKAGE_STRUCT
 
  345        wxString                                            m_tolerance;
 
  346        std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> m_symbolSheetpaths;
 
  349    COMP_PACKAGE_STRUCT                     compPackageStruct;
 
  350    std::map<wxString, COMP_PACKAGE_STRUCT> compPackageMap;
 
  352    for( 
int groupIndex = 1; groupIndex < groupCount; groupIndex++ )
 
  355        auto beginIter = pairIter.first;
 
  356        auto endIter = pairIter.second;
 
  358        SCH_SYMBOL* sym = ( beginIter->second ).first;
 
  361        wxString valueText = sym->
GetValue( 
false, &sheetPath, 
false );
 
  363        wxString deviceType = valueText + wxString(
"_") + footprintText;
 
  365        while( deviceType.GetChar(deviceType.Length()-1) == 
'_' )
 
  367            deviceType.RemoveLast();
 
  372        wxArrayString fieldArray;
 
  373        fieldArray.Add( 
"Spice_Model" );
 
  374        fieldArray.Add( 
"VALUE" );
 
  379        fieldArray.Add( 
"TOLERANCE" );
 
  380        fieldArray.Add( 
"TOL" );
 
  383        std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths;
 
  385        for( 
auto iter = beginIter; iter != endIter; iter++ )
 
  387            symbolSheetpaths.push_back( std::pair<
SCH_SYMBOL*,
 
  389                                                         iter->second.second ) );
 
  392        std::stable_sort( symbolSheetpaths.begin(), symbolSheetpaths.end(),
 
  395        compPackageStruct.m_value = value;
 
  396        compPackageStruct.m_tolerance = tol;
 
  397        compPackageStruct.m_symbolSheetpaths = symbolSheetpaths;
 
  398        compPackageMap.insert( std::pair( deviceType, compPackageStruct ) );
 
  402        wxString deviceFileName = wxFileName( 
m_exportPath, deviceType,
 
  403                                              wxString( 
"txt" ) ).GetFullPath();
 
  405        if( ( d = wxFopen( deviceFileName, wxT( 
"wt" ) ) ) == 
nullptr )
 
  408            msg.Printf( 
_( 
"Failed to create file '%s'.\n" ), deviceFileName );
 
  409            deviceFileCreatingError += msg;
 
  413        footprintText = footprintText.AfterLast( 
':' );
 
  415        wxArrayString footprintAlt;
 
  418        for( 
const wxString& fp : footprintArray )
 
  420            if( ( fp.Find( 
'*' ) != wxNOT_FOUND ) || ( fp.Find( 
'?' ) != wxNOT_FOUND ) )
 
  425            footprintAlt.Add( fp.AfterLast( 
':' ) );
 
  428        if( footprintText.IsEmpty() )
 
  430            if( !footprintAlt.IsEmpty() )
 
  432                footprintText = footprintAlt[0];
 
  433                footprintAlt.RemoveAt( 0 );
 
  437                footprintText = deviceType;
 
  442        fmt::print( d, 
"CLASS IC\n" );
 
  456        for( 
int ii = 0; ii < (int) pinList.size() - 1; ii++ )
 
  458            if( pinList[ii]->GetNumber() == pinList[ii + 1]->GetNumber() )
 
  461                pinList.erase( pinList.begin() + ii + 1 );
 
  466        unsigned int pinCount = pinList.size();
 
  467        fmt::print( d, 
"PINCOUNT {}\n", pinCount );
 
  474        if( !value.IsEmpty() )
 
  476            fmt::print( d, 
"PACKAGEPROP VALUE {}\n", 
TO_UTF8( value ) );
 
  481            fmt::print( d, 
"PACKAGEPROP TOL {}\n", 
TO_UTF8( tol ) );
 
  484        if( !footprintAlt.IsEmpty() )
 
  486            fmt::print( d, 
"PACKAGEPROP ALT_SYMBOLS '({})'\n", fmt::join( footprintAlt, 
"," ) );
 
  489        wxArrayString propArray;
 
  490        propArray.Add( 
"PART_NUMBER" );
 
  491        propArray.Add( 
"mpn" );
 
  492        propArray.Add( 
"mfr_pn" );
 
  497            fmt::print( d, 
"PACKAGEPROP {} {}\n", 
TO_UTF8( propArray[0] ), 
TO_UTF8( data ) );
 
  501        propArray.Add( 
"HEIGHT" );
 
  506            fmt::print( d, 
"PACKAGEPROP {} {}\n", 
TO_UTF8( propArray[0] ), 
TO_UTF8( data ) );
 
  509        fmt::print( d, 
"END\n" );
 
  514    fmt::print( 
m_f, 
"$PACKAGES\n" );
 
  516    for( 
auto iter = compPackageMap.begin(); iter != compPackageMap.end(); iter++ )
 
  518        wxString deviceType = iter->first;
 
  519        wxString value = iter->second.m_value;
 
  520        wxString tolerance = iter->second.m_tolerance;
 
  522        if( value.IsEmpty() && tolerance.IsEmpty() )
 
  524            fmt::print( 
m_f, 
"! '{}' ; ", 
TO_UTF8( deviceType ) );
 
  526        else if( tolerance.IsEmpty() )
 
  532            fmt::print( 
m_f, 
"! '{}' ! '{}' ! {} ; ", 
TO_UTF8( deviceType ), 
TO_UTF8( value ),
 
  536        std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths =
 
  537                iter->second.m_symbolSheetpaths;
 
  539        std::vector<wxString> refTexts;
 
  540        for( 
const auto& [ sym, sheetPath ] : symbolSheetpaths)
 
  541            refTexts.push_back( sym->GetRef( &sheetPath ) );
 
  543        fmt::print( 
m_f, 
"{}", fmt::join( refTexts, 
",\n\t" ) );
 
  545        fmt::print( 
m_f, 
"\n" );
 
  548    if( !deviceFileCreatingError.IsEmpty() )
 
 
  555    if( aString.IsEmpty() )
 
  556        return wxEmptyString;
 
  558    aString.Replace( 
"\u03BC", 
"u" );
 
  560    std::regex reg( 
"[!']|[^ -~]" );
 
  561    wxString   processedString = wxString( std::regex_replace( std::string( aString ), reg, 
"?" ) );
 
  563    std::regex search_reg( 
"[^a-zA-Z0-9_/]" );
 
  565    if( std::regex_search( std::string( processedString ), search_reg ) )
 
  566        return wxString( 
"'" ) + processedString + wxString( 
"'" );
 
  568    return processedString;
 
 
  574    wxString   pinName4Telesis = aPin.
GetName() + wxString( 
"__" ) + aPin.
GetNumber();
 
  575    std::regex reg( 
"[^A-Za-z0-9_+?/-]" );
 
  576    return wxString( std::regex_replace( std::string( pinName4Telesis ), reg, 
"?" ) );
 
 
  583    std::list<wxString> pinNameList;
 
  587    for( 
auto pin : aPinList )
 
  590    wxString out_str = 
"";
 
  593    out_str.Printf( wxT( 
"PINORDER %s " ), 
TO_UTF8( aName ) );
 
  595    for( 
const wxString& pinName : pinNameList )
 
  597        str.Printf( 
",\n\t%s", 
TO_UTF8( pinName ) );
 
  600    out_str += wxString( 
"\n" );
 
  602    str.Printf( wxT( 
"FUNCTION %s %s " ), 
TO_UTF8( aName ), 
TO_UTF8( aName ) );
 
  605    for( 
auto pin : aPinList )
 
  607        str.Printf( 
",\n\t%s", 
TO_UTF8( 
pin->GetNumber() ) );
 
  611    out_str += wxString( 
"\n" );
 
 
  622    for( 
auto iter = pairIter.first; iter != pairIter.second; ++iter )
 
  627        for( 
const wxString& field : aFieldArray )
 
  631                wxString fieldText = fld->GetShownText( &sheetPath, 
true );
 
  633                if( !fieldText.IsEmpty() )
 
  644    for( 
auto iter = pairIter.first; iter != pairIter.second; ++iter )
 
  648        for( 
const wxString& field : aFieldArray )
 
  652                wxString fieldText = fld->GetShownText( 
false, 0 );
 
  654                if( !fieldText.IsEmpty() )
 
  665    return wxEmptyString;
 
 
  672    std::regex reg( 
"[^a-z0-9_-]" );
 
  673    return wxString( std::regex_replace( std::string( aString ), reg, 
"_" ) );
 
 
  679    fmt::print( 
m_f, 
"$A_PROPERTIES\n" );
 
  684        wxString                                    sheetPathText = iter->first;
 
  688        std::vector<wxString> refTexts;
 
  692        for( iter = pairIter.first; iter != pairIter.second; ++iter )
 
  694            wxString refText = iter->second;
 
  695            refTexts.push_back( refText );
 
  700        std::stable_sort( refTexts.begin(), refTexts.end(),
 
  703        fmt::print( 
m_f, 
"{}", fmt::join( refTexts, 
",\n\t" ) );
 
  705        fmt::print( 
m_f, 
"\n" );
 
 
  712    fmt::print( 
m_f, 
"$NETS\n" );
 
  716        std::multimap<wxString, NET_NODE>::iterator iter = 
m_netNameNodes.begin();
 
  717        std::vector<NET_NODE>                       netNodes;
 
  719        wxString netName = iter->first;
 
  725        for( iter = pairIter.first; iter != pairIter.second; ++iter )
 
  728            netNodes.push_back( netNode );
 
  733        std::stable_sort( netNodes.begin(), netNodes.end() );
 
  735        std::vector<wxString> nets;
 
  736        for( 
const NET_NODE& netNode : netNodes )
 
  738            wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
 
  739            wxString pinText = netNode.m_Pin->GetShownNumber();
 
  740            nets.push_back( refText + wxString( 
"." ) + pinText );
 
  743        fmt::print( 
m_f, 
"{}", fmt::join( nets, 
",\n\t" ) );
 
  745        fmt::print( 
m_f, 
"\n" );
 
 
  752    while( ( aString.GetChar( aString.Length() - 1 ) >= 
'0' )
 
  753           && ( aString.GetChar( aString.Length() - 1 ) <= 
'9' ) )
 
  755        aString.RemoveLast();
 
 
  766    while( ( aString.GetChar( aString.Length() - 1 ) >= 
'0' )
 
  767           && ( aString.GetChar( aString.Length() - 1 ) <= 
'9' ) )
 
  769        numString.insert( 0, aString.GetChar( aString.Length() - 1 ) );
 
  770        aString.RemoveLast();
 
  776    numString.ToULong( &val );
 
  777    return (
unsigned int) val;
 
 
A subgraph is a set of items that are electrically connected on a single sheet.
 
A base class for most all the KiCad significant classes used in schematics and boards.
 
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
 
wxArrayString GetFPFilters() const
 
std::vector< SCH_PIN * > GetPins() const override
 
wxString formatDevice(wxString aString)
Convert a string into one safe for a Telesis device name.
 
wxString m_exportPath
Directory to store device files.
 
static unsigned int extractTailNumber(wxString aString)
Extract the str's tailing number.
 
FILE * m_f
File pointer for netlist file writing operation.
 
static wxString removeTailDigits(wxString aString)
Remove the str's tailing digits.
 
void toAllegroPackageProperties()
Write $A_PROPERTIES section.
 
bool WriteNetlist(const wxString &aOutFileName, unsigned aNetlistOptions, REPORTER &aReporter) override
Write netlist to aOutFileName.
 
std::list< std::pair< SCH_SYMBOL *, SCH_SHEET_PATH > > m_orderedSymbolsSheetpath
Store the ordered symbols with sheetpath.
 
static bool CompareSymbolSheetpath(const std::pair< SCH_SYMBOL *, SCH_SHEET_PATH > &aItem1, const std::pair< SCH_SYMBOL *, SCH_SHEET_PATH > &aItem2)
Compare two std::pair<SCH_SYMBOL*, SCH_SHEET_PATH> variables.
 
wxString formatText(wxString aString)
Convert a string into Telesis-safe format.
 
std::multimap< wxString, wxString > m_packageProperties
 
wxString formatFunction(wxString aName, std::vector< SCH_PIN * > aPinList)
Generate the definition of a function in Telesis format, which consists of multiple declarations (PIN...
 
static bool CompareLibPin(const SCH_PIN *aPin1, const SCH_PIN *aPin2)
Compare two SCH_PIN* variables.
 
wxString formatPin(const SCH_PIN &aPin)
Generate a Telesis-compatible pin name from a pin node.
 
static bool CompareSymbolRef(const wxString &aRefText1, const wxString &aRefText2)
Compare two wxString variables.
 
void extractComponentsInfo()
 
wxString getGroupField(int aGroupIndex, const wxArrayString &aFieldArray, bool aSanitize=true)
Look up a field for a component group, which may have mismatched case, or the component group may not...
 
void toAllegroPackages()
Write the $PACKAGES section.
 
std::multimap< wxString, NET_NODE > m_netNameNodes
Store the NET_NODE with the net name.
 
std::multimap< int, std::pair< SCH_SYMBOL *, SCH_SHEET_PATH > > m_componentGroups
Store the component group.
 
void toAllegroNets()
Write the $NETS section.
 
SCHEMATIC * m_schematic
The schematic we're generating a netlist for.
 
SCH_SYMBOL * findNextSymbol(EDA_ITEM *aItem, const SCH_SHEET_PATH &aSheetPath)
Check if the given symbol should be processed for netlisting.
 
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names
 
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.
 
A pure virtual class used to derive REPORTER objects from.
 
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
 
Base class for any item which can be embedded within the SCHEMATIC container class,...
 
const SYMBOL * GetParentSymbol() const
 
wxString GetShownNumber() const
 
const wxString & GetName() const
 
const wxString & GetNumber() const
 
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
 
const SCH_SHEET * GetSheet(unsigned aIndex) const
 
const wxString GetValue(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const override
 
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
Search for a SCH_FIELD with aFieldName.
 
const wxString GetFootprintFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const
 
std::vector< SCH_PIN * > GetLibPins() const
Populate a vector with all the pins from the library object that match the current unit and bodyStyle...
 
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
 
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
 
A base class for LIB_SYMBOL and SCH_SYMBOL.
 
virtual const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const =0
 
bool GetExcludedFromBoard() const override
 
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
 
This file is part of the common library.
 
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
 
Collection of utility functions for component reference designators (refdes)
 
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
 
wxString GetISO8601CurrentDateTime()
 
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.