45#include <wx/tokenzr.h>
52 std::string
name = aProposedName;
58 name = fmt::format(
"{}#{}", aProposedName, ii++ );
68 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
70 m_libMgr.SetFilesStack( std::move( embeddedFilesStack ) );
122 aFormatter.
Print( 0,
".title KiCad schematic\n" );
128 aFormatter.
Print( 0,
".end\n" );
135 std::set<std::string> refNames;
137 wxString variant =
m_schematic->GetCurrentVariant();
150 cacheDir.AppendDir( wxT(
"ibis" ) );
152 if( !cacheDir.DirExists() )
154 cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
156 if( !cacheDir.DirExists() )
158 wxLogTrace( wxT(
"IBIS_CACHE:" ),
159 wxT(
"%s:%s:%d\n * failed to create ibis cache directory '%s'" ),
160 __FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
167 wxString dirName = cacheDir.GetFullPath();
169 if( !dir.Open( dirName ) )
173 wxArrayString fileList;
174 wxString fileSpec = wxT(
"*.cache" );
176 thisFile.SetPath( dirName );
178 size_t numFilesFound = wxDir::GetAllFiles( dirName, &fileList, fileSpec );
180 for(
size_t ii = 0; ii < numFilesFound; ii++ )
183 thisFile.SetFullName( fileList[ii] );
184 wxRemoveFile( thisFile.GetFullPath() );
199 std::vector<PIN_INFO> pins =
CreatePinList( symbol, sheet,
true );
206 spiceItem.
fields.back().SetText( symbol->
GetRef( &sheet ) );
208 spiceItem.
fields.back().SetText( field.GetShownText( &sheet,
false, 0, variant ) );
211 readRefName( sheet, *symbol, spiceItem, refNames );
212 readModel( sheet, *symbol, spiceItem, variant, aReporter );
218 m_items.push_back( std::move( spiceItem ) );
234 std::unique_ptr<MARKUP::NODE> root = markupParser.
Parse();
236 std::function<void(
const std::unique_ptr<MARKUP::NODE>&)> convertMarkup =
237 [&](
const std::unique_ptr<MARKUP::NODE>& aNode )
241 if( !aNode->is_root() )
243 if( aNode->isOverbar() )
248 else if( aNode->isSubscript() || aNode->isSuperscript() )
253 if( aNode->has_content() )
254 *aNetName += aNode->string();
257 for(
const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
258 convertMarkup( child );
262 *aNetName = wxEmptyString;
263 convertMarkup( root );
266 aNetName->Replace(
'%',
'_' );
267 aNetName->Replace(
'(',
'_' );
268 aNetName->Replace(
')',
'_' );
269 aNetName->Replace(
',',
'_' );
270 aNetName->Replace(
'[',
'_' );
271 aNetName->Replace(
']',
'_' );
272 aNetName->Replace(
'<',
'_' );
273 aNetName->Replace(
'>',
'_' );
274 aNetName->Replace(
'~',
'_' );
275 aNetName->Replace(
' ',
'_' );
279 if( aNetName->EndsWith( wxS(
"/0" ) ) && !aNetName->EndsWith( wxS(
"//0" ) ) )
280 aNetName->assign( wxS(
"0" ) );
284 if( aNetName->IsSameAs( wxS(
"/gnd" ),
false ) )
285 aNetName->assign( aNetName->Mid( 1 ) );
289 if( aNetName->StartsWith( wxS(
"//" ) ) )
290 aNetName->Replace( wxS(
"//" ), wxS(
"/root/" ),
false );
297 return item->model->SpiceGenerator().ItemName( *item );
299 return wxEmptyString;
305 const std::string refName = aRefName.ToStdString();
306 const std::list<SPICE_ITEM>& spiceItems =
GetItems();
308 auto it = std::find_if( spiceItems.begin(), spiceItems.end(),
311 return item.refName == refName;
314 if( it != spiceItems.end() )
329 for(
SCH_ITEM* item : sheet.LastScreen()->Items() )
331 if( item->ResolveExcludedFromSim() )
335 text =
static_cast<SCH_TEXT*
>( item )->GetShownText( &sheet,
false );
337 text =
static_cast<SCH_TEXTBOX*
>( item )->GetShownText(
nullptr, &sheet,
false );
342 wxStringTokenizer tokenizer(
text,
"\r\n", wxTOKEN_STRTOK );
343 bool foundDirective =
false;
346 [](
const wxString& line,
const wxString& dir )
348 return line == dir || line.StartsWith( dir + wxS(
" " ) );
351 while( tokenizer.HasMoreTokens() )
353 wxString line = tokenizer.GetNextToken().Upper();
355 if( line.StartsWith( wxT(
"." ) ) )
357 if( isDirective( line, wxS(
".AC" ) )
358 || isDirective( line, wxS(
".CONTROL" ) )
359 || isDirective( line, wxS(
".CSPARAM" ) )
360 || isDirective( line, wxS(
".DISTO" ) )
361 || isDirective( line, wxS(
".DC" ) )
362 || isDirective( line, wxS(
".ELSE" ) )
363 || isDirective( line, wxS(
".ELSEIF" ) )
364 || isDirective( line, wxS(
".END" ) )
365 || isDirective( line, wxS(
".ENDC" ) )
366 || isDirective( line, wxS(
".ENDIF" ) )
367 || isDirective( line, wxS(
".ENDS" ) )
368 || isDirective( line, wxS(
".FOUR" ) )
369 || isDirective( line, wxS(
".FUNC" ) )
370 || isDirective( line, wxS(
".GLOBAL" ) )
371 || isDirective( line, wxS(
".IC" ) )
372 || isDirective( line, wxS(
".IF" ) )
373 || isDirective( line, wxS(
".INCLUDE" ) )
374 || isDirective( line, wxS(
".LIB" ) )
375 || isDirective( line, wxS(
".MEAS" ) )
376 || isDirective( line, wxS(
".MODEL" ) )
377 || isDirective( line, wxS(
".NODESET" ) )
378 || isDirective( line, wxS(
".NOISE" ) )
379 || isDirective( line, wxS(
".OP" ) )
380 || isDirective( line, wxS(
".OPTIONS" ) )
381 || isDirective( line, wxS(
".PARAM" ) )
382 || isDirective( line, wxS(
".PLOT" ) )
383 || isDirective( line, wxS(
".PRINT" ) )
384 || isDirective( line, wxS(
".PROBE" ) )
385 || isDirective( line, wxS(
".PZ" ) )
386 || isDirective( line, wxS(
".SAVE" ) )
387 || isDirective( line, wxS(
".SENS" ) )
388 || isDirective( line, wxS(
".SP" ) )
389 || isDirective( line, wxS(
".SUBCKT" ) )
390 || isDirective( line, wxS(
".TEMP" ) )
391 || isDirective( line, wxS(
".TF" ) )
392 || isDirective( line, wxS(
".TITLE" ) )
393 || isDirective( line, wxS(
".TRAN" ) )
394 || isDirective( line, wxS(
".WIDTH" ) ) )
396 foundDirective =
true;
400 else if( line.StartsWith( wxT(
"K" ) ) )
403 wxStringTokenizer line_t( line,
" \t", wxTOKEN_STRTOK );
406 if( !line_t.HasMoreTokens() || !line_t.GetNextToken().StartsWith( wxT(
"K" ) ) )
410 if( !line_t.HasMoreTokens() || !line_t.GetNextToken().StartsWith( wxT(
"L" ) ) )
414 if( !line_t.HasMoreTokens() || !line_t.GetNextToken().StartsWith( wxT(
"L" ) ) )
419 if( line_t.HasMoreTokens() )
421 foundDirective =
true;
436 const wxString& aVariantName )
440 return wxEmptyString;
442 wxString ref = aSymbol.
GetRef( &aSheet );
443 std::vector<std::pair<wxString, wxString>> pinList;
444 std::set<wxString> pinNumbers;
447 auto parsePins = [&](
const wxString& aPins )
449 wxStringTokenizer tokenizer( aPins, wxS(
" \t\r\n" ), wxTOKEN_STRTOK );
451 while( tokenizer.HasMoreTokens() )
453 wxString token = tokenizer.GetNextToken();
454 int pos = token.Find( wxS(
'=' ) );
456 if( pos == wxNOT_FOUND )
459 wxString pinNumber = token.Left( pos );
460 wxString modelPin = token.Mid( pos + 1 );
463 if( pinNumbers.insert( pinNumber ).second )
464 pinList.emplace_back( pinNumber, modelPin );
470 parsePins( pinsField->GetShownText( &aSheet,
false, 0, aVariantName ) );
479 if( other == &aSymbol )
482 if( other->
GetRef( &sheet ) != ref )
486 parsePins( pinsField->GetShownText( &sheet,
false, 0, aVariantName ) );
492 if( pinList.empty() )
493 return wxEmptyString;
498 for(
const auto& [pinNumber, modelPin] : pinList )
500 if( !merged.IsEmpty() )
501 merged += wxS(
" " );
503 merged += pinNumber + wxS(
"=" ) + modelPin;
512 const wxString& aVariantName )
514 std::vector<UNIT_PIN_MAP> unitMaps;
519 wxString ref = aSymbol.
GetRef( &aSheet );
520 std::set<int> seenUnits;
530 wxString pins = pinsField->
GetShownText( &aUnitSheet,
false, 0, aVariantName );
534 if( !seenUnits.insert( aUnit.
GetUnit() ).second )
541 if( !map.
pins.empty() )
542 unitMaps.push_back( std::move( map ) );
547 parseUnit( aSymbol, aSheet );
555 if( other == &aSymbol )
558 if( other->
GetRef( &sheet ).CmpNoCase( ref ) != 0 )
561 parseUnit( *other, sheet );
567 std::sort( unitMaps.begin(), unitMaps.end(),
570 return lhs.unit < rhs.unit;
579 const wxString& aVariantName )
const
585 return field->GetShownText( &aUnitSheet,
false, 0, aVariantName );
587 return wxEmptyString;
592 wxString value = read( aSymbol, aSheet );
596 wxString ref = aSymbol.
GetRef( &aSheet );
604 if( other == &aSymbol || other->
GetRef( &sheet ).CmpNoCase( ref ) != 0 )
607 value = read( *other, sheet );
609 if( !value.IsEmpty() )
620 SPICE_ITEM& aItem, std::set<std::string>& aRefNames )
624 [[maybe_unused]]
bool inserted = aRefNames.insert( aItem.
refName ).second;
625 wxASSERT_MSG( inserted, wxT(
"Duplicate refdes encountered; what happened to ReadyToNetlist()?" ) );
630 const wxString& aVariantName,
REPORTER& aReporter )
639 wxString mergedSimPins = repeat ? wxString()
643 aReporter, mergedSimPins );
653 if( libModel.
model.
GetType() != SIM_MODEL::TYPE::SUBCKT || libModel.
name.empty() )
656 _(
"Symbol '%s' uses repeat-per-unit decomposition, which requires a named "
657 "subcircuit model." ),
658 aSymbol.
GetRef( &aSheet ) ) );
661 std::vector<UNIT_PIN_MAP> unitMaps =
collectUnitPinMaps( aSymbol, aSheet, aVariantName );
668 auto wrapper = std::make_unique<SIM_MODEL_MULTIUNIT>( libModel.
model, libModel.
name, unitMaps,
692 int libParamIndex =
static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB );
693 wxString
path = rawSpiceModel->GetParam( libParamIndex ).value;
695 if( !
path.IsEmpty() )
702 cacheFn.AppendDir( wxT(
"ibis" ) );
703 cacheFn.SetFullName( aSymbol.
GetRef( &aSheet ) + wxT(
".cache" ) );
705 wxFile cacheFile( cacheFn.GetFullPath(), wxFile::write );
707 if( !cacheFile.IsOpened() )
709 wxLogError(
_(
"Could not open file '%s' to write IBIS model" ),
710 cacheFn.GetFullPath() );
715 wxString cacheFilepath = cacheFn.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR );
717 cacheFilepath, aReporter );
719 cacheFile.Write( wxString( modelData ) );
726 const std::vector<PIN_INFO>& aPins )
734 const std::vector<PIN_INFO>& aPins,
int& aNcCounter )
736 for(
const PIN_INFO& pinInfo : aPins )
740 aItem.
pinNetNames.push_back( netName.ToStdString() );
747 std::vector<std::string>& aModifiers )
754 tao::pegtl::string_input<> in( input,
"Sim.NodesFormat field" );
755 std::unique_ptr<tao::pegtl::parse_tree::node> root;
756 std::string singleNodeModifier;
764 for(
const auto& node : root->children )
769 aModifiers.back().append( node->string() );
773 singleNodeModifier.append( node->string() );
778 aModifiers.push_back( singleNodeModifier );
779 singleNodeModifier.erase( singleNodeModifier.begin(), singleNodeModifier.end() );
783 catch(
const tao::pegtl::parse_error& e )
785 THROW_IO_ERROR( wxString::Format(
_(
"Error in parsing model '%s', error: '%s'" ),
791 std::vector<std::string> xspicePattern;
794 if( xspicePattern.empty() )
797 if( xspicePattern.size() != aItem.
pinNetNames.size() )
799 THROW_IO_ERROR( wxString::Format(
_(
"Error in parsing model '%s', wrong number of nodes "
800 "'?' in Sim.NodesFormat compared to connections" ),
807 for( std::string& pattern : xspicePattern )
810 const std::string netName =
" " + *itNetNames +
" ";
811 pattern.replace( pattern.find(
"?" ), 1, netName );
812 *itNetNames = pattern;
818 const wxString& aPath )
824 expandedPath.Replace(
'\\',
'/' );
833 if( fullPath.IsEmpty() )
835 wxLogError(
_(
"Could not find library file '%s'" ), expandedPath );
836 fullPath = expandedPath;
838 else if( wxFileName::GetPathSeparator() ==
'\\' )
841 fullPath.Replace(
'\\',
'/' );
846 fullPath = expandedPath;
849 aFormatter.
Print( 0,
".include \"%s\"\n",
TO_UTF8( fullPath ) );
868 std::set<std::string> emittedWrappers;
872 if( !item.model->IsEnabled() )
878 && !emittedWrappers.insert( item.modelName ).second )
883 aFormatter.
Print( 0,
"%s", item.model->SpiceGenerator().ModelLine( item ).c_str() );
892 if( !item.model->IsEnabled() )
895 aFormatter.
Print( 0,
"%s", item.model->SpiceGenerator().ItemLine( item ).c_str() );
904 aFormatter.
Print( 0,
".save all\n" );
907 aFormatter.
Print( 0,
".probe alli\n" );
915 std::string itemName = item.model->SpiceGenerator().ItemName( item );
917 if( ( item.model->GetPinCount() >= 2 ) && ( itemName.size() > 0 )
918 && ( itemName.c_str()[0] !=
'A' ) )
920 aFormatter.
Print( 0,
".probe p(%s)\n", itemName.c_str() );
926 [](
const wxString& candidate,
const wxString& dir )
928 return candidate == dir || candidate.StartsWith( dir + wxS(
" " ) );
933 bool simCommand =
false;
935 if( directive.StartsWith(
"." ) )
937 wxString candidate = directive.Upper();
939 simCommand = ( isSimCommand( candidate, wxS(
".AC" ) )
940 || isSimCommand( candidate, wxS(
".DC" ) )
941 || isSimCommand( candidate, wxS(
".TRAN" ) )
942 || isSimCommand( candidate, wxS(
".OP" ) )
943 || isSimCommand( candidate, wxS(
".DISTO" ) )
944 || isSimCommand( candidate, wxS(
".NOISE" ) )
945 || isSimCommand( candidate, wxS(
".PZ" ) )
946 || isSimCommand( candidate, wxS(
".SENS" ) )
947 || isSimCommand( candidate, wxS(
".TF" ) ) );
951 aFormatter.
Print( 0,
"%s\n",
UTF8( directive ).c_str() );
957 int& aNcCounter )
const
963 if( netName.IsEmpty() )
964 netName.Printf( wxS(
"NC-%d" ), aNcCounter++ );
979 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()
int GetUnitCount() const override
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
Owns the synthesized repeat-per-unit wrappers referenced by 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).
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)
wxString collectMergedSimPins(SCH_SYMBOL &aSymbol, const SCH_SHEET_PATH &aSheet, const wxString &aVariantName)
Collect merged Sim.Pins from all units of a multi-unit symbol.
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.
SIM_DECOMPOSITION getDecomposition(SCH_SYMBOL &aSymbol, const SCH_SHEET_PATH &aSheet, const wxString &aVariantName) const
Read and parse the Sim.Decomposition field from the primary unit.
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
void readModel(SCH_SHEET_PATH &aSheet, SCH_SYMBOL &aSymbol, SPICE_ITEM &aItem, const wxString &aVariantName, REPORTER &aReporter)
virtual void WriteTail(OUTPUTFORMATTER &aFormatter, unsigned aNetlistOptions)
Write the tail (.end).
NAME_GENERATOR m_modelNameGenerator
Generates unique model names.
std::vector< std::unique_ptr< SIM_MODEL_MULTIUNIT > > m_multiunitModels
bool WriteNetlist(const wxString &aOutFileName, unsigned aNetlistOptions, REPORTER &aReporter) override
Write to specified output file.
std::vector< UNIT_PIN_MAP > collectUnitPinMaps(SCH_SYMBOL &aSymbol, const SCH_SHEET_PATH &aSheet, const wxString &aVariantName)
Gather every unit's Sim.Pins mapping for a multi-unit symbol, one entry per unit.
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
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) const
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.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Wraps a resolved single-unit base model and presents it as one component-level SPICE device.
virtual bool requiresSpiceModelLine(const SPICE_ITEM &aItem) const
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
#define SIM_DECOMPOSITION_FIELD
std::vector< std::pair< wxString, wxString > > ParseSimPinsTokens(const wxString &aPins, const wxString &aRef)
Parse one unit's Sim.Pins text into (symbolPinNumber -> modelPinName) pairs, preserving the written o...
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.
Per-component decomposition descriptor stored in the Sim.Decomposition field.
static SIM_DECOMPOSITION Parse(const wxString &aField)
std::vector< wxString > sharedModelPins
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
One functional unit's pin map, gathered from its Sim.Pins field.
std::vector< std::pair< wxString, wxString > > pins
@ 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.