Update simulator with NUMERIC_EVAL, decimal separator processing, etc.

Also includes fixes for instance data and resolving of textvar
references.

Also includes virtual d'tors for IBIS parser to get rid of all the
compile warnings on CLang.

Fixes https://gitlab.com/kicad/code/kicad/issues/12357
This commit is contained in:
Jeff Young 2022-12-05 02:07:45 +00:00
parent 54dd494ff2
commit b7d41e0e56
23 changed files with 380 additions and 464 deletions

View File

@ -59,11 +59,12 @@ expr(A) ::= expr(B) PLUS expr(C). { A.dValue = B.dValue + C.dValue; A.va
expr(A) ::= expr(B) MINUS expr(C). { A.dValue = B.dValue - C.dValue; A.valid=C.valid; }
expr(A) ::= expr(B) MULT expr(C). { A.dValue = B.dValue * C.dValue; A.valid=C.valid; }
expr(A) ::= expr(B) DIVIDE expr(C). {
if (C.dValue != 0.0) {
A.dValue = B.dValue / C.dValue;
}
else pEval->parseError("Div by zero");
A.valid=C.valid;
}
expr(A) ::= PARENL expr(B) PARENR. { A.dValue = B.dValue; A.valid=B.valid; }
if( C.dValue != 0.0 )
A.dValue = B.dValue / C.dValue;
else
pEval->parseError( "Divide by zero" );
A.valid = C.valid;
}
expr(A) ::= PARENL expr(B) PARENR. { A.dValue = B.dValue; A.valid = B.valid; }

View File

@ -87,6 +87,7 @@ void NUMERIC_EVALUATOR::SetDefaultUnits( EDA_UNITS aUnits )
case EDA_UNITS::MILS: m_defaultUnits = Unit::Mil; break;
case EDA_UNITS::INCHES: m_defaultUnits = Unit::Inch; break;
case EDA_UNITS::DEGREES: m_defaultUnits = Unit::Degrees; break;
case EDA_UNITS::UNSCALED: m_defaultUnits = Unit::SI; break;
default: m_defaultUnits = Unit::MM; break;
}
}
@ -196,47 +197,82 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
if( m_token.pos >= m_token.inputLen )
return retval;
// Support for old school decimal separators (ie: "2K2")
auto isOldSchoolDecimalSeparator =
[]( char ch, double* siScaler ) -> bool
{
switch( ch )
{
case 'a': *siScaler = 1.0e-18; return true;
case 'f': *siScaler = 1.0e-15; return true;
case 'p': *siScaler = 1.0e-12; return true;
case 'n': *siScaler = 1.0e-9; return true;
case 'u': *siScaler = 1.0e-6; return true;
case 'm': *siScaler = 1.0e-3; return true;
case 'k':
case 'K': *siScaler = 1.0e3; return true;
case 'M': *siScaler = 1.0e6; return true;
case 'G': *siScaler = 1.0e9; return true;
case 'T': *siScaler = 1.0e12; return true;
case 'P': *siScaler = 1.0e15; return true;
case 'E': *siScaler = 1.0e18; return true;
default: return false;
}
};
auto isDecimalSeparator =
[&]( char ch ) -> bool
{
return ( ch == m_localeDecimalSeparator || ch == '.' || ch == ',' );
double dummy;
if( ch == m_localeDecimalSeparator || ch == '.' || ch == ',' )
return true;
if( m_defaultUnits == Unit::SI && isOldSchoolDecimalSeparator( ch, &dummy ) )
return true;
return false;
};
// Lambda: get value as string, store into clToken.token and update current index.
auto extractNumber =
[&]()
[&]( double* aScaler )
{
bool haveSeparator = false;
bool haveSeparator = false;
double siScaler = 1.0;
char ch = m_token.input[ m_token.pos ];
idx = 0;
char ch = m_token.input[ m_token.pos ];
do
{
if( isDecimalSeparator( ch ) && haveSeparator )
break;
m_token.token[ idx++ ] = ch;
if( isDecimalSeparator( ch ) )
haveSeparator = true;
{
if( haveSeparator )
break;
else
haveSeparator = true;
if( isOldSchoolDecimalSeparator( ch, &siScaler ) )
*aScaler = siScaler;
m_token.token[ idx++ ] = m_localeDecimalSeparator;
}
else
{
m_token.token[ idx++ ] = ch;
}
ch = m_token.input[ ++m_token.pos ];
} while( isdigit( ch ) || isDecimalSeparator( ch ) );
m_token.token[ idx ] = 0;
// Ensure that the systems decimal separator is used
for( int i = strlen( m_token.token ); i; i-- )
{
if( isDecimalSeparator( m_token.token[ i - 1 ] ) )
m_token.token[ i - 1 ] = m_localeDecimalSeparator;
}
};
// Lamda: Get unit for current token.
// Valid units are ", in, mm, mil and thou. Returns Unit::Invalid otherwise.
auto checkUnit =
[this]() -> Unit
[&]( double* siScaler ) -> Unit
{
char ch = m_token.input[ m_token.pos ];
@ -289,6 +325,13 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
return Unit::Mil;
}
if( m_defaultUnits == Unit::SI && sizeLeft >= 1
&& isOldSchoolDecimalSeparator( ch, siScaler ) )
{
m_token.pos++;
return Unit::SI;
}
return Unit::Invalid;
};
@ -305,20 +348,21 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
break;
}
Unit convertFrom;
double siScaler;
Unit convertFrom;
if( ch == 0 )
{
/* End of input */
}
else if( isdigit( ch ) || isDecimalSeparator( ch ))
else if( isdigit( ch ) || isDecimalSeparator( ch ) )
{
// VALUE
extractNumber();
extractNumber( &siScaler );
retval.token = VALUE;
retval.value.dValue = atof( m_token.token );
retval.value.dValue = atof( m_token.token ) * siScaler;
}
else if( ( convertFrom = checkUnit() ) != Unit::Invalid )
else if( ( convertFrom = checkUnit( &siScaler ) ) != Unit::Invalid )
{
// UNIT
// Units are appended to a VALUE.
@ -368,6 +412,10 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
{
retval.value.dValue = 1.0;
}
else if( m_defaultUnits == Unit::SI )
{
retval.value.dValue = siScaler;
}
}
else if( isalpha( ch ) )
{

View File

@ -243,6 +243,10 @@ template <typename T>
bool DIALOG_SIM_MODEL<T>::TransferDataFromWindow()
{
m_pinAssignmentsGrid->CommitPendingChanges();
// This should have been done in wxPGTextCtrlEditor::OnTextCtrlEvent(), but something must
// be clearing it before we get here, resulting in CommitChangesFromEditor() doing nothing
m_paramGrid->GetGrid()->EditorsValueWasModified();
m_paramGrid->GetGrid()->CommitChangesFromEditor();
if( !DIALOG_SIM_MODEL_BASE::TransferDataFromWindow() )
@ -277,12 +281,14 @@ bool DIALOG_SIM_MODEL<T>::TransferDataFromWindow()
SIM_MODEL::SetFieldValue(
m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD,
kibismodel->GetIbisPins().at( m_ibisPinCombobox->GetSelection() ).first );
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD,
std::string( m_ibisModelCombobox->GetValue().c_str() ) );
SIM_MODEL::SetFieldValue(
m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD,
std::string( m_ibisModelCombobox->GetValue().c_str() ) );
SIM_MODEL::SetFieldValue(
m_fields, SIM_LIBRARY_KIBIS::DIFF_FIELD,
( kibismodel->CanDifferential() && m_differentialCheckbox->GetValue() ) ? "1"
: "" );
( kibismodel->CanDifferential() && m_differentialCheckbox->GetValue() ) ? "1" : "" );
}
}
@ -644,13 +650,14 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aLibraryPath, bool aForce
try
{
std::string modelName = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD );
int pinCount = m_symbol.GetRawPins().size();
for( auto& [baseModelName, baseModel] : library()->GetModels() )
{
if( baseModelName == modelName )
m_libraryModelsMgr.CreateModel( baseModel, m_symbol.GetRawPins().size(), m_fields );
m_libraryModelsMgr.CreateModel( baseModel, pinCount, m_fields );
else
m_libraryModelsMgr.CreateModel( baseModel, m_symbol.GetRawPins().size() );
m_libraryModelsMgr.CreateModel( baseModel, pinCount );
}
}
catch( const IO_ERROR& e )
@ -800,7 +807,7 @@ wxPGProperty* DIALOG_SIM_MODEL<T>::newParamProperty( int aParamIndex ) const
else
{
prop = new SIM_ENUM_PROPERTY( paramDescription, param.info.name, curModel(),
aParamIndex, SIM_VALUE::TYPE_STRING );
aParamIndex );
}
break;
@ -939,32 +946,6 @@ int DIALOG_SIM_MODEL<T>::getModelPinIndex( const wxString& aModelPinString ) con
}
template <typename T>
void DIALOG_SIM_MODEL<T>::onKeyDown( wxKeyEvent& aEvent )
{
// Because wxPropertyGrid has special handling for the tab key, wxPropertyGrid::DedicateKey()
// and wxPropertyGrid::AddActionTrigger() don't work for it. So instead we translate it to an
// (up or down) arrow key, which has proper handling (select next or previous property) defined
// by the aforementioned functions.
if( aEvent.GetKeyCode() == WXK_TAB )
{
wxWindow* focus = FindFocus();
wxPropertyGrid* pg = focus ? dynamic_cast<wxPropertyGrid*>( focus->GetParent() ) : nullptr;
if( pg )
{
pg->CommitChangesFromEditor();
aEvent.m_keyCode = aEvent.ShiftDown() ? WXK_UP : WXK_DOWN;
aEvent.m_shiftDown = false;
}
}
aEvent.Skip();
}
template <typename T>
void DIALOG_SIM_MODEL<T>::onRadioButton( wxCommandEvent& aEvent )
{
@ -1187,8 +1168,7 @@ void DIALOG_SIM_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
m_libraryModelsMgr.GetModels().at( m_modelNameCombobox->GetSelection() ).get() );
m_libraryModelsMgr.SetModel( m_modelNameCombobox->GetSelection(),
std::make_unique<SIM_MODEL_KIBIS>( type,
kibisModel,
std::make_unique<SIM_MODEL_KIBIS>( type, kibisModel,
m_fields ) );
}

View File

@ -113,7 +113,6 @@ private:
wxString getModelPinString( int aModelPinIndex ) const;
int getModelPinIndex( const wxString& aModelPinString ) const;
void onKeyDown( wxKeyEvent& aEvent ) override;
void onRadioButton( wxCommandEvent& aEvent ) override;
void onLibraryPathTextEnter( wxCommandEvent& aEvent ) override;
void onLibraryPathTextKillFocus( wxFocusEvent& aEvent ) override;

View File

@ -197,6 +197,9 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
bSizerMargins->Add( m_saveInValueCheckbox, 0, wxALL, 6 );
bSizerMargins->Add( 0, 3, 0, wxEXPAND, 5 );
bSizerPanel->Add( bSizerMargins, 1, wxEXPAND, 5 );
@ -244,7 +247,7 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
bSizer10->Fit( m_pinAssignmentsPanel );
m_notebook->AddPage( m_pinAssignmentsPanel, _("Pin Assignments"), false );
bSizer8->Add( m_notebook, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
bSizer8->Add( m_notebook, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizer81;
bSizer81 = new wxBoxSizer( wxHORIZONTAL );
@ -275,7 +278,6 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_SIM_MODEL_BASE::onKeyDown ) );
m_useLibraryModelRadioButton->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onRadioButton ), NULL, this );
m_pathLabel->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onLibraryPathLabelUpdate ), NULL, this );
m_libraryPathText->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_SIM_MODEL_BASE::onLibraryPathTextKillFocus ), NULL, this );
@ -317,7 +319,6 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
DIALOG_SIM_MODEL_BASE::~DIALOG_SIM_MODEL_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_SIM_MODEL_BASE::onKeyDown ) );
m_useLibraryModelRadioButton->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SIM_MODEL_BASE::onRadioButton ), NULL, this );
m_pathLabel->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SIM_MODEL_BASE::onLibraryPathLabelUpdate ), NULL, this );
m_libraryPathText->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_SIM_MODEL_BASE::onLibraryPathTextKillFocus ), NULL, this );

View File

@ -56,7 +56,6 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnKeyDown">onKeyDown</event>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer8</property>
@ -64,7 +63,7 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxNotebook" expanded="1">
<property name="BottomDockable">1</property>
@ -1519,11 +1518,11 @@
</object>
</object>
</object>
<object class="notebookpage" expanded="0">
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">Code</property>
<property name="select">0</property>
<object class="wxPanel" expanded="0">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -1574,7 +1573,7 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="0">
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer5</property>
<property name="orient">wxVERTICAL</property>
@ -1717,6 +1716,16 @@
<event name="OnCheckBox">onSaveInValueCheckbox</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="1">
<property name="height">3</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
</object>
</object>
</object>

View File

@ -84,7 +84,6 @@ class DIALOG_SIM_MODEL_BASE : public DIALOG_SHIM
wxButton* m_sdbSizer1Cancel;
// Virtual event handlers, override them in your derived class
virtual void onKeyDown( wxKeyEvent& event ) { event.Skip(); }
virtual void onRadioButton( wxCommandEvent& event ) { event.Skip(); }
virtual void onLibraryPathLabelUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onLibraryPathTextKillFocus( wxFocusEvent& event ) { event.Skip(); }

View File

@ -217,11 +217,16 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
SPICE_ITEM spiceItem;
// This is a little bit dangerous as any value fetched from the fields will not
// be instance-data aware, and will just fetch the value of some random sheet
// (whatever sheet the user happens to be looking at). However, we currently only
// use it to fetch "Sim_*" fields, which have no instance data.
spiceItem.fields = &symbol->GetFields();
for( int i = 0; i < symbol->GetFieldCount(); ++i )
{
spiceItem.fields.emplace_back( VECTOR2I(), i, symbol,
symbol->GetFields()[ i ].GetName() );
if( i == REFERENCE_FIELD )
spiceItem.fields.back().SetText( symbol->GetRef( &sheet ) );
else
spiceItem.fields.back().SetText( symbol->GetFields()[i].GetShownText( 0, false ) );
}
try
{
@ -371,7 +376,7 @@ bool NETLIST_EXPORTER_SPICE::readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aS
void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol,
SPICE_ITEM& aItem )
{
SIM_LIBRARY::MODEL libModel = m_libMgr.CreateModel( aSymbol );
SIM_LIBRARY::MODEL libModel = m_libMgr.CreateModel( &aSheet, aSymbol );
aItem.baseModelName = libModel.name;
aItem.model = &libModel.model;

View File

@ -210,7 +210,12 @@ public:
class IbisComponentPin : public IBIS_INPUT
{
public:
IbisComponentPin( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
IbisComponentPin( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter )
{};
virtual ~IbisComponentPin()
{};
std::string m_pinName;
std::string m_signalName;
@ -232,7 +237,13 @@ public:
class IbisComponentPinMapping : public IBIS_INPUT
{
public:
IbisComponentPinMapping( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
IbisComponentPinMapping( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter )
{};
virtual ~IbisComponentPinMapping()
{};
std::string m_pinName;
std::string m_PDref;
std::string m_PUref;
@ -247,7 +258,13 @@ public:
class IbisDiffPinEntry : public IBIS_INPUT
{
public:
IbisDiffPinEntry( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ), tdelay( aReporter ){};
IbisDiffPinEntry( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter ),
tdelay( aReporter )
{};
virtual ~IbisDiffPinEntry()
{};
std::string pinA;
std::string pinB;
@ -259,7 +276,10 @@ public:
class IbisDiffPin : IBIS_INPUT
{
public:
IbisDiffPin( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
IbisDiffPin( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter )
{};
std::vector<IbisDiffPinEntry> m_entries;
};
@ -267,10 +287,13 @@ class IbisComponent : public IBIS_INPUT
{
public:
IbisComponent( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter ),
m_package( aReporter ),
m_diffPin( aReporter )
{};
IBIS_INPUT( aReporter ),
m_package( aReporter ),
m_diffPin( aReporter )
{};
virtual ~IbisComponent()
{};
std::string m_name = "";
std::string m_manufacturer = "";
@ -297,7 +320,13 @@ public:
class IbisModelSelector : public IBIS_INPUT
{
public:
IbisModelSelector( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
IbisModelSelector( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter )
{};
virtual ~IbisModelSelector()
{};
std::string m_name;
std::vector<IbisModelSelectorEntry> m_models;
@ -308,7 +337,14 @@ public:
class IVtableEntry : public IBIS_INPUT
{
public:
IVtableEntry( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ), I( aReporter ){};
IVtableEntry( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter ),
I( aReporter )
{};
virtual ~IVtableEntry()
{};
double V = 0;
TypMinMaxValue I;
};
@ -317,7 +353,10 @@ public:
class IVtable : public IBIS_INPUT
{
public:
IVtable( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
IVtable( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter )
{};
std::vector<IVtableEntry> m_entries;
bool Check() override;
@ -345,7 +384,7 @@ public:
* @return Multline spice directives
*/
std::string Spice( int aN, std::string aPort1, std::string aPort2, std::string aModelName,
IBIS_CORNER aCorner );
IBIS_CORNER aCorner );
private:
};
@ -353,7 +392,14 @@ private:
class VTtableEntry : public IBIS_INPUT
{
public:
VTtableEntry( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ), V( aReporter ){};
VTtableEntry( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter ),
V( aReporter )
{};
virtual ~VTtableEntry()
{};
double t = 0;
TypMinMaxValue V = 0;
};
@ -361,7 +407,10 @@ public:
class VTtable : public IBIS_INPUT
{
public:
VTtable( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
VTtable( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter )
{};
std::vector<VTtableEntry> m_entries;
};
@ -468,23 +517,27 @@ enum class IBIS_MODEL_POLARITY
class IbisModel : IBIS_INPUT
{
public:
IbisModel( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ),
m_C_comp( aReporter ),
m_voltageRange( aReporter ),
m_temperatureRange( aReporter ),
m_pullupReference( aReporter ),
m_pulldownReference( aReporter ),
m_GNDClampReference( aReporter ),
m_POWERClampReference( aReporter ),
m_Rgnd( aReporter ),
m_Rpower( aReporter ),
m_Rac( aReporter ),
m_Cac( aReporter ),
m_GNDClamp( aReporter ),
m_POWERClamp( aReporter ),
m_pullup( aReporter ),
m_pulldown( aReporter ),
m_ramp( aReporter )
IbisModel( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter ),
m_C_comp( aReporter ),
m_voltageRange( aReporter ),
m_temperatureRange( aReporter ),
m_pullupReference( aReporter ),
m_pulldownReference( aReporter ),
m_GNDClampReference( aReporter ),
m_POWERClampReference( aReporter ),
m_Rgnd( aReporter ),
m_Rpower( aReporter ),
m_Rac( aReporter ),
m_Cac( aReporter ),
m_GNDClamp( aReporter ),
m_POWERClamp( aReporter ),
m_pullup( aReporter ),
m_pulldown( aReporter ),
m_ramp( aReporter )
{};
virtual ~IbisModel()
{};
std::string m_name;
@ -527,7 +580,12 @@ public:
class IbisPackageModel : public IBIS_INPUT
{
public:
IbisPackageModel( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ){};
IbisPackageModel( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter )
{};
virtual ~IbisPackageModel()
{};
std::string m_name;
std::string m_manufacturer;
@ -546,7 +604,13 @@ public:
class IbisFile : public IBIS_INPUT
{
public:
IbisFile( IBIS_REPORTER* aReporter ) : IBIS_INPUT( aReporter ), m_header( aReporter ){};
IbisFile( IBIS_REPORTER* aReporter ) :
IBIS_INPUT( aReporter ),
m_header( aReporter )
{};
virtual ~IbisFile()
{};
IbisHeader m_header;
std::vector<IbisComponent> m_components;

View File

@ -95,9 +95,21 @@ template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, int a
const std::vector<LIB_FIELD>& aFields );
SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( SCH_SYMBOL& aSymbol )
SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const SCH_SHEET_PATH* aSheetPath, SCH_SYMBOL& aSymbol )
{
return CreateModel( aSymbol.GetFields(), static_cast<int>( aSymbol.GetRawPins().size() ) );
std::vector<SCH_FIELD> fields;
for( int i = 0; i < aSymbol.GetFieldCount(); ++i )
{
fields.emplace_back( VECTOR2I(), i, &aSymbol, aSymbol.GetFields()[ i ].GetName() );
if( i == REFERENCE_FIELD )
fields.back().SetText( aSymbol.GetRef( aSheetPath ) );
else
fields.back().SetText( aSymbol.GetFields()[ i ].GetShownText( 0, false ) );
}
return CreateModel( fields, static_cast<int>( aSymbol.GetRawPins().size() ) );
}
template <typename T>
@ -154,10 +166,10 @@ SIM_LIBRARY::MODEL SIM_LIB_MGR::CreateModel( const std::string& aLibraryPath,
if( !baseModel )
{
THROW_IO_ERROR(
wxString::Format( _( "Error loading simulation model: could not find base model '%s' in library '%s'" ),
aBaseModelName,
absolutePath ) );
THROW_IO_ERROR( wxString::Format( _( "Error loading simulation model: could not find "
"base model '%s' in library '%s'" ),
aBaseModelName,
absolutePath ) );
}
m_models.push_back( SIM_MODEL::Create( *baseModel, aSymbolPinCount, aFields ) );

View File

@ -57,7 +57,7 @@ public:
const std::vector<T>& aFields );
// TODO: The argument can be made const.
SIM_LIBRARY::MODEL CreateModel( SCH_SYMBOL& aSymbol );
SIM_LIBRARY::MODEL CreateModel( const SCH_SHEET_PATH* aSheetPath, SCH_SYMBOL& aSymbol );
template <typename T>
SIM_LIBRARY::MODEL CreateModel( const std::vector<T>& aFields, int aSymbolPinCount );

View File

@ -499,8 +499,7 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( TYPE aType, unsigned aSymbolPinCou
}
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel,
unsigned aSymbolPinCount )
std::unique_ptr<SIM_MODEL> SIM_MODEL::Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount )
{
std::unique_ptr<SIM_MODEL> model = Create( aBaseModel.GetType() );

View File

@ -373,8 +373,8 @@ public:
};
std::unique_ptr<SIM_VALUE> value;
const INFO& info;
bool isOtherVariant = false; // Legacy.
const INFO& info;
bool isOtherVariant = false; // Legacy.
PARAM( const INFO& aInfo, bool aIsOtherVariant = false )
: value( SIM_VALUE::Create( aInfo.type ) ),
@ -395,9 +395,9 @@ public:
template <typename T>
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
static std::unique_ptr<SIM_MODEL> Create( TYPE aType, unsigned aSymbolPinCount );
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel,
unsigned aSymbolPinCount );
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount );
template <typename T>
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount,

View File

@ -61,11 +61,11 @@ std::vector<std::string> SPICE_GENERATOR_KIBIS::CurrentNames( const SPICE_ITEM&
std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const std::string aCwd,
const std::string aCacheDir ) const
{
std::string ibisLibFilename = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY::LIBRARY_FIELD );
std::string ibisCompName = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY::NAME_FIELD );
std::string ibisPinName = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY_KIBIS::PIN_FIELD );
std::string ibisModelName = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY_KIBIS::MODEL_FIELD );
bool diffMode = SIM_MODEL::GetFieldValue( aItem.fields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
std::string ibisLibFilename = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY::LIBRARY_FIELD );
std::string ibisCompName = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY::NAME_FIELD );
std::string ibisPinName = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_KIBIS::PIN_FIELD );
std::string ibisModelName = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_KIBIS::MODEL_FIELD );
bool diffMode = SIM_MODEL::GetFieldValue( &aItem.fields, SIM_LIBRARY_KIBIS::DIFF_FIELD ) == "1";
wxFileName libPath = wxFileName( wxString( ibisLibFilename ) );
@ -77,8 +77,7 @@ std::string SPICE_GENERATOR_KIBIS::IbisDevice( const SPICE_ITEM& aItem, const st
if( !kibis.m_valid )
{
THROW_IO_ERROR( wxString::Format( _( "Invalid IBIS file '%s'" ),
ibisLibFilename ) );
THROW_IO_ERROR( wxString::Format( _( "Invalid IBIS file '%s'" ), ibisLibFilename ) );
}
KIBIS_COMPONENT* kcomp = kibis.GetComponent( std::string( ibisCompName ) );
@ -267,7 +266,8 @@ void SIM_MODEL_KIBIS::SwitchSingleEndedDiff( bool aDiff )
}
}
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, const SIM_MODEL_KIBIS& aSource ) : SIM_MODEL_KIBIS( aType )
SIM_MODEL_KIBIS::SIM_MODEL_KIBIS( TYPE aType, const SIM_MODEL_KIBIS& aSource ) :
SIM_MODEL_KIBIS( aType )
{
for( PARAM& param1 : m_params )
{

View File

@ -592,6 +592,7 @@ void SIM_PLOT_FRAME::AddTuner( SCH_SYMBOL* aSymbol )
}
}
void SIM_PLOT_FRAME::UpdateTunerValue( SCH_SYMBOL* aSymbol, const wxString& aValue )
{
for( EDA_ITEM* item : m_schematicFrame->GetScreen()->Items().OfType( SCH_SYMBOL_T ) )
@ -599,7 +600,8 @@ void SIM_PLOT_FRAME::UpdateTunerValue( SCH_SYMBOL* aSymbol, const wxString& aVal
if( item == aSymbol )
{
SIM_LIB_MGR mgr( Prj() );
SIM_MODEL& model = mgr.CreateModel( *aSymbol ).model;
SIM_MODEL& model = mgr.CreateModel( &m_schematicFrame->GetCurrentSheet(),
*aSymbol ).model;
const SIM_MODEL::PARAM* tunerParam = model.GetTunerParam();

View File

@ -22,10 +22,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <confirm.h>
#include <wx/combo.h>
#include <wx/combobox.h>
#include <wx/notebook.h>
// Include simulator headers after wxWidgets headers to avoid conflicts with Windows headers
// (especially on msys2 + wxWidgets 3.0.x)
@ -34,229 +31,11 @@
#include <ki_exception.h>
wxBEGIN_EVENT_TABLE( SIM_VALIDATOR, wxValidator )
EVT_KEY_DOWN( SIM_VALIDATOR::onKeyDown )
wxEND_EVENT_TABLE()
void SIM_VALIDATOR::navigate( int flags )
{
wxWindow* textCtrl = GetWindow();
if( !textCtrl )
return;
wxPropertyGrid* paramGrid = dynamic_cast<wxPropertyGrid*>( textCtrl->GetParent() );
if( !paramGrid )
return;
wxPropertyGridManager* paramGridMgr =
dynamic_cast<wxPropertyGridManager*>( paramGrid->GetParent() );
if( !paramGridMgr )
return;
#ifdef __WXGTK__
// Workaround for wxWindow::Navigate() working differently on GTK. Same workaround is
// in the WxWidgets source code.
if( flags == wxNavigationKeyEvent::IsBackward )
{
if( wxWindow* sibling = paramGridMgr->GetPrevSibling() )
{
sibling->SetFocusFromKbd();
return;
}
}
else if( flags == wxNavigationKeyEvent::IsForward )
{
if( wxWindow* sibling = paramGridMgr->GetNextSibling() )
{
sibling->SetFocusFromKbd();
return;
}
}
// We didn't find the sibling, so instead we try another workaround by by finding the notebook
// we are in, and jumping out of it.
for( wxWindow* window = paramGridMgr; window; window = window->GetParent() )
{
if( wxNotebook* notebook = dynamic_cast<wxNotebook*>( window ) )
{
if( flags == wxNavigationKeyEvent::IsBackward )
{
for( wxWindow* sibling = notebook->GetNextSibling();
sibling;
sibling = sibling->GetNextSibling() )
{
if( sibling->IsFocusable() )
{
sibling->SetFocusFromKbd();
return;
}
}
}
else if( flags == wxNavigationKeyEvent::IsForward )
{
for( wxWindow* sibling = notebook->GetNextSibling();
sibling;
sibling = sibling->GetNextSibling() )
{
if( sibling->IsFocusable() )
{
sibling->SetFocusFromKbd();
return;
}
}
}
}
}
#else
paramGridMgr->Navigate( flags );
#endif
}
void SIM_VALIDATOR::onKeyDown( wxKeyEvent& aEvent )
{
// Because wxPropertyGrid has special handling for the tab key, wxPropertyGrid::DedicateKey()
// and wxPropertyGrid::AddActionTrigger() don't work for it. So instead we translate it to an
// (up or down) arrow key, which has proper handling (select next or previous property) defined
// by the aforementioned functions.
if( aEvent.GetKeyCode() == WXK_TAB )
{
// However, before that, if this is the first or last property, we instead want to navigate
// to the next or previous widget.
wxWindow* textCtrl = GetWindow();
if( !textCtrl )
{
aEvent.Skip();
return;
}
wxPropertyGrid* paramGrid = dynamic_cast<wxPropertyGrid*>( textCtrl->GetParent() );
if( !paramGrid )
{
aEvent.Skip();
return;
}
wxPropertyGridIterator it = paramGrid->GetIterator( wxPG_ITERATE_VISIBLE,
paramGrid->GetSelection() );
if( !it.AtEnd() )
it.Next();
bool isFirst = paramGrid->GetSelection() == paramGrid->wxPropertyGridInterface::GetFirst();
bool isLast = it.AtEnd();
if( isFirst && aEvent.ShiftDown() )
{
navigate( wxNavigationKeyEvent::IsBackward );
return;
}
if( isLast && !aEvent.ShiftDown() )
{
navigate( wxNavigationKeyEvent::IsForward );
return;
}
if( aEvent.GetModifiers() == wxMOD_SHIFT )
{
aEvent.m_shiftDown = false;
aEvent.m_keyCode = WXK_UP;
}
else
aEvent.m_keyCode = WXK_DOWN;
}
aEvent.Skip();
}
wxBEGIN_EVENT_TABLE( SIM_BOOL_VALIDATOR, SIM_VALIDATOR )
wxEND_EVENT_TABLE()
bool SIM_BOOL_VALIDATOR::Validate( wxWindow* aParent )
{
return true;
}
SIM_STRING_VALIDATOR::SIM_STRING_VALIDATOR( SIM_VALUE::TYPE aValueType,
SIM_VALUE_GRAMMAR::NOTATION aNotation )
: SIM_VALIDATOR(),
m_valueType( aValueType ),
m_notation( aNotation )
{
}
wxObject* SIM_STRING_VALIDATOR::Clone() const
{
return new SIM_STRING_VALIDATOR( *this );
}
bool SIM_STRING_VALIDATOR::Validate( wxWindow* aParent )
{
if( !m_validatorWindow->IsEnabled() )
return true;
wxTextEntry* const textEntry = getTextEntry();
if( !textEntry )
return false;
return isValid( textEntry->GetValue() );
}
bool SIM_STRING_VALIDATOR::TransferToWindow()
{
return true;
}
bool SIM_STRING_VALIDATOR::TransferFromWindow()
{
return true;
}
bool SIM_STRING_VALIDATOR::isValid( const wxString& aString )
{
return SIM_VALUE_GRAMMAR::IsValid( aString.ToStdString(), m_valueType, m_notation );
}
wxTextEntry* SIM_STRING_VALIDATOR::getTextEntry()
{
if( !m_validatorWindow )
return nullptr;
// Taken from wxTextValidator.
if( wxDynamicCast( m_validatorWindow, wxTextCtrl ) )
return ( wxTextCtrl* ) m_validatorWindow;
if( wxDynamicCast( m_validatorWindow, wxComboBox ) )
return ( wxComboBox* ) m_validatorWindow;
if( wxDynamicCast( m_validatorWindow, wxComboCtrl ) )
return ( wxComboCtrl* ) m_validatorWindow;
wxFAIL_MSG(
"SIM_STRING_VALIDATOR can only be used with wxTextCtrl, wxComboBox, or wxComboCtrl"
);
return nullptr;
}
SIM_PROPERTY::SIM_PROPERTY( SIM_MODEL& aModel, int aParamIndex ) :
m_model( aModel ),
m_paramIndex( aParamIndex ),
m_needsEval( false ),
m_eval( EDA_UNITS::UNSCALED ),
m_disabled( false )
{
}
@ -269,10 +48,9 @@ void SIM_PROPERTY::Disable()
SIM_BOOL_PROPERTY::SIM_BOOL_PROPERTY( const wxString& aLabel, const wxString& aName,
SIM_MODEL& aModel,
int aParamIndex )
: wxBoolProperty( aLabel, aName ),
SIM_PROPERTY( aModel, aParamIndex )
SIM_MODEL& aModel, int aParamIndex ) :
wxBoolProperty( aLabel, aName ),
SIM_PROPERTY( aModel, aParamIndex )
{
auto simValue = dynamic_cast<SIM_VALUE_INST<bool>*>(
m_model.GetParam( m_paramIndex ).value.get() );
@ -285,7 +63,7 @@ SIM_BOOL_PROPERTY::SIM_BOOL_PROPERTY( const wxString& aLabel, const wxString& aN
wxValidator* SIM_BOOL_PROPERTY::DoGetValidator() const
{
return new SIM_BOOL_VALIDATOR();
return new SIM_VALIDATOR();
}
@ -309,22 +87,73 @@ void SIM_BOOL_PROPERTY::OnSetValue()
SIM_STRING_PROPERTY::SIM_STRING_PROPERTY( const wxString& aLabel, const wxString& aName,
SIM_MODEL& aModel,
int aParamIndex,
SIM_MODEL& aModel, int aParamIndex,
SIM_VALUE::TYPE aValueType,
SIM_VALUE_GRAMMAR::NOTATION aNotation )
: wxStringProperty( aLabel, aName ),
SIM_PROPERTY( aModel, aParamIndex ),
m_valueType( aValueType ),
m_notation( aNotation )
SIM_VALUE_GRAMMAR::NOTATION aNotation ) :
wxStringProperty( aLabel, aName ),
SIM_PROPERTY( aModel, aParamIndex ),
m_valueType( aValueType ),
m_notation( aNotation )
{
SetValueFromString( GetParam().value->ToString() );
}
bool SIM_STRING_PROPERTY::OnEvent( wxPropertyGrid* propgrid, wxWindow* wnd_primary, wxEvent& event )
{
if( event.GetEventType() == wxEVT_SET_FOCUS )
{
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wnd_primary );
if( textEntry )
{
wxString oldStr = m_eval.OriginalText();
if( oldStr.length() && oldStr != textEntry->GetValue() )
{
SetValueInEvent( oldStr );
textEntry->SetValue( oldStr );
}
m_needsEval = true;
return true;
}
}
else if( event.GetEventType() == wxEVT_KILL_FOCUS )
{
wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( wnd_primary );
if( textEntry && m_eval.Process( textEntry->GetValue() ) )
{
SetValueInEvent( m_eval.Result() );
m_needsEval = false;
return true;
}
}
else if( event.GetEventType() == wxEVT_KEY_DOWN )
{
wxKeyEvent& keyEvent = dynamic_cast<wxKeyEvent&>( event );
wxPropertyGrid* propGrid = dynamic_cast<wxPropertyGrid*>( wnd_primary->GetParent() );
if( propGrid )
{
if( keyEvent.GetKeyCode() == WXK_TAB )
{
propGrid->CommitChangesFromEditor();
keyEvent.m_keyCode = keyEvent.ShiftDown() ? WXK_UP : WXK_DOWN;
keyEvent.m_shiftDown = false;
}
}
}
return false;
}
wxValidator* SIM_STRING_PROPERTY::DoGetValidator() const
{
return new SIM_STRING_VALIDATOR( m_valueType, m_notation );
return new SIM_VALIDATOR();
}
@ -334,28 +163,18 @@ bool SIM_STRING_PROPERTY::StringToValue( wxVariant& aVariant, const wxString& aT
if( m_disabled )
return false;
wxString baseParamValue = m_model.GetBaseParam( m_paramIndex ).value->ToString();
aVariant = aText;
wxString evaledText;
// TODO: Don't use string comparison.
if( m_model.GetBaseModel() && ( aText == "" || aText == baseParamValue ) )
{
try
{
m_model.SetParamValue( m_paramIndex, "" ); // Nullify.
}
catch( const IO_ERROR& )
{
return false;
}
aVariant = baseParamValue; // Use the inherited value (if it exists) if null.
}
if( m_needsEval && m_eval.Process( aText ) )
evaledText = m_eval.Result();
else
{
m_model.SetParamValue( m_paramIndex, std::string( aText.ToUTF8() ) );
aVariant = GetParam().value->ToString();
}
evaledText = aText;
wxString baseParamValue = m_model.GetBaseParam( m_paramIndex ).value->ToString();
aVariant = evaledText;
m_model.SetParamValue( m_paramIndex, std::string( evaledText.ToUTF8() ) );
aVariant = GetParam().value->ToString();
return true;
}
@ -373,13 +192,9 @@ static wxArrayString convertStringsToWx( const std::vector<std::string>& aString
SIM_ENUM_PROPERTY::SIM_ENUM_PROPERTY( const wxString& aLabel, const wxString& aName,
SIM_MODEL& aModel,
int aParamIndex,
SIM_VALUE::TYPE aValueType,
SIM_VALUE_GRAMMAR::NOTATION aNotation )
: wxEnumProperty( aLabel, aName,
convertStringsToWx( aModel.GetParam( aParamIndex ).info.enumValues ) ),
SIM_PROPERTY( aModel, aParamIndex )
SIM_MODEL& aModel, int aParamIndex ) :
wxEnumProperty( aLabel, aName, convertStringsToWx( aModel.GetParam( aParamIndex ).info.enumValues ) ),
SIM_PROPERTY( aModel, aParamIndex )
{
auto it = std::find( GetParam().info.enumValues.begin(), GetParam().info.enumValues.end(),
GetParam().value->ToString() );

View File

@ -31,51 +31,15 @@
#include <wx/propgrid/props.h>
#include <sim/sim_model.h>
#include "libeval/numeric_evaluator.h"
class SIM_VALIDATOR : public wxValidator
{
private:
void navigate( int flags );
void onKeyDown( wxKeyEvent& aEvent );
wxDECLARE_EVENT_TABLE();
};
class SIM_STRING_VALIDATOR : public SIM_VALIDATOR
{
public:
SIM_STRING_VALIDATOR( SIM_VALUE::TYPE aValueType, SIM_VALUE_GRAMMAR::NOTATION aNotation );
SIM_STRING_VALIDATOR( const SIM_STRING_VALIDATOR& aValidator ) = default;
wxObject* Clone() const override;
bool Validate( wxWindow* aParent ) override;
bool TransferToWindow() override;
bool TransferFromWindow() override;
private:
bool isValid( const wxString& aString );
wxTextEntry* getTextEntry();
SIM_VALUE::TYPE m_valueType;
SIM_VALUE_GRAMMAR::NOTATION m_notation;
};
class SIM_BOOL_VALIDATOR : public SIM_VALIDATOR
{
public:
SIM_BOOL_VALIDATOR() : SIM_VALIDATOR() {}
SIM_BOOL_VALIDATOR( const SIM_BOOL_VALIDATOR& aValidator ) = default;
bool Validate( wxWindow* aParent ) override;
private:
wxDECLARE_EVENT_TABLE();
bool Validate( wxWindow* aParent ) override { return true; }
bool TransferToWindow() override { return true; }
bool TransferFromWindow() override { return true; }
};
@ -91,7 +55,11 @@ public:
protected:
SIM_MODEL& m_model;
int m_paramIndex;
bool m_disabled; // If true, never access the models.
bool m_needsEval;
mutable NUMERIC_EVALUATOR m_eval;
bool m_disabled; ///< If true, never access the models.
};
@ -124,6 +92,8 @@ public:
bool StringToValue( wxVariant& aVariant, const wxString& aText, int aArgFlags = 0 )
const override;
bool OnEvent( wxPropertyGrid* propgrid, wxWindow* wnd_primary, wxEvent& event ) override;
protected:
SIM_VALUE::TYPE m_valueType;
SIM_VALUE_GRAMMAR::NOTATION m_notation;
@ -133,11 +103,8 @@ protected:
class SIM_ENUM_PROPERTY : public wxEnumProperty, public SIM_PROPERTY
{
public:
SIM_ENUM_PROPERTY( const wxString& aLabel, const wxString& aName,
SIM_MODEL& aModel,
int aParamIndex,
SIM_VALUE::TYPE aValueType = SIM_VALUE::TYPE_FLOAT,
SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SI );
SIM_ENUM_PROPERTY( const wxString& aLabel, const wxString& aName, SIM_MODEL& aModel,
int aParamIndex );
bool IntToValue( wxVariant& aVariant, int aNumber, int aArgFlags = 0 ) const override;
};

View File

@ -482,7 +482,13 @@ bool SIM_VALUE_INT::FromString( const std::string& aString, NOTATION aNotation )
template <>
bool SIM_VALUE_FLOAT::FromString( const std::string& aString, NOTATION aNotation )
{
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString, aNotation );
wxString buf( aString );
// Convert any entered decimal point separators to the one our PEGTL grammar expects
buf.Replace( wxT( "," ), wxT( "." ) );
SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( buf.ToStdString(),
aNotation );
m_value = std::nullopt;
if( !parseResult.isOk )
@ -513,8 +519,7 @@ bool SIM_VALUE_FLOAT::FromString( const std::string& aString, NOTATION aNotation
template <>
bool SIM_VALUE_COMPLEX::FromString( const std::string& aString,
NOTATION aNotation )
bool SIM_VALUE_COMPLEX::FromString( const std::string& aString, NOTATION aNotation )
{
// TODO

View File

@ -32,13 +32,13 @@ class SCH_FIELD;
struct SPICE_ITEM
{
std::string refName;
std::string refName;
std::vector<std::string> pinNumbers;
std::vector<std::string> pinNetNames;
std::string baseModelName;
std::string modelName;
const SIM_MODEL* model = nullptr;
const std::vector<SCH_FIELD>* fields = nullptr;
std::string baseModelName;
std::string modelName;
const SIM_MODEL* model = nullptr;
std::vector<SCH_FIELD> fields;
};

View File

@ -33,7 +33,12 @@ class SIM_LIBRARY_SPICE;
class SPICE_LIBRARY_PARSER
{
public:
SPICE_LIBRARY_PARSER( SIM_LIBRARY_SPICE& aLibrary ) : m_library( aLibrary ) {}
SPICE_LIBRARY_PARSER( SIM_LIBRARY_SPICE& aLibrary ) :
m_library( aLibrary )
{};
virtual ~SPICE_LIBRARY_PARSER()
{};
virtual void ReadFile( const std::string& aFilePath );

View File

@ -866,6 +866,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
{
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
EDA_ITEM* item = selTool->GetNode( aPosition );
SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
if( !item )
return false;
@ -879,10 +880,10 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
std::vector<LIB_PIN*> pins = symbol->GetLibPins();
SIM_LIB_MGR mgr( m_frame->Prj() );
SIM_MODEL& model = mgr.CreateModel( *symbol ).model;
SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol ).model;
SPICE_ITEM spiceItem;
spiceItem.refName = std::string( symbol->GetRef( &m_frame->GetCurrentSheet() ).ToUTF8() );
spiceItem.refName = std::string( symbol->GetRef( &sheet ).ToUTF8() );
std::vector<std::string> currentNames =
model.SpiceGenerator().CurrentNames( spiceItem );

View File

@ -76,7 +76,6 @@ Supported units are millimeters (mm), Mil (mil) and inch (")
// This namespace is used for the lemon parser
namespace numEval
{
struct TokenType
{
union
@ -93,7 +92,7 @@ namespace numEval
class NUMERIC_EVALUATOR
{
enum class Unit { Invalid, MM, CM, Inch, Mil, Degrees };
enum class Unit { Invalid, MM, CM, Inch, Mil, Degrees, SI };
public:
NUMERIC_EVALUATOR( EDA_UNITS aUnits );
@ -162,16 +161,19 @@ private:
struct TokenStat
{
TokenStat() :
input( nullptr ), token( nullptr ), inputLen( 0 ), outputLen( 0 ), pos( 0 )
{ /* empty */ }
input( nullptr ),
token( nullptr ),
inputLen( 0 ),
outputLen( 0 ),
pos( 0 )
{};
const char* input; // current input string ("var=4")
char* token; // output token ("var", type:VAR; "4", type:VALUE)
size_t inputLen; // strlen(input)
size_t outputLen; // At least 64, up to input length
size_t pos; // current index
}
m_token;
} m_token;
char m_localeDecimalSeparator;

View File

@ -36,8 +36,10 @@
#include <string_utils.h>
PCB_PROPERTIES_PANEL::PCB_PROPERTIES_PANEL( wxWindow* aParent, PCB_EDIT_FRAME* aFrame )
: PROPERTIES_PANEL( aParent, aFrame ), m_frame( aFrame ), m_propMgr( PROPERTY_MANAGER::Instance() )
PCB_PROPERTIES_PANEL::PCB_PROPERTIES_PANEL( wxWindow* aParent, PCB_EDIT_FRAME* aFrame ) :
PROPERTIES_PANEL( aParent, aFrame ),
m_frame( aFrame ),
m_propMgr( PROPERTY_MANAGER::Instance() )
{
m_propMgr.Rebuild();
bool found = false;