54 std::string
name = aProposedName;
58 name = fmt::format(
"{}#{}", aProposedName, ii++ );
66 m_libMgr( &aSchematic->
Prj() )
68 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
78 return DoWriteNetlist( wxEmptyString, aNetlistOptions, formatter, aReporter );
111 aFormatter.
Print( 0,
".title KiCad schematic\n" );
117 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 );
190 spiceItem.
fields.emplace_back( symbol, FIELD_T::USER, field.GetName() );
192 if( field.GetId() == FIELD_T::REFERENCE )
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() )
307 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
309 if( item->ResolveExcludedFromSim() )
313 text =
static_cast<SCH_TEXT*
>( item )->GetShownText( &sheet,
false );
320 wxStringTokenizer tokenizer(
text, wxT(
"\r\n" ), wxTOKEN_STRTOK );
321 bool foundDirective =
false;
324 [](
const wxString& line,
const wxString& dir )
326 return line == dir || line.StartsWith( dir + wxS(
" " ) );
329 while( tokenizer.HasMoreTokens() )
331 wxString line = tokenizer.GetNextToken().Upper();
333 if( line.StartsWith( wxT(
"." ) ) )
335 if( isDirective( line, wxS(
".AC" ) )
336 || isDirective( line, wxS(
".CONTROL" ) )
337 || isDirective( line, wxS(
".CSPARAM" ) )
338 || isDirective( line, wxS(
".DISTO" ) )
339 || isDirective( line, wxS(
".DC" ) )
340 || isDirective( line, wxS(
".ELSE" ) )
341 || isDirective( line, wxS(
".ELSEIF" ) )
342 || isDirective( line, wxS(
".END" ) )
343 || isDirective( line, wxS(
".ENDC" ) )
344 || isDirective( line, wxS(
".ENDIF" ) )
345 || isDirective( line, wxS(
".ENDS" ) )
346 || isDirective( line, wxS(
".FOUR" ) )
347 || isDirective( line, wxS(
".FUNC" ) )
348 || isDirective( line, wxS(
".GLOBAL" ) )
349 || isDirective( line, wxS(
".IC" ) )
350 || isDirective( line, wxS(
".IF" ) )
351 || isDirective( line, wxS(
".INCLUDE" ) )
352 || isDirective( line, wxS(
".LIB" ) )
353 || isDirective( line, wxS(
".MEAS" ) )
354 || isDirective( line, wxS(
".MODEL" ) )
355 || isDirective( line, wxS(
".NODESET" ) )
356 || isDirective( line, wxS(
".NOISE" ) )
357 || isDirective( line, wxS(
".OP" ) )
358 || isDirective( line, wxS(
".OPTIONS" ) )
359 || isDirective( line, wxS(
".PARAM" ) )
360 || isDirective( line, wxS(
".PLOT" ) )
361 || isDirective( line, wxS(
".PRINT" ) )
362 || isDirective( line, wxS(
".PROBE" ) )
363 || isDirective( line, wxS(
".PZ" ) )
364 || isDirective( line, wxS(
".SAVE" ) )
365 || isDirective( line, wxS(
".SENS" ) )
366 || isDirective( line, wxS(
".SP" ) )
367 || isDirective( line, wxS(
".SUBCKT" ) )
368 || isDirective( line, wxS(
".TEMP" ) )
369 || isDirective( line, wxS(
".TF" ) )
370 || isDirective( line, wxS(
".TITLE" ) )
371 || isDirective( line, wxS(
".TRAN" ) )
372 || isDirective( line, wxS(
".WIDTH" ) ) )
374 foundDirective =
true;
378 else if( line.StartsWith( wxT(
"K" ) ) )
381 wxStringTokenizer line_t( line, wxT(
" \t" ), wxTOKEN_STRTOK );
384 if( !line_t.HasMoreTokens() || !line_t.GetNextToken().StartsWith( wxT(
"K" ) ) )
388 if( !line_t.HasMoreTokens() || !line_t.GetNextToken().StartsWith( wxT(
"L" ) ) )
392 if( !line_t.HasMoreTokens() || !line_t.GetNextToken().StartsWith( wxT(
"L" ) ) )
397 if( line_t.HasMoreTokens() )
399 foundDirective =
true;
413 SPICE_ITEM& aItem, std::set<std::string>& aRefNames )
417 if( !aRefNames.insert( aItem.
refName ).second )
418 wxASSERT( wxT(
"Duplicate refdes encountered; what happened to ReadyToNetlist()?" ) );
437 int libParamIndex =
static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB );
438 wxString
path = rawSpiceModel->GetParam( libParamIndex ).value;
440 if( !
path.IsEmpty() )
447 cacheFn.AppendDir( wxT(
"ibis" ) );
448 cacheFn.SetFullName( aSymbol.
GetRef( &aSheet ) + wxT(
".cache" ) );
450 wxFile cacheFile( cacheFn.GetFullPath(), wxFile::write );
452 if( !cacheFile.IsOpened() )
454 wxLogError(
_(
"Could not open file '%s' to write IBIS model" ),
455 cacheFn.GetFullPath() );
460 wxString cacheFilepath = cacheFn.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
462 cacheFilepath, aReporter );
464 cacheFile.Write( wxString( modelData ) );
471 const std::vector<PIN_INFO>& aPins )
479 const std::vector<PIN_INFO>& aPins,
int& aNcCounter )
481 for(
const PIN_INFO& pinInfo : aPins )
485 aItem.
pinNetNames.push_back( netName.ToStdString() );
492 std::vector<std::string>& aModifiers )
499 tao::pegtl::string_input<> in( input,
"Sim.NodesFormat field" );
500 std::unique_ptr<tao::pegtl::parse_tree::node> root;
501 std::string singleNodeModifier;
509 for(
const auto& node : root->children )
514 aModifiers.back().append( node->string() );
518 singleNodeModifier.append( node->string() );
523 aModifiers.push_back( singleNodeModifier );
524 singleNodeModifier.erase( singleNodeModifier.begin(), singleNodeModifier.end() );
528 catch(
const tao::pegtl::parse_error& e )
530 THROW_IO_ERROR( wxString::Format(
_(
"Error in parsing model '%s', error: '%s'" ),
536 std::vector<std::string> xspicePattern;
539 if( xspicePattern.empty() )
542 if( xspicePattern.size() != aItem.
pinNetNames.size() )
544 THROW_IO_ERROR( wxString::Format(
_(
"Error in parsing model '%s', wrong number of nodes "
545 "'?' in Sim.NodesFormat compared to connections" ),
552 for( std::string& pattern : xspicePattern )
555 const std::string netName =
" " + *itNetNames +
" ";
556 pattern.replace( pattern.find(
"?" ), 1, netName );
557 *itNetNames = pattern;
563 const wxString& aPath )
569 expandedPath.Replace(
'\\',
'/' );
578 if( fullPath.IsEmpty() )
580 wxLogError(
_(
"Could not find library file '%s'" ), expandedPath );
581 fullPath = expandedPath;
583 else if( wxFileName::GetPathSeparator() ==
'\\' )
586 fullPath.Replace(
'\\',
'/' );
591 fullPath = expandedPath;
594 aFormatter.
Print( 0,
".include \"%s\"\n",
TO_UTF8( fullPath ) );
615 if( !item.model->IsEnabled() )
618 aFormatter.
Print( 0,
"%s", item.model->SpiceGenerator().ModelLine( item ).c_str() );
627 if( !item.model->IsEnabled() )
630 aFormatter.
Print( 0,
"%s", item.model->SpiceGenerator().ItemLine( item ).c_str() );
639 aFormatter.
Print( 0,
".save all\n" );
642 aFormatter.
Print( 0,
".probe alli\n" );
650 std::string itemName = item.model->SpiceGenerator().ItemName( item );
652 if( ( item.model->GetPinCount() >= 2 ) && ( itemName.size() > 0 )
653 && ( itemName.c_str()[0] !=
'A' ) )
655 aFormatter.
Print( 0,
".probe p(%s)\n", itemName.c_str() );
661 [](
const wxString& candidate,
const wxString& dir )
663 return candidate == dir || candidate.StartsWith( dir + wxS(
" " ) );
668 bool simCommand =
false;
670 if( directive.StartsWith(
"." ) )
672 wxString candidate = directive.Upper();
674 simCommand = ( isSimCommand( candidate, wxS(
".AC" ) )
675 || isSimCommand( candidate, wxS(
".DC" ) )
676 || isSimCommand( candidate, wxS(
".TRAN" ) )
677 || isSimCommand( candidate, wxS(
".OP" ) )
678 || isSimCommand( candidate, wxS(
".DISTO" ) )
679 || isSimCommand( candidate, wxS(
".NOISE" ) )
680 || isSimCommand( candidate, wxS(
".PZ" ) )
681 || isSimCommand( candidate, wxS(
".SENS" ) )
682 || isSimCommand( candidate, wxS(
".TF" ) ) );
692 int& aNcCounter )
const
698 if( netName.IsEmpty() )
699 netName.Printf( wxS(
"NC-%d" ), aNcCounter++ );
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)
An abstract class used for the netlist exporters that Eeschema supports.
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
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.
PROJECT & Prj() const
Return a reference to the project this schematic is part of.
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
EMBEDDED_FILES * GetEmbeddedFiles() override
SCH_SHEET_PATH & CurrentSheet() const
Base class for any item which can be embedded within the SCHEMATIC container class,...
bool ResolveExcludedFromSim() 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
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
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
virtual wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
std::map< wxString, std::reference_wrapper< const SIM_LIBRARY > > GetLibraries() const
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
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
void Clear()
Erase the record.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
const char * c_str() const
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)
must_if< error >::control< Rule > control
void delete_if(_Container &__c, _Function &&__f)
Deletes all values from __c for which __f returns true.
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 ? ~~ is not allowed [] can en...
std::vector< SCH_FIELD > fields
std::vector< std::string > pinNetNames
std::string baseModelName
std::vector< std::string > pinNumbers