55    std::string 
name = aProposedName;
 
   59        name = fmt::format( 
"{}#{}", aProposedName, ii++ );
 
 
   69    std::vector<EMBEDDED_FILES*> embeddedFilesStack;
 
   71    m_libMgr.SetFilesStack( std::move( embeddedFilesStack ) );
 
 
   79    return DoWriteNetlist( wxEmptyString, aNetlistOptions, formatter, aReporter );
 
 
  112    aFormatter.
Print( 0, 
".title KiCad schematic\n" );
 
 
  118    aFormatter.
Print( 0, 
".end\n" );
 
 
  125    std::set<std::string> refNames; 
 
  137    cacheDir.AppendDir( wxT( 
"ibis" ) );
 
  139    if( !cacheDir.DirExists() )
 
  141        cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
 
  143        if( !cacheDir.DirExists() )
 
  145            wxLogTrace( wxT( 
"IBIS_CACHE:" ),
 
  146                        wxT( 
"%s:%s:%d\n * failed to create ibis cache directory '%s'" ),
 
  147                        __FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
 
  154    wxString dirName = cacheDir.GetFullPath();
 
  156    if( !dir.Open( dirName ) )
 
  160    wxArrayString fileList;
 
  161    wxString      fileSpec = wxT( 
"*.cache" );
 
  163    thisFile.SetPath( dirName ); 
 
  165    size_t numFilesFound = wxDir::GetAllFiles( dirName, &fileList, fileSpec );
 
  167    for( 
size_t ii = 0; ii < numFilesFound; ii++ )
 
  170        thisFile.SetFullName( fileList[ii] );
 
  171        wxRemoveFile( thisFile.GetFullPath() );
 
  186                std::vector<PIN_INFO> pins = 
CreatePinList( symbol, sheet, 
true );
 
  193                        spiceItem.
fields.back().SetText( symbol->
GetRef( &sheet ) );
 
  195                        spiceItem.
fields.back().SetText( field.GetShownText( &sheet, 
false ) );
 
  198                readRefName( sheet, *symbol, spiceItem, refNames );
 
  199                readModel( sheet, *symbol, spiceItem, aReporter );
 
  205                m_items.push_back( std::move( spiceItem ) );
 
 
  221    std::unique_ptr<MARKUP::NODE> root = markupParser.
Parse();
 
  223    std::function<void( 
const std::unique_ptr<MARKUP::NODE>&)> convertMarkup =
 
  224            [&]( 
const std::unique_ptr<MARKUP::NODE>& aNode )
 
  228                    if( !aNode->is_root() )
 
  230                        if( aNode->isOverbar() )
 
  235                        else if( aNode->isSubscript() || aNode->isSuperscript() )
 
  240                        if( aNode->has_content() )
 
  241                            *aNetName += aNode->string();
 
  244                    for( 
const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
 
  245                        convertMarkup( child );
 
  249    *aNetName = wxEmptyString;
 
  250    convertMarkup( root );
 
  253    aNetName->Replace( 
'%', 
'_' );
 
  254    aNetName->Replace( 
'(', 
'_' );
 
  255    aNetName->Replace( 
')', 
'_' );
 
  256    aNetName->Replace( 
',', 
'_' );
 
  257    aNetName->Replace( 
'[', 
'_' );
 
  258    aNetName->Replace( 
']', 
'_' );
 
  259    aNetName->Replace( 
'<', 
'_' );
 
  260    aNetName->Replace( 
'>', 
'_' );
 
  261    aNetName->Replace( 
'~', 
'_' );
 
  262    aNetName->Replace( 
' ', 
'_' );
 
  266    if( aNetName->StartsWith( wxS( 
"//" ) ) )
 
  267        aNetName->Replace( wxS( 
"//" ), wxS( 
"/root/" ), 
false  );
 
 
  274        return item->model->SpiceGenerator().ItemName( *item );
 
  276    return wxEmptyString;
 
 
  282    const std::string            refName = aRefName.ToStdString();
 
  283    const std::list<SPICE_ITEM>& spiceItems = 
GetItems();
 
  285    auto it = std::find_if( spiceItems.begin(), spiceItems.end(),
 
  288                                return item.refName == refName;
 
  291    if( it != spiceItems.end() )
 
 
  306        for( 
SCH_ITEM* item : sheet.LastScreen()->Items() )
 
  308            if( item->ResolveExcludedFromSim() )
 
  312                text = 
static_cast<SCH_TEXT*
>( item )->GetShownText( &sheet, 
false );
 
  314                text = 
static_cast<SCH_TEXTBOX*
>( item )->GetShownText( 
nullptr, &sheet, 
false );
 
  319            wxStringTokenizer tokenizer( 
text, 
"\r\n", wxTOKEN_STRTOK );
 
  320            bool              foundDirective = 
false;
 
  323                    []( 
const wxString& line, 
const wxString& dir )
 
  325                        return line == dir || line.StartsWith( dir + wxS( 
" " ) );
 
  328            while( tokenizer.HasMoreTokens() )
 
  330                wxString line = tokenizer.GetNextToken().Upper();
 
  332                if( line.StartsWith( wxT( 
"." ) ) )
 
  334                    if(    isDirective( line, wxS( 
".AC" ) )
 
  335                        || isDirective( line, wxS( 
".CONTROL" ) )
 
  336                        || isDirective( line, wxS( 
".CSPARAM" ) )
 
  337                        || isDirective( line, wxS( 
".DISTO" ) )
 
  338                        || isDirective( line, wxS( 
".DC" ) )
 
  339                        || isDirective( line, wxS( 
".ELSE" ) )
 
  340                        || isDirective( line, wxS( 
".ELSEIF" ) )
 
  341                        || isDirective( line, wxS( 
".END" ) )
 
  342                        || isDirective( line, wxS( 
".ENDC" ) )
 
  343                        || isDirective( line, wxS( 
".ENDIF" ) )
 
  344                        || isDirective( line, wxS( 
".ENDS" ) )
 
  345                        || isDirective( line, wxS( 
".FOUR" ) )
 
  346                        || isDirective( line, wxS( 
".FUNC" ) )
 
  347                        || isDirective( line, wxS( 
".GLOBAL" ) )
 
  348                        || isDirective( line, wxS( 
".IC" ) )
 
  349                        || isDirective( line, wxS( 
".IF" ) )
 
  350                        || isDirective( line, wxS( 
".INCLUDE" ) )
 
  351                        || isDirective( line, wxS( 
".LIB" ) )
 
  352                        || isDirective( line, wxS( 
".MEAS" ) )
 
  353                        || isDirective( line, wxS( 
".MODEL" ) )
 
  354                        || isDirective( line, wxS( 
".NODESET" ) )
 
  355                        || isDirective( line, wxS( 
".NOISE" ) )
 
  356                        || isDirective( line, wxS( 
".OP" ) )
 
  357                        || isDirective( line, wxS( 
".OPTIONS" ) )
 
  358                        || isDirective( line, wxS( 
".PARAM" ) )
 
  359                        || isDirective( line, wxS( 
".PLOT" ) )
 
  360                        || isDirective( line, wxS( 
".PRINT" ) )
 
  361                        || isDirective( line, wxS( 
".PROBE" ) )
 
  362                        || isDirective( line, wxS( 
".PZ" ) )
 
  363                        || isDirective( line, wxS( 
".SAVE" ) )
 
  364                        || isDirective( line, wxS( 
".SENS" ) )
 
  365                        || isDirective( line, wxS( 
".SP" ) )
 
  366                        || isDirective( line, wxS( 
".SUBCKT" ) )
 
  367                        || isDirective( line, wxS( 
".TEMP" ) )
 
  368                        || isDirective( line, wxS( 
".TF" ) )
 
  369                        || isDirective( line, wxS( 
".TITLE" ) )
 
  370                        || isDirective( line, wxS( 
".TRAN" ) )
 
  371                        || isDirective( line, wxS( 
".WIDTH" ) ) )
 
  373                        foundDirective = 
true;
 
  377                else if( line.StartsWith( wxT( 
"K" ) ) )
 
  380                    wxStringTokenizer line_t( line, 
" \t", wxTOKEN_STRTOK );
 
  383                    if( !line_t.HasMoreTokens() || !line_t.GetNextToken().StartsWith( wxT( 
"K" ) ) )
 
  387                    if( !line_t.HasMoreTokens() || !line_t.GetNextToken().StartsWith( wxT( 
"L" ) ) )
 
  391                    if( !line_t.HasMoreTokens() || !line_t.GetNextToken().StartsWith( wxT( 
"L" ) ) )
 
  396                    if( line_t.HasMoreTokens() )
 
  398                        foundDirective = 
true;
 
 
  412                                          SPICE_ITEM& aItem, std::set<std::string>& aRefNames )
 
  416    if( !aRefNames.insert( aItem.
refName ).second )
 
  417        wxASSERT( wxT( 
"Duplicate refdes encountered; what happened to ReadyToNetlist()?" ) );
 
 
  436        int      libParamIndex = 
static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB );
 
  437        wxString 
path = rawSpiceModel->GetParam( libParamIndex ).value;
 
  439        if( !
path.IsEmpty() )
 
  446        cacheFn.AppendDir( wxT( 
"ibis" ) );
 
  447        cacheFn.SetFullName( aSymbol.
GetRef( &aSheet ) + wxT( 
".cache" ) );
 
  449        wxFile cacheFile( cacheFn.GetFullPath(), wxFile::write );
 
  451        if( !cacheFile.IsOpened() )
 
  453            wxLogError( 
_( 
"Could not open file '%s' to write IBIS model" ),
 
  454                        cacheFn.GetFullPath() );
 
  459        wxString    cacheFilepath = cacheFn.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
 
  461                                                           cacheFilepath, aReporter );
 
  463        cacheFile.Write( wxString( modelData ) );
 
 
  470                                             const std::vector<PIN_INFO>& aPins  )
 
 
  478                                              const std::vector<PIN_INFO>& aPins, 
int& aNcCounter )
 
  480    for( 
const PIN_INFO& pinInfo : aPins )
 
  484        aItem.
pinNetNames.push_back( netName.ToStdString() );
 
 
  491                                             std::vector<std::string>& aModifiers )
 
  498    tao::pegtl::string_input<>                    in( input, 
"Sim.NodesFormat field" );
 
  499    std::unique_ptr<tao::pegtl::parse_tree::node> root;
 
  500    std::string                                   singleNodeModifier;
 
  508        for( 
const auto& node : root->children )
 
  513                aModifiers.back().append( node->string() );
 
  517                singleNodeModifier.append( node->string() );
 
  522                aModifiers.push_back( singleNodeModifier );
 
  523                singleNodeModifier.erase( singleNodeModifier.begin(), singleNodeModifier.end() );
 
  527    catch( 
const tao::pegtl::parse_error& e )
 
  529        THROW_IO_ERROR( wxString::Format( 
_( 
"Error in parsing model '%s', error: '%s'" ),
 
 
  535    std::vector<std::string> xspicePattern;
 
  538    if( xspicePattern.empty() )
 
  541    if( xspicePattern.size() != aItem.
pinNetNames.size() )
 
  543        THROW_IO_ERROR( wxString::Format( 
_( 
"Error in parsing model '%s', wrong number of nodes " 
  544                                             "'?' in Sim.NodesFormat compared to connections" ),
 
  551    for( std::string& pattern : xspicePattern )
 
  554        const std::string netName = 
" " + *itNetNames + 
" ";
 
  555        pattern.replace( pattern.find( 
"?" ), 1, netName );
 
  556        *itNetNames = pattern;
 
 
  562                                           const wxString& aPath )
 
  568    expandedPath.Replace( 
'\\', 
'/' );
 
  577        if( fullPath.IsEmpty() )
 
  579            wxLogError( 
_( 
"Could not find library file '%s'" ), expandedPath );
 
  580            fullPath = expandedPath;
 
  582        else if( wxFileName::GetPathSeparator() == 
'\\' )
 
  585            fullPath.Replace( 
'\\', 
'/' );
 
  590        fullPath = expandedPath;
 
  593    aFormatter.
Print( 0, 
".include \"%s\"\n", 
TO_UTF8( fullPath ) );
 
 
  614        if( !item.model->IsEnabled() )
 
  617        aFormatter.
Print( 0, 
"%s", item.model->SpiceGenerator().ModelLine( item ).c_str() );
 
 
  626        if( !item.model->IsEnabled() )
 
  629        aFormatter.
Print( 0, 
"%s", item.model->SpiceGenerator().ItemLine( item ).c_str() );
 
 
  638        aFormatter.
Print( 0, 
".save all\n" );
 
  641        aFormatter.
Print( 0, 
".probe alli\n" );
 
  649            std::string itemName = item.model->SpiceGenerator().ItemName( item );
 
  651            if( ( item.model->GetPinCount() >= 2 ) && ( itemName.size() > 0 )
 
  652                && ( itemName.c_str()[0] != 
'A' ) )
 
  654                aFormatter.
Print( 0, 
".probe p(%s)\n", itemName.c_str() );
 
  660            []( 
const wxString& candidate, 
const wxString& dir )
 
  662                return candidate == dir || candidate.StartsWith( dir + wxS( 
" " ) );
 
  667        bool simCommand = 
false;
 
  669        if( directive.StartsWith( 
"." ) )
 
  671            wxString candidate = directive.Upper();
 
  673            simCommand = ( isSimCommand( candidate, wxS( 
".AC" ) )
 
  674                        || isSimCommand( candidate, wxS( 
".DC" ) )
 
  675                        || isSimCommand( candidate, wxS( 
".TRAN" ) )
 
  676                        || isSimCommand( candidate, wxS( 
".OP" ) )
 
  677                        || isSimCommand( candidate, wxS( 
".DISTO" ) )
 
  678                        || isSimCommand( candidate, wxS( 
".NOISE" ) )
 
  679                        || isSimCommand( candidate, wxS( 
".PZ" ) )
 
  680                        || isSimCommand( candidate, wxS( 
".SENS" ) )
 
  681                        || isSimCommand( candidate, wxS( 
".TF" ) ) );
 
  685            aFormatter.
Print( 0, 
"%s\n", 
UTF8( directive ).c_str() );
 
 
  691                                                         int& aNcCounter )
 const 
  697    if( netName.IsEmpty() )
 
  698        netName.Printf( wxS( 
"NC-%d" ), aNcCounter++ );
 
 
  713    std::erase_if( sheets,
 
 
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
 
virtual const wxString What() const
A composite of Problem() and Where()
 
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
 
std::unique_ptr< NODE > Parse()
 
std::unordered_set< std::string > m_names
 
std::string Generate(const std::string &aProposedName)
 
SCHEMATIC * m_schematic
The schematic we're generating a netlist for.
 
std::vector< PIN_INFO > CreatePinList(SCH_SYMBOL *aSymbol, const SCH_SHEET_PATH &aSheetPath, bool aKeepUnconnectedPins)
Find a symbol from the DrawList and builds its pin list.
 
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
 
NETLIST_EXPORTER_BASE(SCHEMATIC *aSchematic)
 
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.
 
void readPinNetNames(SCH_SYMBOL &aSymbol, SPICE_ITEM &aItem, const std::vector< PIN_INFO > &aPins, int &aNcCounter)
 
void writeModels(OUTPUTFORMATTER &aFormatter)
 
void writeIncludes(OUTPUTFORMATTER &aFormatter, unsigned aNetlistOptions)
 
std::list< SPICE_ITEM > m_items
 
void getNodePattern(SPICE_ITEM &aItem, std::vector< std::string > &aModifiers)
 
static void ConvertToSpiceMarkup(wxString *aNetName)
Remove formatting wrappers and replace illegal spice net name characters with underscores.
 
void ReadDirectives(unsigned aNetlistOptions)
 
@ OPTION_SAVE_ALL_CURRENTS
 
@ OPTION_SAVE_ALL_VOLTAGES
 
@ OPTION_SAVE_ALL_DISSIPATIONS
 
@ OPTION_ADJUST_INCLUDE_PATHS
 
@ OPTION_CUR_SHEET_AS_ROOT
 
SCH_SHEET_LIST BuildSheetList(unsigned aNetlistOptions=0) const
Return the paths of exported sheets (either all or the current one).
 
void readModel(SCH_SHEET_PATH &aSheet, SCH_SYMBOL &aSymbol, SPICE_ITEM &aItem, REPORTER &aReporter)
 
virtual wxString GenerateItemPinNetName(const wxString &aNetName, int &aNcCounter) const
 
std::set< wxString > m_nets
Items representing schematic symbols in Spice world.
 
void readRefName(SCH_SHEET_PATH &aSheet, SCH_SYMBOL &aSymbol, SPICE_ITEM &aItem, std::set< std::string > &aRefNames)
 
wxString GetItemName(const wxString &aRefName) const
Return name of Spice device corresponding to a schematic symbol.
 
void writeItems(OUTPUTFORMATTER &aFormatter)
 
std::vector< wxString > m_directives
Spice directives found in the schematic sheet.
 
virtual void WriteHead(OUTPUTFORMATTER &aFormatter, unsigned aNetlistOptions)
Write the netlist head (title and so on).
 
void writeInclude(OUTPUTFORMATTER &aFormatter, unsigned aNetlistOptions, const wxString &aPath)
 
virtual void WriteDirectives(const wxString &aSimCommand, unsigned aSimOptions, OUTPUTFORMATTER &candidate) const
 
NETLIST_EXPORTER_SPICE(SCHEMATIC *aSchematic)
 
SIM_LIB_MGR m_libMgr
Holds libraries and models.
 
const SPICE_ITEM * FindItem(const wxString &aRefName) const
Find and return the item corresponding to aRefName.
 
virtual bool ReadSchematicAndLibraries(unsigned aNetlistOptions, REPORTER &aReporter)
Process the schematic and Spice libraries to create net mapping and a list of SPICE_ITEMs.
 
bool DoWriteNetlist(const wxString &aSimCommand, unsigned aSimOptions, OUTPUTFORMATTER &aFormatter, REPORTER &aReporter)
Write the netlist in aFormatter.
 
void readPinNumbers(SCH_SYMBOL &aSymbol, SPICE_ITEM &aItem, const std::vector< PIN_INFO > &aPins)
 
const std::list< SPICE_ITEM > & GetItems() const
Return the list of items representing schematic symbols in the Spice world.
 
void readNodePattern(SPICE_ITEM &aItem)
 
std::set< wxString > m_rawIncludes
include directives found in symbols
 
virtual void WriteTail(OUTPUTFORMATTER &aFormatter, unsigned aNetlistOptions)
Write the tail (.end).
 
NAME_GENERATOR m_modelNameGenerator
Generates unique model names.
 
bool WriteNetlist(const wxString &aOutFileName, unsigned aNetlistOptions, REPORTER &aReporter) override
Write to specified output file.
 
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
 
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.
 
virtual bool HasMessageOfSeverity(int aSeverityMask) const
Returns true if the reporter has one or more messages matching the specified severity mask.
 
Holds all the data relating to one schematic.
 
EMBEDDED_FILES * GetEmbeddedFiles() override
 
Base class for any item which can be embedded within the SCHEMATIC container class,...
 
bool ResolveExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const
 
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
 
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
 
bool GetExcludedFromSim() const
 
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
 
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
 
const SPICE_GENERATOR & SpiceGenerator() const
 
std::string IbisDevice(const SPICE_ITEM &aItem, SCHEMATIC *aSchematic, const wxString &aCacheDir, REPORTER &aReporter) const
 
virtual std::string ModelName(const SPICE_ITEM &aItem) const
 
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
 
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
 
This file is part of the common library.
 
wxString ResolveFile(const wxString &aFileName, const ENV_VAR_MAP *aEnvVars, const PROJECT *aProject)
Search the default paths trying to find one with the requested file.
 
Helper functions to substitute paths with environmental variables.
 
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
 
must_if< error >::control< Rule > control
 
PGM_BASE & Pgm()
The global program "get" accessor.
 
wxString GetFieldValue(const std::vector< SCH_FIELD > *aFields, FIELD_T aFieldType)
 
#define SIM_NODES_FORMAT_FIELD
 
std::vector< FAB_LAYER_COLOR > dummy
 
wxString UnescapeString(const wxString &aSource)
 
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
 
Notes: spaces are allowed everywhere in any number ~ can only be before ?
 
std::vector< SCH_FIELD > fields
 
std::vector< std::string > pinNetNames
 
std::string baseModelName
 
std::vector< std::string > pinNumbers
 
@ USER
The field ID hasn't been set yet; field is invalid.
 
@ REFERENCE
Field Reference of part, i.e. "IC21".
 
wxString result
Test unit parsing edge cases and error handling.