From b7d41e0e5624e3256e1c6ada2ec001dc2e48bb77 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 5 Dec 2022 02:07:45 +0000 Subject: [PATCH] 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 --- common/libeval/grammar.lemon | 15 +- common/libeval/numeric_evaluator.cpp | 94 +++-- eeschema/dialogs/dialog_sim_model.cpp | 50 +-- eeschema/dialogs/dialog_sim_model.h | 1 - eeschema/dialogs/dialog_sim_model_base.cpp | 7 +- eeschema/dialogs/dialog_sim_model_base.fbp | 19 +- eeschema/dialogs/dialog_sim_model_base.h | 1 - .../netlist_exporter_spice.cpp | 17 +- eeschema/sim/kibis/ibis_parser.h | 130 +++++-- eeschema/sim/sim_lib_mgr.cpp | 24 +- eeschema/sim/sim_lib_mgr.h | 2 +- eeschema/sim/sim_model.cpp | 3 +- eeschema/sim/sim_model.h | 8 +- eeschema/sim/sim_model_kibis.cpp | 16 +- eeschema/sim/sim_plot_frame.cpp | 4 +- eeschema/sim/sim_property.cpp | 341 ++++-------------- eeschema/sim/sim_property.h | 59 +-- eeschema/sim/sim_value.cpp | 11 +- eeschema/sim/spice_generator.h | 10 +- eeschema/sim/spice_library_parser.h | 7 +- eeschema/tools/sch_editor_control.cpp | 5 +- include/libeval/numeric_evaluator.h | 14 +- pcbnew/widgets/pcb_properties_panel.cpp | 6 +- 23 files changed, 380 insertions(+), 464 deletions(-) diff --git a/common/libeval/grammar.lemon b/common/libeval/grammar.lemon index 44516005c1..ae93af0839 100644 --- a/common/libeval/grammar.lemon +++ b/common/libeval/grammar.lemon @@ -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; } diff --git a/common/libeval/numeric_evaluator.cpp b/common/libeval/numeric_evaluator.cpp index aaf243ca97..bcdb8f7a39 100644 --- a/common/libeval/numeric_evaluator.cpp +++ b/common/libeval/numeric_evaluator.cpp @@ -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 ) ) { diff --git a/eeschema/dialogs/dialog_sim_model.cpp b/eeschema/dialogs/dialog_sim_model.cpp index fb06de5b28..69bfba1642 100644 --- a/eeschema/dialogs/dialog_sim_model.cpp +++ b/eeschema/dialogs/dialog_sim_model.cpp @@ -243,6 +243,10 @@ template bool DIALOG_SIM_MODEL::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::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::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::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::getModelPinIndex( const wxString& aModelPinString ) con } -template -void DIALOG_SIM_MODEL::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( focus->GetParent() ) : nullptr; - - if( pg ) - { - pg->CommitChangesFromEditor(); - - aEvent.m_keyCode = aEvent.ShiftDown() ? WXK_UP : WXK_DOWN; - aEvent.m_shiftDown = false; - } - } - - aEvent.Skip(); -} - - template void DIALOG_SIM_MODEL::onRadioButton( wxCommandEvent& aEvent ) { @@ -1187,8 +1168,7 @@ void DIALOG_SIM_MODEL::onTypeChoice( wxCommandEvent& aEvent ) m_libraryModelsMgr.GetModels().at( m_modelNameCombobox->GetSelection() ).get() ); m_libraryModelsMgr.SetModel( m_modelNameCombobox->GetSelection(), - std::make_unique( type, - kibisModel, + std::make_unique( type, kibisModel, m_fields ) ); } diff --git a/eeschema/dialogs/dialog_sim_model.h b/eeschema/dialogs/dialog_sim_model.h index 58213b8d40..e67dffb77c 100644 --- a/eeschema/dialogs/dialog_sim_model.h +++ b/eeschema/dialogs/dialog_sim_model.h @@ -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; diff --git a/eeschema/dialogs/dialog_sim_model_base.cpp b/eeschema/dialogs/dialog_sim_model_base.cpp index 434e9fbcb5..bd3e6b5439 100644 --- a/eeschema/dialogs/dialog_sim_model_base.cpp +++ b/eeschema/dialogs/dialog_sim_model_base.cpp @@ -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 ); diff --git a/eeschema/dialogs/dialog_sim_model_base.fbp b/eeschema/dialogs/dialog_sim_model_base.fbp index f76c53f09c..1023791fd8 100644 --- a/eeschema/dialogs/dialog_sim_model_base.fbp +++ b/eeschema/dialogs/dialog_sim_model_base.fbp @@ -56,7 +56,6 @@ - onKeyDown bSizer8 @@ -64,7 +63,7 @@ none 5 - wxEXPAND|wxTOP|wxRIGHT|wxLEFT + wxEXPAND|wxRIGHT|wxLEFT 1 1 @@ -1519,11 +1518,11 @@ - + Code 0 - + 1 1 1 @@ -1574,7 +1573,7 @@ wxTAB_TRAVERSAL - + bSizer5 wxVERTICAL @@ -1717,6 +1716,16 @@ onSaveInValueCheckbox + + 5 + wxEXPAND + 0 + + 3 + protected + 0 + + diff --git a/eeschema/dialogs/dialog_sim_model_base.h b/eeschema/dialogs/dialog_sim_model_base.h index ca9ea62e20..30d2ae0f95 100644 --- a/eeschema/dialogs/dialog_sim_model_base.h +++ b/eeschema/dialogs/dialog_sim_model_base.h @@ -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(); } diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index 6d4528cc7f..fad5133f33 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -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; diff --git a/eeschema/sim/kibis/ibis_parser.h b/eeschema/sim/kibis/ibis_parser.h index 22092054b6..0b61dd1da6 100644 --- a/eeschema/sim/kibis/ibis_parser.h +++ b/eeschema/sim/kibis/ibis_parser.h @@ -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 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 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 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 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 m_components; diff --git a/eeschema/sim/sim_lib_mgr.cpp b/eeschema/sim/sim_lib_mgr.cpp index eb4b36dca9..80af5e0b58 100644 --- a/eeschema/sim/sim_lib_mgr.cpp +++ b/eeschema/sim/sim_lib_mgr.cpp @@ -95,9 +95,21 @@ template SIM_MODEL& SIM_LIB_MGR::CreateModel( const SIM_MODEL& aBaseModel, int a const std::vector& 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( aSymbol.GetRawPins().size() ) ); + std::vector 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( aSymbol.GetRawPins().size() ) ); } template @@ -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 ) ); diff --git a/eeschema/sim/sim_lib_mgr.h b/eeschema/sim/sim_lib_mgr.h index 3c51eecf49..fe5f49ab17 100644 --- a/eeschema/sim/sim_lib_mgr.h +++ b/eeschema/sim/sim_lib_mgr.h @@ -57,7 +57,7 @@ public: const std::vector& 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 SIM_LIBRARY::MODEL CreateModel( const std::vector& aFields, int aSymbolPinCount ); diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp index d776962a2c..e4aa0f99be 100644 --- a/eeschema/sim/sim_model.cpp +++ b/eeschema/sim/sim_model.cpp @@ -499,8 +499,7 @@ std::unique_ptr SIM_MODEL::Create( TYPE aType, unsigned aSymbolPinCou } -std::unique_ptr SIM_MODEL::Create( const SIM_MODEL& aBaseModel, - unsigned aSymbolPinCount ) +std::unique_ptr SIM_MODEL::Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount ) { std::unique_ptr model = Create( aBaseModel.GetType() ); diff --git a/eeschema/sim/sim_model.h b/eeschema/sim/sim_model.h index a750b78ab9..b2365d4a02 100644 --- a/eeschema/sim/sim_model.h +++ b/eeschema/sim/sim_model.h @@ -373,8 +373,8 @@ public: }; std::unique_ptr 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 static TYPE InferTypeFromLegacyFields( const std::vector& aFields ); + static std::unique_ptr Create( TYPE aType, unsigned aSymbolPinCount ); - static std::unique_ptr Create( const SIM_MODEL& aBaseModel, - unsigned aSymbolPinCount ); + static std::unique_ptr Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount ); template static std::unique_ptr Create( const SIM_MODEL& aBaseModel, unsigned aSymbolPinCount, diff --git a/eeschema/sim/sim_model_kibis.cpp b/eeschema/sim/sim_model_kibis.cpp index b0aa6d9d9a..008cdf6a58 100644 --- a/eeschema/sim/sim_model_kibis.cpp +++ b/eeschema/sim/sim_model_kibis.cpp @@ -61,11 +61,11 @@ std::vector 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 ) { diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp index 796cc9399c..730582769e 100644 --- a/eeschema/sim/sim_plot_frame.cpp +++ b/eeschema/sim/sim_plot_frame.cpp @@ -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(); diff --git a/eeschema/sim/sim_property.cpp b/eeschema/sim/sim_property.cpp index 88f5332456..38057dbf0b 100644 --- a/eeschema/sim/sim_property.cpp +++ b/eeschema/sim/sim_property.cpp @@ -22,10 +22,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include #include -#include -#include // Include simulator headers after wxWidgets headers to avoid conflicts with Windows headers // (especially on msys2 + wxWidgets 3.0.x) @@ -34,229 +31,11 @@ #include -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( textCtrl->GetParent() ); - if( !paramGrid ) - return; - - wxPropertyGridManager* paramGridMgr = - dynamic_cast( 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( 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( 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*>( 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( 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( 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( event ); + wxPropertyGrid* propGrid = dynamic_cast( 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& 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() ); diff --git a/eeschema/sim/sim_property.h b/eeschema/sim/sim_property.h index d256370096..acc3a356db 100644 --- a/eeschema/sim/sim_property.h +++ b/eeschema/sim/sim_property.h @@ -31,51 +31,15 @@ #include #include +#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; }; diff --git a/eeschema/sim/sim_value.cpp b/eeschema/sim/sim_value.cpp index ab5d66b490..bf14eecaac 100644 --- a/eeschema/sim/sim_value.cpp +++ b/eeschema/sim/sim_value.cpp @@ -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 diff --git a/eeschema/sim/spice_generator.h b/eeschema/sim/spice_generator.h index fe9e38b661..b0b47a3356 100644 --- a/eeschema/sim/spice_generator.h +++ b/eeschema/sim/spice_generator.h @@ -32,13 +32,13 @@ class SCH_FIELD; struct SPICE_ITEM { - std::string refName; + std::string refName; std::vector pinNumbers; std::vector pinNetNames; - std::string baseModelName; - std::string modelName; - const SIM_MODEL* model = nullptr; - const std::vector* fields = nullptr; + std::string baseModelName; + std::string modelName; + const SIM_MODEL* model = nullptr; + std::vector fields; }; diff --git a/eeschema/sim/spice_library_parser.h b/eeschema/sim/spice_library_parser.h index 2b5800044c..bfcce2b703 100644 --- a/eeschema/sim/spice_library_parser.h +++ b/eeschema/sim/spice_library_parser.h @@ -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 ); diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index 480ddd19bc..02ab39387a 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -866,6 +866,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent ) { EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); 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 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 currentNames = model.SpiceGenerator().CurrentNames( spiceItem ); diff --git a/include/libeval/numeric_evaluator.h b/include/libeval/numeric_evaluator.h index c211369607..e03ad28a6e 100644 --- a/include/libeval/numeric_evaluator.h +++ b/include/libeval/numeric_evaluator.h @@ -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; diff --git a/pcbnew/widgets/pcb_properties_panel.cpp b/pcbnew/widgets/pcb_properties_panel.cpp index d25d1ac3c5..091ee71d1a 100644 --- a/pcbnew/widgets/pcb_properties_panel.cpp +++ b/pcbnew/widgets/pcb_properties_panel.cpp @@ -36,8 +36,10 @@ #include -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;