Sim: Implement loading Spice library files

Implement parsing and loading Spice libraries into KiCad. This is done
without any involvement of Ngspice -- we create our own in-tree parser
using PEGTL -- because Ngspice doesn't offer any intermediate output we
could plug ourselves into. We don't parse everything -- just the library
content, so this won't be that much effort.

We implement some basic Spice code preview to give the user a hint what
Spice code eir model will correspond to.
This commit is contained in:
Mikolaj Wielgus 2022-04-01 06:30:50 +02:00
parent 978f01553b
commit ce84a48037
32 changed files with 2135 additions and 725 deletions

View File

@ -320,6 +320,8 @@ if( KICAD_SPICE )
sim/sim_plot_panel.cpp sim/sim_plot_panel.cpp
sim/sim_property.cpp sim/sim_property.cpp
sim/sim_workbook.cpp sim/sim_workbook.cpp
sim/sim_library.cpp
sim/sim_library_spice.cpp
sim/sim_model.cpp sim/sim_model.cpp
sim/sim_model_behavioral.cpp sim/sim_model_behavioral.cpp
sim/sim_model_codemodel.cpp sim/sim_model_codemodel.cpp

View File

@ -24,10 +24,12 @@
#include <dialog_spice_model.h> #include <dialog_spice_model.h>
#include <sim/sim_property.h> #include <sim/sim_property.h>
#include <sim/sim_library_spice.h>
#include <widgets/wx_grid.h> #include <widgets/wx_grid.h>
#include <kiplatform/ui.h> #include <kiplatform/ui.h>
#include <confirm.h> #include <confirm.h>
#include <locale_io.h> #include <locale_io.h>
#include <wx/filedlg.h>
using TYPE = SIM_VALUE_BASE::TYPE; using TYPE = SIM_VALUE_BASE::TYPE;
using CATEGORY = SIM_MODEL::PARAM::CATEGORY; using CATEGORY = SIM_MODEL::PARAM::CATEGORY;
@ -42,26 +44,18 @@ DIALOG_SPICE_MODEL<T>::DIALOG_SPICE_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbo
: DIALOG_SPICE_MODEL_BASE( aParent ), : DIALOG_SPICE_MODEL_BASE( aParent ),
m_symbol( aSymbol ), m_symbol( aSymbol ),
m_fields( aFields ), m_fields( aFields ),
m_library( std::make_shared<SIM_LIBRARY_SPICE>() ),
m_prevModel( nullptr ),
m_firstCategory( nullptr ) m_firstCategory( nullptr )
{ {
try try
{ {
SIM_MODEL::TYPE typeFromFields = SIM_MODEL::ReadTypeFromFields( aFields );
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() ) for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
{ {
if( type == typeFromFields )
{
m_models.push_back( SIM_MODEL::Create( type, m_symbol.GetAllPins().size(),
&aFields ) );
m_curModelType = type;
}
else
m_models.push_back( SIM_MODEL::Create( type, m_symbol.GetAllPins().size() ) ); m_models.push_back( SIM_MODEL::Create( type, m_symbol.GetAllPins().size() ) );
SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( type ).deviceType; SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( type ).deviceType;
// By default choose the first model type of each device type.
if( !m_curModelTypeOfDeviceType.count( deviceType ) ) if( !m_curModelTypeOfDeviceType.count( deviceType ) )
m_curModelTypeOfDeviceType[deviceType] = type; m_curModelTypeOfDeviceType[deviceType] = type;
} }
@ -114,21 +108,28 @@ DIALOG_SPICE_MODEL<T>::DIALOG_SPICE_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbo
} }
template <typename T>
bool DIALOG_SPICE_MODEL<T>::TransferDataFromWindow()
{
if( !DIALOG_SPICE_MODEL_BASE::TransferDataFromWindow() )
return false;
getCurModel().WriteFields( m_fields );
return true;
}
template <typename T> template <typename T>
bool DIALOG_SPICE_MODEL<T>::TransferDataToWindow() bool DIALOG_SPICE_MODEL<T>::TransferDataToWindow()
{ {
wxString libraryFilename = SIM_MODEL::GetFieldValue( &m_fields, LIBRARY_FIELD );
if( !libraryFilename.IsEmpty() )
{
// The model is sourced from a library, optionally with instance overrides.
loadLibrary( libraryFilename );
// Must be set before curModel() is used since the latter checks the combobox value.
m_modelNameCombobox->SetStringSelection( SIM_MODEL::GetFieldValue( &m_fields, NAME_FIELD ) );
curModel().ReadDataFields( m_symbol.GetAllPins().size(), &m_fields );
m_overrideCheckbox->SetValue( curModel().HasNonPrincipalOverrides() );
}
else
{
// The model is sourced from the instance.
SIM_MODEL::TYPE type = SIM_MODEL::ReadTypeFromFields( m_fields );
try try
{ {
m_models.at( static_cast<int>( SIM_MODEL::ReadTypeFromFields( m_fields ) ) ) m_models.at( static_cast<int>( SIM_MODEL::ReadTypeFromFields( m_fields ) ) )
@ -140,26 +141,50 @@ bool DIALOG_SPICE_MODEL<T>::TransferDataToWindow()
return DIALOG_SPICE_MODEL_BASE::TransferDataToWindow(); return DIALOG_SPICE_MODEL_BASE::TransferDataToWindow();
} }
m_curModelType = type;
}
updateWidgets(); updateWidgets();
return DIALOG_SPICE_MODEL_BASE::TransferDataToWindow(); return DIALOG_SPICE_MODEL_BASE::TransferDataToWindow();
} }
template <typename T>
bool DIALOG_SPICE_MODEL<T>::TransferDataFromWindow()
{
if( !DIALOG_SPICE_MODEL_BASE::TransferDataFromWindow() )
return false;
if( m_useLibraryModelRadioButton->GetValue() )
{
SIM_MODEL::SetFieldValue( m_fields, NAME_FIELD, m_modelNameCombobox->GetValue() );
SIM_MODEL::SetFieldValue( m_fields, LIBRARY_FIELD, m_library->GetFilename() );
}
curModel().WriteFields( m_fields );
return true;
}
template <typename T> template <typename T>
void DIALOG_SPICE_MODEL<T>::updateWidgets() void DIALOG_SPICE_MODEL<T>::updateWidgets()
{ {
updateModelParamsTab(); updateModelParamsTab();
updateModelCodeTab(); updateModelCodeTab();
updatePinAssignmentsTab(); updatePinAssignmentsTab();
m_prevModel = &curModel();
} }
template <typename T> template <typename T>
void DIALOG_SPICE_MODEL<T>::updateModelParamsTab() void DIALOG_SPICE_MODEL<T>::updateModelParamsTab()
{ {
SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( m_curModelType ).deviceType; if( &curModel() != m_prevModel )
{
SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( curModel().GetType() ).deviceType;
m_deviceTypeChoice->SetSelection( static_cast<int>( deviceType ) ); m_deviceTypeChoice->SetSelection( static_cast<int>( deviceType ) );
m_typeChoice->Clear(); m_typeChoice->Clear();
@ -173,13 +198,14 @@ void DIALOG_SPICE_MODEL<T>::updateModelParamsTab()
if( !description.IsEmpty() ) if( !description.IsEmpty() )
m_typeChoice->Append( description ); m_typeChoice->Append( description );
if( type == m_curModelType ) if( type == curModel().GetType() )
m_typeChoice->SetSelection( m_typeChoice->GetCount() - 1 ); m_typeChoice->SetSelection( m_typeChoice->GetCount() - 1 );
} }
} }
// This wxPropertyGridManager stuff has to be here because it segfaults in the constructor. // This wxPropertyGridManager column and header stuff has to be here because it segfaults in
// the constructor.
m_paramGridMgr->SetColumnCount( static_cast<int>( PARAM_COLUMN::END_ ) ); m_paramGridMgr->SetColumnCount( static_cast<int>( PARAM_COLUMN::END_ ) );
@ -216,24 +242,53 @@ void DIALOG_SPICE_MODEL<T>::updateModelParamsTab()
m_paramGrid->Append( new wxPropertyCategory( "Flags" ) ); m_paramGrid->Append( new wxPropertyCategory( "Flags" ) );
m_paramGrid->HideProperty( "Flags" ); m_paramGrid->HideProperty( "Flags" );
for( const SIM_MODEL::PARAM& param : getCurModel().Params() ) for( int i = 0; i < curModel().GetParamCount(); ++i )
addParamPropertyIfRelevant( param ); addParamPropertyIfRelevant( i );
m_paramGrid->CollapseAll(); m_paramGrid->CollapseAll();
} }
// Either enable all properties or disable all except the principal ones.
for( wxPropertyGridIterator it = m_paramGrid->GetIterator(); !it.AtEnd(); ++it )
{
SIM_PROPERTY* prop = dynamic_cast<SIM_PROPERTY*>( *it );
if( !prop ) // Not all properties are SIM_PROPERTY yet. TODO.
continue;
// Model values other than the currently edited value may have changed. Update them.
// This feature is called "autofill" and present only in certain models. Don't do it for
// models that don't have it for performance reasons.
if( curModel().HasAutofill() )
prop->SetValueFromString( prop->GetParam().value->ToString() );
// Most of the values are disabled when the override checkbox is unchecked.
prop->Enable( m_useInstanceModelRadioButton->GetValue()
|| prop->GetParam().info.category == CATEGORY::PRINCIPAL
|| m_overrideCheckbox->GetValue() );
}
}
template <typename T> template <typename T>
void DIALOG_SPICE_MODEL<T>::updateModelCodeTab() void DIALOG_SPICE_MODEL<T>::updateModelCodeTab()
{ {
wxString modelName = m_modelNameCombobox->GetStringSelection();
if( m_useInstanceModelRadioButton->GetValue() || modelName.IsEmpty() )
modelName = m_fields.at( REFERENCE_FIELD ).GetText();
m_codePreview->SetText( curModel().GenerateSpicePreview( modelName ) );
} }
template <typename T> template <typename T>
void DIALOG_SPICE_MODEL<T>::updatePinAssignmentsTab() void DIALOG_SPICE_MODEL<T>::updatePinAssignmentsTab()
{ {
m_pinAssignmentsGrid->ClearRows(); if( &curModel() == m_prevModel )
return;
m_pinAssignmentsGrid->ClearRows();
std::vector<SCH_PIN*> pinList = m_symbol.GetAllPins(); std::vector<SCH_PIN*> pinList = m_symbol.GetAllPins();
m_pinAssignmentsGrid->AppendRows( static_cast<int>( pinList.size() ) ); m_pinAssignmentsGrid->AppendRows( static_cast<int>( pinList.size() ) );
@ -254,9 +309,9 @@ void DIALOG_SPICE_MODEL<T>::updatePinAssignmentsTab()
"Not Connected" ); "Not Connected" );
} }
for( unsigned int i = 0; i < getCurModel().Pins().size(); ++i ) for( int i = 0; i < curModel().GetPinCount(); ++i )
{ {
int symbolPinNumber = getCurModel().Pins().at( i ).symbolPinNumber; int symbolPinNumber = curModel().GetPin( i ).symbolPinNumber;
if( symbolPinNumber == SIM_MODEL::PIN::NOT_CONNECTED ) if( symbolPinNumber == SIM_MODEL::PIN::NOT_CONNECTED )
continue; continue;
@ -282,9 +337,9 @@ void DIALOG_SPICE_MODEL<T>::updatePinAssignmentsGridEditors()
wxString modelPinChoicesString = ""; wxString modelPinChoicesString = "";
bool isFirst = true; bool isFirst = true;
for( unsigned int i = 0; i < getCurModel().Pins().size(); ++i ) for( int i = 0; i < curModel().GetPinCount(); ++i )
{ {
const SIM_MODEL::PIN& modelPin = getCurModel().Pins().at( i ); const SIM_MODEL::PIN& modelPin = curModel().GetPin( i );
int modelPinNumber = static_cast<int>( i + 1 ); int modelPinNumber = static_cast<int>( i + 1 );
if( modelPin.symbolPinNumber != SIM_MODEL::PIN::NOT_CONNECTED ) if( modelPin.symbolPinNumber != SIM_MODEL::PIN::NOT_CONNECTED )
@ -329,62 +384,78 @@ void DIALOG_SPICE_MODEL<T>::updatePinAssignmentsGridEditors()
template <typename T> template <typename T>
void DIALOG_SPICE_MODEL<T>::addParamPropertyIfRelevant( const SIM_MODEL::PARAM& aParam ) void DIALOG_SPICE_MODEL<T>::loadLibrary( const wxString& aFilePath )
{ {
if( aParam.info.dir == SIM_MODEL::PARAM::DIR::OUT ) m_library->ReadFile( aFilePath );
m_libraryFilenameInput->SetValue( aFilePath );
m_libraryModels.clear();
for( const SIM_MODEL& baseModel : m_library->GetModels() )
m_libraryModels.push_back( SIM_MODEL::Create( baseModel ) );
m_modelNameCombobox->Clear();
for( const wxString& name : m_library->GetModelNames() )
m_modelNameCombobox->Append( name );
m_useLibraryModelRadioButton->SetValue( true );
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::addParamPropertyIfRelevant( int aParamIndex )
{
if( curModel().GetParam( aParamIndex ).info.dir == SIM_MODEL::PARAM::DIR::OUT )
return; return;
switch( aParam.info.category ) switch( curModel().GetParam( aParamIndex ).info.category )
{ {
case CATEGORY::DC: case CATEGORY::DC:
m_paramGrid->HideProperty( "DC", false ); m_paramGrid->HideProperty( "DC", false );
m_paramGrid->AppendIn( "DC", newParamProperty( aParam ) ); m_paramGrid->AppendIn( "DC", newParamProperty( aParamIndex ) );
break; break;
case CATEGORY::CAPACITANCE: case CATEGORY::CAPACITANCE:
m_paramGrid->HideProperty( "Capacitance", false ); m_paramGrid->HideProperty( "Capacitance", false );
m_paramGrid->AppendIn( "Capacitance", newParamProperty( aParam ) ); m_paramGrid->AppendIn( "Capacitance", newParamProperty( aParamIndex ) );
break; break;
case CATEGORY::TEMPERATURE: case CATEGORY::TEMPERATURE:
m_paramGrid->HideProperty( "Temperature", false ); m_paramGrid->HideProperty( "Temperature", false );
m_paramGrid->AppendIn( "Temperature", newParamProperty( aParam ) ); m_paramGrid->AppendIn( "Temperature", newParamProperty( aParamIndex ) );
break; break;
case CATEGORY::NOISE: case CATEGORY::NOISE:
m_paramGrid->HideProperty( "Noise", false ); m_paramGrid->HideProperty( "Noise", false );
m_paramGrid->AppendIn( "Noise", newParamProperty( aParam ) ); m_paramGrid->AppendIn( "Noise", newParamProperty( aParamIndex ) );
break; break;
case CATEGORY::DISTRIBUTED_QUANTITIES: case CATEGORY::DISTRIBUTED_QUANTITIES:
m_paramGrid->HideProperty( "Distributed Quantities", false ); m_paramGrid->HideProperty( "Distributed Quantities", false );
m_paramGrid->AppendIn( "Distributed Quantities", newParamProperty( aParam ) ); m_paramGrid->AppendIn( "Distributed Quantities", newParamProperty( aParamIndex ) );
break; break;
case CATEGORY::GEOMETRY: case CATEGORY::GEOMETRY:
m_paramGrid->HideProperty( "Geometry", false ); m_paramGrid->HideProperty( "Geometry", false );
m_paramGrid->AppendIn( "Geometry", newParamProperty( aParam ) ); m_paramGrid->AppendIn( "Geometry", newParamProperty( aParamIndex ) );
break; break;
case CATEGORY::LIMITING_VALUES: case CATEGORY::LIMITING_VALUES:
m_paramGrid->HideProperty( "Limiting Values", false ); m_paramGrid->HideProperty( "Limiting Values", false );
m_paramGrid->AppendIn( "Limiting Values", newParamProperty( aParam ) ); m_paramGrid->AppendIn( "Limiting Values", newParamProperty( aParamIndex ) );
break; break;
case CATEGORY::ADVANCED: case CATEGORY::ADVANCED:
m_paramGrid->HideProperty( "Advanced", false ); m_paramGrid->HideProperty( "Advanced", false );
m_paramGrid->AppendIn( "Advanced", newParamProperty( aParam ) ); m_paramGrid->AppendIn( "Advanced", newParamProperty( aParamIndex ) );
break; break;
case CATEGORY::FLAGS: case CATEGORY::FLAGS:
m_paramGrid->HideProperty( "Flags", false ); m_paramGrid->HideProperty( "Flags", false );
m_paramGrid->AppendIn( "Flags", newParamProperty( aParam ) ); m_paramGrid->AppendIn( "Flags", newParamProperty( aParamIndex ) );
break; break;
default: default:
//m_paramGrid->AppendIn( nullptr, newParamProperty( aParam ) ); m_paramGrid->Insert( m_firstCategory, newParamProperty( aParamIndex ) );
m_paramGrid->Insert( m_firstCategory, newParamProperty( aParam ) );
//m_paramGrid->Append( newParamProperty( aParam ) );
break; break;
case CATEGORY::INITIAL_CONDITIONS: case CATEGORY::INITIAL_CONDITIONS:
@ -394,46 +465,47 @@ void DIALOG_SPICE_MODEL<T>::addParamPropertyIfRelevant( const SIM_MODEL::PARAM&
} }
template <typename T> template <typename T>
wxPGProperty* DIALOG_SPICE_MODEL<T>::newParamProperty( const SIM_MODEL::PARAM& aParam ) const wxPGProperty* DIALOG_SPICE_MODEL<T>::newParamProperty( int aParamIndex ) const
{ {
const SIM_MODEL::PARAM& param = curModel().GetParam( aParamIndex );
wxString paramDescription = wxString::Format( "%s (%s)", wxString paramDescription = wxString::Format( "%s (%s)",
aParam.info.description, param.info.description,
aParam.info.name ); param.info.name );
wxPGProperty* prop = nullptr; wxPGProperty* prop = nullptr;
switch( aParam.info.type ) switch( param.info.type )
{ {
case TYPE::INT: case TYPE::INT:
prop = new SIM_PROPERTY( paramDescription,aParam.info.name, *aParam.value, prop = new SIM_PROPERTY( paramDescription, param.info.name, m_library, curModelSharedPtr(),
SIM_VALUE_BASE::TYPE::INT ); aParamIndex, SIM_VALUE_BASE::TYPE::INT );
break; break;
case TYPE::FLOAT: case TYPE::FLOAT:
prop = new SIM_PROPERTY( paramDescription,aParam.info.name, *aParam.value, prop = new SIM_PROPERTY( paramDescription, param.info.name, m_library, curModelSharedPtr(),
SIM_VALUE_BASE::TYPE::FLOAT ); aParamIndex, SIM_VALUE_BASE::TYPE::FLOAT );
break; break;
case TYPE::BOOL: case TYPE::BOOL:
prop = new wxBoolProperty( paramDescription, aParam.info.name ); prop = new wxBoolProperty( paramDescription, param.info.name );
prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX, true ); prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX, true );
break; break;
default: default:
prop = new wxStringProperty( paramDescription, aParam.info.name ); prop = new wxStringProperty( paramDescription, param.info.name );
break; break;
} }
prop->SetAttribute( wxPG_ATTR_UNITS, aParam.info.unit ); prop->SetAttribute( wxPG_ATTR_UNITS, param.info.unit );
// Legacy due to the way we extracted the parameters from Ngspice. // Legacy due to the way we extracted the parameters from Ngspice.
if( aParam.isOtherVariant ) if( param.isOtherVariant )
prop->SetCell( 3, aParam.info.defaultValueOfOtherVariant ); prop->SetCell( 3, param.info.defaultValueOfOtherVariant );
else else
prop->SetCell( 3, aParam.info.defaultValue ); prop->SetCell( 3, param.info.defaultValue );
wxString typeStr; wxString typeStr;
switch( aParam.info.type ) switch( param.info.type )
{ {
case TYPE::BOOL: typeStr = wxString( "Bool" ); break; case TYPE::BOOL: typeStr = wxString( "Bool" ); break;
case TYPE::INT: typeStr = wxString( "Int" ); break; case TYPE::INT: typeStr = wxString( "Int" ); break;
@ -448,14 +520,34 @@ wxPGProperty* DIALOG_SPICE_MODEL<T>::newParamProperty( const SIM_MODEL::PARAM& a
prop->SetCell( static_cast<int>( PARAM_COLUMN::TYPE ), typeStr ); prop->SetCell( static_cast<int>( PARAM_COLUMN::TYPE ), typeStr );
if( m_useLibraryModelRadioButton->GetValue()
&& !m_overrideCheckbox->GetValue()
&& param.info.category != SIM_MODEL::PARAM::CATEGORY::PRINCIPAL )
{
prop->Enable( false );
}
return prop; return prop;
} }
template <typename T> template <typename T>
SIM_MODEL& DIALOG_SPICE_MODEL<T>::getCurModel() const SIM_MODEL& DIALOG_SPICE_MODEL<T>::curModel() const
{ {
return *m_models.at( static_cast<int>( m_curModelType ) ); return *curModelSharedPtr();
}
template <typename T>
std::shared_ptr<SIM_MODEL> DIALOG_SPICE_MODEL<T>::curModelSharedPtr() const
{
if( m_useLibraryModelRadioButton->GetValue()
&& m_modelNameCombobox->GetSelection() != wxNOT_FOUND )
{
return m_libraryModels.at( m_modelNameCombobox->GetSelection() );
}
else
return m_models.at( static_cast<int>( m_curModelType ) );
} }
@ -480,7 +572,7 @@ wxString DIALOG_SPICE_MODEL<T>::getSymbolPinString( int symbolPinNumber ) const
template <typename T> template <typename T>
wxString DIALOG_SPICE_MODEL<T>::getModelPinString( int modelPinNumber ) const wxString DIALOG_SPICE_MODEL<T>::getModelPinString( int modelPinNumber ) const
{ {
const wxString& pinName = getCurModel().Pins().at( modelPinNumber - 1 ).name; const wxString& pinName = curModel().GetPin( modelPinNumber - 1 ).name;
LOCALE_IO toggle; LOCALE_IO toggle;
@ -509,6 +601,39 @@ int DIALOG_SPICE_MODEL<T>::getModelPinNumber( const wxString& aModelPinString )
} }
template <typename T>
void DIALOG_SPICE_MODEL<T>::onRadioButton( wxCommandEvent& aEvent )
{
updateWidgets();
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onBrowseButtonClick( wxCommandEvent& aEvent )
{
wxFileDialog dlg( this, _( "Browse Models" ) );
if( dlg.ShowModal() == wxID_CANCEL )
return;
loadLibrary( dlg.GetPath() );
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onModelNameCombobox( wxCommandEvent& aEvent )
{
updateWidgets();
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onOverrideCheckbox( wxCommandEvent& aEvent )
{
updateWidgets();
}
template <typename T> template <typename T>
void DIALOG_SPICE_MODEL<T>::onDeviceTypeChoice( wxCommandEvent& aEvent ) void DIALOG_SPICE_MODEL<T>::onDeviceTypeChoice( wxCommandEvent& aEvent )
{ {
@ -543,6 +668,13 @@ void DIALOG_SPICE_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
} }
template <typename T>
void DIALOG_SPICE_MODEL<T>::onParamGridChanged( wxPropertyGridEvent& aEvent )
{
updateWidgets();
}
template <typename T> template <typename T>
void DIALOG_SPICE_MODEL<T>::onPinAssignmentsGridCellChange( wxGridEvent& aEvent ) void DIALOG_SPICE_MODEL<T>::onPinAssignmentsGridCellChange( wxGridEvent& aEvent )
{ {
@ -552,11 +684,10 @@ void DIALOG_SPICE_MODEL<T>::onPinAssignmentsGridCellChange( wxGridEvent& aEvent
m_pinAssignmentsGrid->GetCellValue( aEvent.GetRow(), aEvent.GetCol() ) ); m_pinAssignmentsGrid->GetCellValue( aEvent.GetRow(), aEvent.GetCol() ) );
if( oldModelPinNumber != SIM_MODEL::PIN::NOT_CONNECTED ) if( oldModelPinNumber != SIM_MODEL::PIN::NOT_CONNECTED )
getCurModel().Pins().at( oldModelPinNumber - 1 ).symbolPinNumber = curModel().SetPinSymbolPinNumber( oldModelPinNumber - 1, SIM_MODEL::PIN::NOT_CONNECTED );
SIM_MODEL::PIN::NOT_CONNECTED;
if( modelPinNumber != SIM_MODEL::PIN::NOT_CONNECTED ) if( modelPinNumber != SIM_MODEL::PIN::NOT_CONNECTED )
getCurModel().Pins().at( modelPinNumber - 1 ).symbolPinNumber = symbolPinNumber; curModel().SetPinSymbolPinNumber( modelPinNumber - 1, symbolPinNumber );
updatePinAssignmentsGridEditors(); updatePinAssignmentsGridEditors();
@ -577,6 +708,48 @@ void DIALOG_SPICE_MODEL<T>::onPinAssignmentsGridSize( wxSizeEvent& aEvent )
} }
template <typename T>
void DIALOG_SPICE_MODEL<T>::onLibraryFilenameInputUpdate( wxUpdateUIEvent& aEvent )
{
aEvent.Enable( m_useLibraryModelRadioButton->GetValue() );
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onBrowseButtonUpdate( wxUpdateUIEvent& aEvent )
{
aEvent.Enable( m_useLibraryModelRadioButton->GetValue() );
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onModelNameComboboxUpdate( wxUpdateUIEvent& aEvent )
{
aEvent.Enable( m_useLibraryModelRadioButton->GetValue() );
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onOverrideCheckboxUpdate( wxUpdateUIEvent& aEvent )
{
aEvent.Enable( m_useLibraryModelRadioButton->GetValue() );
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onDeviceTypeChoiceUpdate( wxUpdateUIEvent& aEvent )
{
aEvent.Enable( m_useInstanceModelRadioButton->GetValue() );
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onTypeChoiceUpdate( wxUpdateUIEvent& aEvent )
{
aEvent.Enable( m_useInstanceModelRadioButton->GetValue() );
}
template <typename T> template <typename T>
void DIALOG_SPICE_MODEL<T>::onSelectionChange( wxPropertyGridEvent& aEvent ) void DIALOG_SPICE_MODEL<T>::onSelectionChange( wxPropertyGridEvent& aEvent )
{ {

View File

@ -30,6 +30,7 @@
#include <scintilla_tricks.h> #include <scintilla_tricks.h>
#include <sim/sim_model.h> #include <sim/sim_model.h>
#include <sim/sim_library.h>
#include <sch_symbol.h> #include <sch_symbol.h>
// Some probable wxWidgets bugs encountered when writing this class: // Some probable wxWidgets bugs encountered when writing this class:
@ -41,14 +42,17 @@ template <typename T>
class DIALOG_SPICE_MODEL : public DIALOG_SPICE_MODEL_BASE class DIALOG_SPICE_MODEL : public DIALOG_SPICE_MODEL_BASE
{ {
public: public:
static constexpr auto LIBRARY_FIELD = "Model_Library";
static constexpr auto NAME_FIELD = "Model_Name";
enum class PARAM_COLUMN : int { DESCRIPTION, VALUE, UNIT, DEFAULT, TYPE, END_ }; enum class PARAM_COLUMN : int { DESCRIPTION, VALUE, UNIT, DEFAULT, TYPE, END_ };
enum class PIN_COLUMN : int { SYMBOL, MODEL }; enum class PIN_COLUMN : int { SYMBOL, MODEL };
DIALOG_SPICE_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbol, std::vector<T>& aSchFields ); DIALOG_SPICE_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbol, std::vector<T>& aSchFields );
private: private:
bool TransferDataFromWindow() override;
bool TransferDataToWindow() override; bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
void updateWidgets(); void updateWidgets();
void updateModelParamsTab(); void updateModelParamsTab();
@ -56,29 +60,50 @@ private:
void updatePinAssignmentsTab(); void updatePinAssignmentsTab();
void updatePinAssignmentsGridEditors(); void updatePinAssignmentsGridEditors();
void addParamPropertyIfRelevant( const SIM_MODEL::PARAM& aParam ); void loadLibrary( const wxString& aFilePath );
wxPGProperty* newParamProperty( const SIM_MODEL::PARAM& aParam ) const;
void addParamPropertyIfRelevant( int aParamIndex );
wxPGProperty* newParamProperty( int aParamIndex ) const;
SIM_MODEL& curModel() const;
std::shared_ptr<SIM_MODEL> curModelSharedPtr() const;
SIM_MODEL& getCurModel() const;
wxString getSymbolPinString( int aSymbolPinNumber ) const; wxString getSymbolPinString( int aSymbolPinNumber ) const;
wxString getModelPinString( int aModelPinNumber ) const; wxString getModelPinString( int aModelPinNumber ) const;
int getModelPinNumber( const wxString& aModelPinString ) const; int getModelPinNumber( const wxString& aModelPinString ) const;
void onRadioButton( wxCommandEvent& aEvent ) override;
void onBrowseButtonClick( wxCommandEvent& aEvent ) override;
void onModelNameCombobox( wxCommandEvent& aEvent ) override;
void onOverrideCheckbox( wxCommandEvent& aEvent ) override;
void onDeviceTypeChoice( wxCommandEvent& aEvent ) override; void onDeviceTypeChoice( wxCommandEvent& aEvent ) override;
void onTypeChoice( wxCommandEvent& aEvent ) override; void onTypeChoice( wxCommandEvent& aEvent ) override;
void onParamGridChanged( wxPropertyGridEvent& aEvent ) override;
void onPinAssignmentsGridCellChange( wxGridEvent& aEvent ) override; void onPinAssignmentsGridCellChange( wxGridEvent& aEvent ) override;
void onPinAssignmentsGridSize( wxSizeEvent& aEvent ) override; void onPinAssignmentsGridSize( wxSizeEvent& aEvent ) override;
void onLibraryFilenameInputUpdate( wxUpdateUIEvent& aEvent ) override;
void onBrowseButtonUpdate( wxUpdateUIEvent& aEvent ) override;
void onModelNameComboboxUpdate( wxUpdateUIEvent& aEvent ) override;
void onOverrideCheckboxUpdate( wxUpdateUIEvent& aEvent ) override;
void onDeviceTypeChoiceUpdate( wxUpdateUIEvent& aEvent ) override;
void onTypeChoiceUpdate( wxUpdateUIEvent& aEvent ) override;
virtual void onSelectionChange( wxPropertyGridEvent& aEvent ); virtual void onSelectionChange( wxPropertyGridEvent& aEvent );
//void onPropertyChanged( wxPropertyGridEvent& aEvent ) override; //void onPropertyChanged( wxPropertyGridEvent& aEvent ) override;
SCH_SYMBOL& m_symbol; SCH_SYMBOL& m_symbol;
std::vector<T>& m_fields; std::vector<T>& m_fields;
std::vector<std::unique_ptr<SIM_MODEL>> m_models; std::vector<std::shared_ptr<SIM_MODEL>> m_models;
std::map<SIM_MODEL::DEVICE_TYPE, SIM_MODEL::TYPE> m_curModelTypeOfDeviceType; std::map<SIM_MODEL::DEVICE_TYPE, SIM_MODEL::TYPE> m_curModelTypeOfDeviceType;
SIM_MODEL::TYPE m_curModelType = SIM_MODEL::TYPE::NONE; SIM_MODEL::TYPE m_curModelType = SIM_MODEL::TYPE::NONE;
std::shared_ptr<SIM_LIBRARY> m_library;
std::vector<std::shared_ptr<SIM_MODEL>> m_libraryModels;
const SIM_MODEL* m_prevModel;
wxPGProperty* m_firstCategory; // Used to add principal parameters to root (any better ideas?) wxPGProperty* m_firstCategory; // Used to add principal parameters to root (any better ideas?)
std::unique_ptr<SCINTILLA_TRICKS> m_scintillaTricks; std::unique_ptr<SCINTILLA_TRICKS> m_scintillaTricks;
}; };

View File

@ -24,31 +24,38 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
bSizer9 = new wxBoxSizer( wxVERTICAL ); bSizer9 = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizer4; wxStaticBoxSizer* sbSizer4;
sbSizer4 = new wxStaticBoxSizer( new wxStaticBox( m_modelPanel, wxID_ANY, wxT("Properties") ), wxVERTICAL ); sbSizer4 = new wxStaticBoxSizer( new wxStaticBox( m_modelPanel, wxID_ANY, wxT("Source") ), wxVERTICAL );
wxFlexGridSizer* fgSizer15; wxFlexGridSizer* fgSizer15;
fgSizer15 = new wxFlexGridSizer( 0, 3, 0, 0 ); fgSizer15 = new wxFlexGridSizer( 0, 4, 0, 0 );
fgSizer15->AddGrowableCol( 1 ); fgSizer15->AddGrowableCol( 2 );
fgSizer15->SetFlexibleDirection( wxBOTH ); fgSizer15->SetFlexibleDirection( wxBOTH );
fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_staticText122 = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, wxT("Model Name:"), wxDefaultPosition, wxDefaultSize, 0 ); m_useInstanceModelRadioButton = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, wxT("Instance"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
m_staticText122->Wrap( -1 ); fgSizer15->Add( m_useInstanceModelRadioButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
fgSizer15->Add( m_staticText122, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_modelName = new wxTextCtrl( sbSizer4->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_useLibraryModelRadioButton = new wxRadioButton( sbSizer4->GetStaticBox(), wxID_ANY, wxT("Library:"), wxDefaultPosition, wxDefaultSize, 0 );
fgSizer15->Add( m_modelName, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 ); fgSizer15->Add( m_useLibraryModelRadioButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_browseButton = new wxButton( sbSizer4->GetStaticBox(), wxID_ANY, wxT("Browse..."), wxDefaultPosition, wxDefaultSize, 0 ); m_libraryFilenameInput = new wxTextCtrl( sbSizer4->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer15->Add( m_browseButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); fgSizer15->Add( m_libraryFilenameInput, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
m_staticText124 = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, wxT("Location:"), wxDefaultPosition, wxDefaultSize, 0 ); m_browseButton = new wxBitmapButton( sbSizer4->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
m_staticText124->Wrap( -1 ); fgSizer15->Add( m_browseButton, 0, wxALL, 5 );
fgSizer15->Add( m_staticText124, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_staticText125 = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, wxT("etc/kicad-sim/diodes.lib"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText125->Wrap( -1 ); fgSizer15->Add( 0, 0, 1, wxEXPAND, 5 );
fgSizer15->Add( m_staticText125, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_modelNameLabel = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, wxT("Model:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT );
m_modelNameLabel->Wrap( -1 );
fgSizer15->Add( m_modelNameLabel, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
m_modelNameCombobox = new wxComboBox( sbSizer4->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
fgSizer15->Add( m_modelNameCombobox, 0, wxALL|wxEXPAND, 5 );
m_overrideCheckbox = new wxCheckBox( sbSizer4->GetStaticBox(), wxID_ANY, wxT("Override"), wxDefaultPosition, wxDefaultSize, 0 );
fgSizer15->Add( m_overrideCheckbox, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
sbSizer4->Add( fgSizer15, 1, wxEXPAND, 5 ); sbSizer4->Add( fgSizer15, 1, wxEXPAND, 5 );
@ -59,9 +66,6 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
wxStaticBoxSizer* sbSizer5; wxStaticBoxSizer* sbSizer5;
sbSizer5 = new wxStaticBoxSizer( new wxStaticBox( m_modelPanel, wxID_ANY, wxT("Model") ), wxVERTICAL ); sbSizer5 = new wxStaticBoxSizer( new wxStaticBox( m_modelPanel, wxID_ANY, wxT("Model") ), wxVERTICAL );
m_checkBox2 = new wxCheckBox( sbSizer5->GetStaticBox(), wxID_ANY, wxT("Change parameters for this symbol"), wxDefaultPosition, wxDefaultSize, 0 );
sbSizer5->Add( m_checkBox2, 0, wxALL, 5 );
m_notebook4 = new wxNotebook( sbSizer5->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); m_notebook4 = new wxNotebook( sbSizer5->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_parametersPanel = new wxPanel( m_notebook4, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_parametersPanel = new wxPanel( m_notebook4, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer12; wxBoxSizer* bSizer12;
@ -226,9 +230,20 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
this->Centre( wxBOTH ); this->Centre( wxBOTH );
// Connect Events // Connect Events
m_useInstanceModelRadioButton->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onRadioButton ), NULL, this );
m_useLibraryModelRadioButton->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onRadioButton ), NULL, this );
m_libraryFilenameInput->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onLibraryFilenameInputUpdate ), NULL, this );
m_browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onBrowseButtonClick ), NULL, this );
m_browseButton->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onBrowseButtonUpdate ), NULL, this );
m_modelNameCombobox->Connect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onModelNameCombobox ), NULL, this );
m_modelNameCombobox->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
m_overrideCheckbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onOverrideCheckbox ), NULL, this );
m_overrideCheckbox->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onOverrideCheckboxUpdate ), NULL, this );
m_deviceTypeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoice ), NULL, this ); m_deviceTypeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
m_deviceTypeChoice->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoiceUpdate ), NULL, this );
m_typeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoice ), NULL, this ); m_typeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoice ), NULL, this );
m_paramGridMgr->Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPropertyChanged ), NULL, this ); m_typeChoice->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoiceUpdate ), NULL, this );
m_paramGridMgr->Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( DIALOG_SPICE_MODEL_BASE::onParamGridChanged ), NULL, this );
m_pinAssignmentsGrid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridCellChange ), NULL, this ); m_pinAssignmentsGrid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridCellChange ), NULL, this );
m_pinAssignmentsGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridSize ), NULL, this ); m_pinAssignmentsGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridSize ), NULL, this );
} }
@ -236,9 +251,20 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
DIALOG_SPICE_MODEL_BASE::~DIALOG_SPICE_MODEL_BASE() DIALOG_SPICE_MODEL_BASE::~DIALOG_SPICE_MODEL_BASE()
{ {
// Disconnect Events // Disconnect Events
m_useInstanceModelRadioButton->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onRadioButton ), NULL, this );
m_useLibraryModelRadioButton->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onRadioButton ), NULL, this );
m_libraryFilenameInput->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onLibraryFilenameInputUpdate ), NULL, this );
m_browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onBrowseButtonClick ), NULL, this );
m_browseButton->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onBrowseButtonUpdate ), NULL, this );
m_modelNameCombobox->Disconnect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onModelNameCombobox ), NULL, this );
m_modelNameCombobox->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onModelNameComboboxUpdate ), NULL, this );
m_overrideCheckbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onOverrideCheckbox ), NULL, this );
m_overrideCheckbox->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onOverrideCheckboxUpdate ), NULL, this );
m_deviceTypeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoice ), NULL, this ); m_deviceTypeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
m_deviceTypeChoice->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoiceUpdate ), NULL, this );
m_typeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoice ), NULL, this ); m_typeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoice ), NULL, this );
m_paramGridMgr->Disconnect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPropertyChanged ), NULL, this ); m_typeChoice->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoiceUpdate ), NULL, this );
m_paramGridMgr->Disconnect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( DIALOG_SPICE_MODEL_BASE::onParamGridChanged ), NULL, this );
m_pinAssignmentsGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridCellChange ), NULL, this ); m_pinAssignmentsGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridCellChange ), NULL, this );
m_pinAssignmentsGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridSize ), NULL, this ); m_pinAssignmentsGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SPICE_MODEL_BASE::onPinAssignmentsGridSize ), NULL, this );

View File

@ -184,7 +184,7 @@
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticBoxSizer" expanded="1"> <object class="wxStaticBoxSizer" expanded="1">
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Properties</property> <property name="label">Source</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">sbSizer4</property> <property name="name">sbSizer4</property>
<property name="orient">wxVERTICAL</property> <property name="orient">wxVERTICAL</property>
@ -195,9 +195,9 @@
<property name="flag">wxEXPAND</property> <property name="flag">wxEXPAND</property>
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="wxFlexGridSizer" expanded="1"> <object class="wxFlexGridSizer" expanded="1">
<property name="cols">3</property> <property name="cols">4</property>
<property name="flexible_direction">wxBOTH</property> <property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1</property> <property name="growablecols">2</property>
<property name="growablerows"></property> <property name="growablerows"></property>
<property name="hgap">0</property> <property name="hgap">0</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
@ -206,11 +206,11 @@
<property name="permission">none</property> <property name="permission">none</property>
<property name="rows">0</property> <property name="rows">0</property>
<property name="vgap">0</property> <property name="vgap">0</property>
<object class="sizeritem" expanded="0"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="0"> <object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
@ -238,8 +238,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Model Name:</property> <property name="label">Instance</property>
<property name="markup">0</property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
@ -247,7 +246,72 @@
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="moveable">1</property> <property name="moveable">1</property>
<property name="name">m_staticText122</property> <property name="name">m_useInstanceModelRadioButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxRB_GROUP</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnRadioButton">onRadioButton</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxRadioButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Library:</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_useLibraryModelRadioButton</property>
<property name="pane_border">1</property> <property name="pane_border">1</property>
<property name="pane_position"></property> <property name="pane_position"></property>
<property name="pane_size"></property> <property name="pane_size"></property>
@ -261,10 +325,15 @@
<property name="subclass">; ; forward_declare</property> <property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property> <property name="toolbar_pane">0</property>
<property name="tooltip"></property> <property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value">0</property>
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<property name="wrap">-1</property> <event name="OnRadioButton">onRadioButton</event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="0"> <object class="sizeritem" expanded="0">
@ -307,7 +376,7 @@
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="moveable">1</property> <property name="moveable">1</property>
<property name="name">m_modelName</property> <property name="name">m_libraryFilenameInput</property>
<property name="pane_border">1</property> <property name="pane_border">1</property>
<property name="pane_position"></property> <property name="pane_position"></property>
<property name="pane_size"></property> <property name="pane_size"></property>
@ -329,13 +398,14 @@
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<event name="OnUpdateUI">onLibraryFilenameInputUpdate</event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="0"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property> <property name="flag">wxALL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxButton" expanded="0"> <object class="wxBitmapButton" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
@ -369,7 +439,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Browse...</property> <property name="label">MyButton</property>
<property name="margins"></property> <property name="margins"></property>
<property name="markup">0</property> <property name="markup">0</property>
<property name="max_size"></property> <property name="max_size"></property>
@ -402,149 +472,151 @@
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
</object> <event name="OnButtonClick">onBrowseButtonClick</event>
</object> <event name="OnUpdateUI">onBrowseButtonUpdate</event>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Location:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText124</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">etc/kicad-sim/diodes.lib</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText125</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</object>
</object>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxEXPAND</property> <property name="flag">wxEXPAND</property>
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="wxStaticBoxSizer" expanded="1"> <object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Model</property> <property name="label">Model:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">sbSizer5</property> <property name="moveable">1</property>
<property name="orient">wxVERTICAL</property> <property name="name">m_modelNameLabel</property>
<property name="parent">1</property> <property name="pane_border">1</property>
<property name="permission">none</property> <property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxALIGN_RIGHT</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALL</property> <property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxComboBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices"></property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_modelNameCombobox</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">-1</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCombobox">onModelNameCombobox</event>
<event name="OnUpdateUI">onModelNameComboboxUpdate</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxCheckBox" expanded="1"> <object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
@ -575,7 +647,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Change parameters for this symbol</property> <property name="label">Override</property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
@ -583,7 +655,7 @@
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="moveable">1</property> <property name="moveable">1</property>
<property name="name">m_checkBox2</property> <property name="name">m_overrideCheckbox</property>
<property name="pane_border">1</property> <property name="pane_border">1</property>
<property name="pane_position"></property> <property name="pane_position"></property>
<property name="pane_size"></property> <property name="pane_size"></property>
@ -604,8 +676,26 @@
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<event name="OnCheckBox">onOverrideCheckbox</event>
<event name="OnUpdateUI">onOverrideCheckboxUpdate</event>
</object> </object>
</object> </object>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxStaticBoxSizer" expanded="1">
<property name="id">wxID_ANY</property>
<property name="label">Model</property>
<property name="minimum_size"></property>
<property name="name">sbSizer5</property>
<property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property> <property name="flag">wxEXPAND | wxALL</property>
@ -863,6 +953,7 @@
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<event name="OnChoice">onDeviceTypeChoice</event> <event name="OnChoice">onDeviceTypeChoice</event>
<event name="OnUpdateUI">onDeviceTypeChoiceUpdate</event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
@ -989,6 +1080,7 @@
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<event name="OnChoice">onTypeChoice</event> <event name="OnChoice">onTypeChoice</event>
<event name="OnUpdateUI">onTypeChoiceUpdate</event>
</object> </object>
</object> </object>
</object> </object>
@ -1051,7 +1143,7 @@
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<event name="OnPropertyGridChanged">onPropertyChanged</event> <event name="OnPropertyGridChanged">onParamGridChanged</event>
<object class="propGridPage" expanded="1"> <object class="propGridPage" expanded="1">
<property name="bitmap"></property> <property name="bitmap"></property>
<property name="label">Page</property> <property name="label">Page</property>

View File

@ -12,19 +12,22 @@
class WX_GRID; class WX_GRID;
#include <wx/string.h> #include <wx/string.h>
#include <wx/stattext.h> #include <wx/radiobut.h>
#include <wx/gdicmn.h> #include <wx/gdicmn.h>
#include <wx/font.h> #include <wx/font.h>
#include <wx/colour.h> #include <wx/colour.h>
#include <wx/settings.h> #include <wx/settings.h>
#include <wx/textctrl.h> #include <wx/textctrl.h>
#include <wx/button.h> #include <wx/bmpbuttn.h>
#include <wx/bitmap.h> #include <wx/bitmap.h>
#include <wx/image.h> #include <wx/image.h>
#include <wx/icon.h> #include <wx/icon.h>
#include <wx/button.h>
#include <wx/stattext.h>
#include <wx/combobox.h>
#include <wx/checkbox.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/statbox.h> #include <wx/statbox.h>
#include <wx/checkbox.h>
#include <wx/choice.h> #include <wx/choice.h>
#include <wx/propgrid/propgrid.h> #include <wx/propgrid/propgrid.h>
#include <wx/propgrid/manager.h> #include <wx/propgrid/manager.h>
@ -49,12 +52,13 @@ class DIALOG_SPICE_MODEL_BASE : public wxDialog
protected: protected:
wxNotebook* m_notebook; wxNotebook* m_notebook;
wxPanel* m_modelPanel; wxPanel* m_modelPanel;
wxStaticText* m_staticText122; wxRadioButton* m_useInstanceModelRadioButton;
wxTextCtrl* m_modelName; wxRadioButton* m_useLibraryModelRadioButton;
wxButton* m_browseButton; wxTextCtrl* m_libraryFilenameInput;
wxStaticText* m_staticText124; wxBitmapButton* m_browseButton;
wxStaticText* m_staticText125; wxStaticText* m_modelNameLabel;
wxCheckBox* m_checkBox2; wxComboBox* m_modelNameCombobox;
wxCheckBox* m_overrideCheckbox;
wxNotebook* m_notebook4; wxNotebook* m_notebook4;
wxPanel* m_parametersPanel; wxPanel* m_parametersPanel;
wxStaticText* m_staticText127; wxStaticText* m_staticText127;
@ -74,9 +78,19 @@ class DIALOG_SPICE_MODEL_BASE : public wxDialog
wxButton* m_sdbSizer1Cancel; wxButton* m_sdbSizer1Cancel;
// Virtual event handlers, override them in your derived class // Virtual event handlers, override them in your derived class
virtual void onRadioButton( wxCommandEvent& event ) { event.Skip(); }
virtual void onLibraryFilenameInputUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onBrowseButtonClick( wxCommandEvent& event ) { event.Skip(); }
virtual void onBrowseButtonUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onModelNameCombobox( wxCommandEvent& event ) { event.Skip(); }
virtual void onModelNameComboboxUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onOverrideCheckbox( wxCommandEvent& event ) { event.Skip(); }
virtual void onOverrideCheckboxUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onDeviceTypeChoice( wxCommandEvent& event ) { event.Skip(); } virtual void onDeviceTypeChoice( wxCommandEvent& event ) { event.Skip(); }
virtual void onDeviceTypeChoiceUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onTypeChoice( wxCommandEvent& event ) { event.Skip(); } virtual void onTypeChoice( wxCommandEvent& event ) { event.Skip(); }
virtual void onPropertyChanged( wxPropertyGridEvent& event ) { event.Skip(); } virtual void onTypeChoiceUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void onParamGridChanged( wxPropertyGridEvent& event ) { event.Skip(); }
virtual void onPinAssignmentsGridCellChange( wxGridEvent& event ) { event.Skip(); } virtual void onPinAssignmentsGridCellChange( wxGridEvent& event ) { event.Skip(); }
virtual void onPinAssignmentsGridSize( wxSizeEvent& event ) { event.Skip(); } virtual void onPinAssignmentsGridSize( wxSizeEvent& event ) { event.Skip(); }

View File

@ -148,6 +148,7 @@ LIB_SYMBOL::LIB_SYMBOL( const LIB_SYMBOL& aSymbol, SYMBOL_LIB* aLibrary ) :
catch( ... ) catch( ... )
{ {
wxFAIL_MSG( "Failed to clone LIB_ITEM." ); wxFAIL_MSG( "Failed to clone LIB_ITEM." );
return;
} }
} }

View File

@ -0,0 +1,43 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* https://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <sim/sim_library.h>
bool SIM_LIBRARY::ReadFile( const wxString& aFilename )
{
m_filename = aFilename;
return true;
}
std::vector<std::reference_wrapper<SIM_MODEL>> SIM_LIBRARY::GetModels()
{
std::vector<std::reference_wrapper<SIM_MODEL>> ret;
for( const std::unique_ptr<SIM_MODEL>& model : m_models )
ret.emplace_back( *model );
return ret;
}

View File

@ -0,0 +1,56 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* https://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef SIM_LIBRARY_H
#define SIM_LIBRARY_H
#include <sim/sim_model.h>
class SIM_LIBRARY
{
public:
virtual ~SIM_LIBRARY() = default;
SIM_LIBRARY() = default;
virtual bool ReadFile( const wxString& aFilename ) = 0;
virtual void WriteFile( const wxString& aFilename ) = 0;
std::vector<std::reference_wrapper<SIM_MODEL>> GetModels();
const std::vector<wxString>& GetModelNames() { return m_modelNames; }
wxString GetFilename() const { return m_filename; }
wxString GetErrorMessage() const { return m_errorMessage; }
protected:
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
std::vector<wxString> m_modelNames;
wxString m_filename;
wxString m_errorMessage;
};
#endif // SIM_LIBRARY_H

View File

@ -0,0 +1,111 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* https://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <sim/sim_library_spice.h>
#include <sim/spice_grammar.h>
#include <locale_io.h>
#include <pegtl.hpp>
#include <pegtl/contrib/parse_tree.hpp>
namespace SIM_LIBRARY_SPICE_PARSER
{
using namespace SPICE_GRAMMAR;
struct unknownLine : until<newline> {};
struct library : star<sor<spiceUnit,
unknownLine>> {};
struct libraryGrammar : must<library, eof> {};
template <typename Rule> struct librarySelector : std::false_type {};
template <> struct librarySelector<modelUnit> : std::true_type {};
template <> struct librarySelector<modelName> : std::true_type {};
// For debugging.
template <> struct librarySelector<unknownLine> : std::true_type {};
};
bool SIM_LIBRARY_SPICE::ReadFile( const wxString& aFilename )
{
if( !SIM_LIBRARY::ReadFile( aFilename ) )
return false;
LOCALE_IO toggle;
tao::pegtl::file_input in( aFilename.ToStdString() );
std::unique_ptr<tao::pegtl::parse_tree::node> root;
try
{
root = tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar,
SIM_LIBRARY_SPICE_PARSER::librarySelector>
( in );
}
catch( tao::pegtl::parse_error& e )
{
m_errorMessage = wxString::Format( "Parsing failed: %s", e.what() );
return false;
}
wxASSERT( root );
for( const auto& node : root->children )
{
if( node->is_type<SIM_LIBRARY_SPICE_PARSER::modelUnit>() )
{
m_models.push_back( SIM_MODEL::Create( node->string() ) );
if( node->children.size() != 1 )
{
m_errorMessage = wxString::Format(
"Captured %d name tokens, expected one", node->children.size() );
return false;
}
m_modelNames.emplace_back( node->children.at( 0 )->string() );
}
else if( node->is_type<SIM_LIBRARY_SPICE_PARSER::unknownLine>() )
{
// Do nothing.
}
else
{
m_errorMessage = wxString::Format( "Unhandled parse tree node: '%s'", node->string() );
return false;
}
}
return true;
}
void SIM_LIBRARY_SPICE::WriteFile( const wxString& aFileName )
{
}

View File

@ -0,0 +1,40 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* https://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef SIM_LIBRARY_SPICE_H
#define SIM_LIBRARY_SPICE_H
#include <sim/sim_library.h>
class SIM_LIBRARY_SPICE : public SIM_LIBRARY
{
// We'll make SIM_LIBRARY have no subclasses probably.
public:
bool ReadFile( const wxString& aFilename ) override;
void WriteFile( const wxString& aFilename ) override;
};
#endif // SIM_LIBRARY_SPICE_H

File diff suppressed because it is too large Load Diff

View File

@ -25,22 +25,46 @@
#ifndef SIM_MODEL_H #ifndef SIM_MODEL_H
#define SIM_MODEL_H #define SIM_MODEL_H
#include <sim/spice_grammar.h>
#include <enum_vector.h> #include <enum_vector.h>
#include <sch_field.h> #include <sch_field.h>
#include <lib_field.h> #include <lib_field.h>
#include <sim/sim_value.h>
#include <wx/string.h> #include <wx/string.h>
#include <map> #include <map>
#include <stdexcept> #include <stdexcept>
class SIM_LIBRARY;
namespace SIM_MODEL_GRAMMAR
{
using namespace SPICE_GRAMMAR;
struct pinNumber : sor<digits, one<'X'>> {};
struct pinSequence : seq<opt<pinNumber,
star<sep,
pinNumber>>> {};
struct pinSequenceGrammar : must<opt<sep>,
pinSequence,
opt<sep>,
eof> {};
template <NOTATION Notation>
struct paramValuePairsGrammar : must<opt<sep>,
paramValuePairs<Notation>,
opt<sep>,
eof> {};
}
class SIM_MODEL class SIM_MODEL
{ {
public: public:
static constexpr auto DEVICE_TYPE_FIELD = "Model_Device"; static constexpr auto DEVICE_TYPE_FIELD = "Model_Device";
static constexpr auto TYPE_FIELD = "Model_Type"; static constexpr auto TYPE_FIELD = "Model_Type";
static constexpr auto FILE_FIELD = "Model_File"; static constexpr auto PINS_FIELD = "Model_Pins";
static constexpr auto PIN_SEQUENCE_FIELD = "Model_Pin_Sequence";
static constexpr auto PARAMS_FIELD = "Model_Params"; static constexpr auto PARAMS_FIELD = "Model_Params";
@ -238,6 +262,17 @@ public:
}; };
struct SPICE_INFO
{
wxString itemType;
wxString typeString = "";
wxString inlineTypeString = "";
int level = 0;
bool hasExpression = false;
wxString version = "";
};
struct PIN struct PIN
{ {
static constexpr auto NOT_CONNECTED = 0; static constexpr auto NOT_CONNECTED = 0;
@ -278,41 +313,52 @@ public:
{ {
wxString name; wxString name;
unsigned int id = 0; // Legacy. unsigned int id = 0; // Legacy.
DIR dir; DIR dir = DIR::INOUT;
SIM_VALUE_BASE::TYPE type; SIM_VALUE_BASE::TYPE type;
FLAGS flags = {}; // Legacy FLAGS flags = {}; // Legacy
wxString unit; wxString unit = "";
CATEGORY category; CATEGORY category = CATEGORY::PRINCIPAL;
wxString defaultValue = ""; wxString defaultValue = "";
wxString defaultValueOfOtherVariant = ""; // Legacy. wxString defaultValueOfOtherVariant = ""; // Legacy.
wxString description; wxString description = "";
}; };
std::unique_ptr<SIM_VALUE_BASE> value; std::unique_ptr<SIM_VALUE_BASE> value;
const INFO& info; const INFO& info;
bool isOtherVariant = false; // Legacy. bool isOtherVariant = false; // Legacy.
PARAM( const INFO& aInfo ) : PARAM( const INFO& aInfo, bool aIsOtherVariant = false )
value( SIM_VALUE_BASE::Create( aInfo.type ) ), : value( SIM_VALUE_BASE::Create( aInfo.type ) ),
info( aInfo ) info( aInfo ),
isOtherVariant( aIsOtherVariant )
{} {}
}; };
static DEVICE_INFO DeviceTypeInfo( DEVICE_TYPE aDeviceType ); static DEVICE_INFO DeviceTypeInfo( DEVICE_TYPE aDeviceType );
static INFO TypeInfo( TYPE aType ); static INFO TypeInfo( TYPE aType );
static SPICE_INFO SpiceInfo( TYPE aType );
static TYPE ReadTypeFromSpiceCode( const std::string& aSpiceCode );
template <typename T> template <typename T>
static TYPE ReadTypeFromFields( const std::vector<T>& aFields ); static TYPE ReadTypeFromFields( const std::vector<T>& aFields );
template <typename T> static std::unique_ptr<SIM_MODEL> Create( TYPE aType, int aSymbolPinCount = 0 );
static std::unique_ptr<SIM_MODEL> Create( int symbolPinCount, const std::vector<T>& aFields ); static std::unique_ptr<SIM_MODEL> Create( const std::string& aSpiceCode );
static std::unique_ptr<SIM_MODEL> Create( const SIM_MODEL& aBaseModel );
template <typename T = void> template <typename T>
static std::unique_ptr<SIM_MODEL> Create( TYPE aType, static std::unique_ptr<SIM_MODEL> Create( int aSymbolPinCount, const std::vector<T>& aFields );
int symbolPinCount,
const std::vector<T>* aFields = nullptr ); template <typename T>
static wxString GetFieldValue( const std::vector<T>* aFields, const wxString& aFieldName );
template <typename T>
static void SetFieldValue( std::vector<T>& aFields, const wxString& aFieldName,
const wxString& aValue );
// Move semantics. // Move semantics.
@ -321,17 +367,17 @@ public:
SIM_MODEL() = delete; SIM_MODEL() = delete;
SIM_MODEL( const SIM_MODEL& aOther ) = delete; SIM_MODEL( const SIM_MODEL& aOther ) = delete;
SIM_MODEL( SIM_MODEL&& aOther ) = default; SIM_MODEL( SIM_MODEL&& aOther ) = default;
SIM_MODEL& operator=(SIM_MODEL&& aOther ) = default; SIM_MODEL& operator=(SIM_MODEL&& aOther ) = delete;
SIM_MODEL( TYPE aType );
virtual bool ReadSpiceCode( const std::string& aSpiceCode );
template <typename T> template <typename T>
void ReadDataFields( int symbolPinCount, const std::vector<T>* aFields ); void ReadDataFields( int aSymbolPinCount, const std::vector<T>* aFields );
// C++ doesn't allow virtual template methods, so we do this: // C++ doesn't allow virtual template methods, so we do this:
virtual void ReadDataSchFields( int symbolPinCount, const std::vector<SCH_FIELD>* aFields ); virtual void ReadDataSchFields( int aSymbolPinCount, const std::vector<SCH_FIELD>* aFields );
virtual void ReadDataLibFields( int symbolPinCount, const std::vector<LIB_FIELD>* aFields ); virtual void ReadDataLibFields( int aSymbolPinCount, const std::vector<LIB_FIELD>* aFields );
template <typename T> template <typename T>
@ -341,46 +387,83 @@ public:
virtual void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ); virtual void WriteDataSchFields( std::vector<SCH_FIELD>& aFields );
virtual void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ); virtual void WriteDataLibFields( std::vector<LIB_FIELD>& aFields );
virtual void WriteCode( wxString& aCode ) = 0;
virtual wxString GenerateSpiceIncludeLine( const wxString& aLibraryFilename ) const;
virtual wxString GenerateSpiceModelLine( const wxString& aModelName ) const;
virtual SPICE_INFO GetSpiceInfo() const;
wxString GenerateSpiceItemLine( const wxString& aRefName, const wxString& aModelName ) const;
virtual wxString GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aPinNetNames ) const;
virtual wxString GenerateSpicePreview( const wxString& aModelName ) const;
TYPE GetType() { return m_type; } void AddParam( const PARAM::INFO& aInfo, bool aIsOtherVariant = false );
virtual wxString GetFile() { return m_file; } TYPE GetType() const { return m_type; }
virtual void SetFile( const wxString& aFile ) { m_file = aFile; }
std::vector<PIN>& Pins() { return m_pins; } const SIM_MODEL* GetBaseModel() const { return m_baseModel; }
std::vector<PARAM>& Params() { return m_params; } void SetBaseModel( const SIM_MODEL& aBaseModel ) { m_baseModel = &aBaseModel; }
int GetPinCount() const { return static_cast<int>( m_pins.size() ); }
const PIN& GetPin( int aIndex ) const { return m_pins.at( aIndex ); }
void SetPinSymbolPinNumber( int aIndex, int aSymbolPinNumber )
{
m_pins.at( aIndex ).symbolPinNumber = aSymbolPinNumber;
}
int GetParamCount() const { return static_cast<int>( m_params.size() ); }
const PARAM& GetParam( int aParamIndex ) const; // Return base parameter unless it's overridden.
const PARAM& GetUnderlyingParam( int aParamIndex ) const; // Return the actual parameter.
const PARAM& GetBaseParam( int aParamIndex ) const; // Always return base parameter if it exists.
virtual bool SetParamValue( int aParamIndex, const wxString& aValue );
bool HasOverrides() const;
bool HasNonPrincipalOverrides() const;
// Can modifying a model parameter also modify other parameters?
virtual bool HasAutofill() const { return false; }
protected:
SIM_MODEL( TYPE aType );
private: private:
TYPE m_type; static std::unique_ptr<SIM_MODEL> create( TYPE aType );
wxString m_file; static TYPE readTypeFromSpiceTypeString( const std::string& aTypeString );
wxString m_spiceCode;
const SIM_MODEL* m_baseModel;
const TYPE m_type;
std::vector<PIN> m_pins; std::vector<PIN> m_pins;
std::vector<PARAM> m_params; std::vector<PARAM> m_params;
template <typename T> template <typename T>
void doReadDataFields( int symbolPinCount, const std::vector<T>* aFields ); void doReadDataFields( int aSymbolPinCount, const std::vector<T>* aFields );
template <typename T> template <typename T>
void doWriteFields( std::vector<T>& aFields ); void doWriteFields( std::vector<T>& aFields );
template <typename T> virtual std::vector<wxString> getPinNames() const { return {}; }
static wxString getFieldValue( const std::vector<T>* aFields, const wxString& aFieldName );
template <typename T> wxString generateDeviceTypeField() const;
static void setFieldValue( std::vector<T>& aFields, const wxString& aFieldName, wxString generateTypeField() const;
const wxString& aValue );
virtual std::vector<wxString> getPinNames() { return {}; } wxString generatePinsField() const;
void parsePinsField( int aSymbolPinCount, const wxString& aPinsField );
wxString generatePinSequence();
void parsePinSequence( int symbolPinCount, const wxString& aPinSequence );
virtual wxString generateParamValuePairs(); wxString generateParamsField( const wxString& aPairSeparator ) const;
virtual void parseParamValuePairs( const wxString& aParamValuePairs ); void parseParamsField( const wxString& aParamsField );
virtual bool setParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue );
}; };
#endif // SIM_MODEL_H #endif // SIM_MODEL_H

View File

@ -23,18 +23,10 @@
*/ */
#include <sim/sim_model_behavioral.h> #include <sim/sim_model_behavioral.h>
#include <locale_io.h>
template SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount, SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType )
const std::vector<void>* aFields );
template SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount,
const std::vector<SCH_FIELD>* aFields );
template SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount,
const std::vector<LIB_FIELD>* aFields );
template <typename T>
SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount,
const std::vector<T>* aFields )
: SIM_MODEL( aType ) : SIM_MODEL( aType )
{ {
static PARAM::INFO resistor = makeParamInfo( "r", "Expression for resistance", "ohm" ); static PARAM::INFO resistor = makeParamInfo( "r", "Expression for resistance", "ohm" );
@ -45,22 +37,62 @@ SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount,
switch( aType ) switch( aType )
{ {
case TYPE::RESISTOR_BEHAVIORAL: Params().emplace_back( resistor ); break; case TYPE::RESISTOR_BEHAVIORAL: AddParam( resistor ); break;
case TYPE::CAPACITOR_BEHAVIORAL: Params().emplace_back( capacitor ); break; case TYPE::CAPACITOR_BEHAVIORAL: AddParam( capacitor ); break;
case TYPE::INDUCTOR_BEHAVIORAL: Params().emplace_back( inductor ); break; case TYPE::INDUCTOR_BEHAVIORAL: AddParam( inductor ); break;
case TYPE::VSOURCE_BEHAVIORAL: Params().emplace_back( vsource ); break; case TYPE::VSOURCE_BEHAVIORAL: AddParam( vsource ); break;
case TYPE::ISOURCE_BEHAVIORAL: Params().emplace_back( isource ); break; case TYPE::ISOURCE_BEHAVIORAL: AddParam( isource ); break;
default: default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_IDEAL" ); wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_IDEAL" );
} }
ReadDataFields( symbolPinCount, aFields );
} }
void SIM_MODEL_BEHAVIORAL::WriteCode( wxString& aCode ) wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceIncludeLine( const wxString& aLibraryFilename ) const
{ {
// TODO return "";
}
wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceModelLine( const wxString& aModelName ) const
{
return "";
}
wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aPinNetNames ) const
{
LOCALE_IO toggle;
switch( GetType() )
{
case TYPE::RESISTOR_BEHAVIORAL:
case TYPE::CAPACITOR_BEHAVIORAL:
case TYPE::INDUCTOR_BEHAVIORAL:
return SIM_MODEL::GenerateSpiceItemLine( aRefName,
GetParam( 0 ).value->ToString(),
aPinNetNames );
case TYPE::VSOURCE_BEHAVIORAL:
return SIM_MODEL::GenerateSpiceItemLine( aRefName,
wxString::Format( "V=%s", GetParam( 0 ).value->ToString() ), aPinNetNames );
case TYPE::ISOURCE_BEHAVIORAL:
return SIM_MODEL::GenerateSpiceItemLine( aRefName,
wxString::Format( "I=%s", GetParam( 0 ).value->ToString() ), aPinNetNames );
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_BEHAVIORAL" );
return "";
}
}
std::vector<wxString> SIM_MODEL_BEHAVIORAL::getPinNames() const
{
return { "+", "-" };
} }

View File

@ -31,12 +31,17 @@
class SIM_MODEL_BEHAVIORAL : public SIM_MODEL class SIM_MODEL_BEHAVIORAL : public SIM_MODEL
{ {
public: public:
template <typename T = void> SIM_MODEL_BEHAVIORAL( TYPE aType );
SIM_MODEL_BEHAVIORAL( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
void WriteCode( wxString& aCode ) override; wxString GenerateSpiceIncludeLine( const wxString& aLibraryFilename ) const override;
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
wxString GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aPinNetNames ) const override;
private: private:
std::vector<wxString> getPinNames() const override;
static PARAM::INFO makeParamInfo( wxString name, wxString description, wxString unit ); static PARAM::INFO makeParamInfo( wxString name, wxString description, wxString unit );
}; };

View File

@ -25,22 +25,7 @@
#include <sim/sim_model_codemodel.h> #include <sim/sim_model_codemodel.h>
template SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount, SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType )
const std::vector<void>* aFields );
template SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount,
const std::vector<SCH_FIELD>* aFields );
template SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount,
const std::vector<LIB_FIELD>* aFields );
template <typename T>
SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount,
const std::vector<T>* aFields )
: SIM_MODEL( aType ) : SIM_MODEL( aType )
{ {
} }
void SIM_MODEL_CODEMODEL::WriteCode( wxString& aCode )
{
// TODO
}

View File

@ -31,10 +31,7 @@
class SIM_MODEL_CODEMODEL : public SIM_MODEL class SIM_MODEL_CODEMODEL : public SIM_MODEL
{ {
public: public:
template <typename T = void> SIM_MODEL_CODEMODEL( TYPE aType );
SIM_MODEL_CODEMODEL( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
void WriteCode( wxString& aCode ) override;
}; };
#endif // SIM_MODEL_CODEMODEL_H #endif // SIM_MODEL_CODEMODEL_H

View File

@ -27,16 +27,7 @@
using PARAM = SIM_MODEL::PARAM; using PARAM = SIM_MODEL::PARAM;
template SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount, SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType )
const std::vector<void>* aFields );
template SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount,
const std::vector<SCH_FIELD>* aFields );
template SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount,
const std::vector<LIB_FIELD>* aFields );
template <typename T>
SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount,
const std::vector<T>* aFields )
: SIM_MODEL( aType ) : SIM_MODEL( aType )
{ {
static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "ohm" ); static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "ohm" );
@ -45,24 +36,37 @@ SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount,
switch( aType ) switch( aType )
{ {
case TYPE::RESISTOR_IDEAL: Params().emplace_back( resistor ); break; case TYPE::RESISTOR_IDEAL: AddParam( resistor ); break;
case TYPE::CAPACITOR_IDEAL: Params().emplace_back( capacitor ); break; case TYPE::CAPACITOR_IDEAL: AddParam( capacitor ); break;
case TYPE::INDUCTOR_IDEAL: Params().emplace_back( inductor ); break; case TYPE::INDUCTOR_IDEAL: AddParam( inductor ); break;
default: default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_IDEAL" ); wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_IDEAL" );
} }
ReadDataFields( symbolPinCount, aFields );
} }
void SIM_MODEL_IDEAL::WriteCode( wxString& aCode ) wxString SIM_MODEL_IDEAL::GenerateSpiceIncludeLine( const wxString& aLibraryFilename ) const
{ {
// TODO return "";
} }
std::vector<wxString> SIM_MODEL_IDEAL::getPinNames() wxString SIM_MODEL_IDEAL::GenerateSpiceModelLine( const wxString& aModelName ) const
{
return "";
}
wxString SIM_MODEL_IDEAL::GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aPinNetNames ) const
{
return SIM_MODEL::GenerateSpiceItemLine( aRefName, GetParam( 0 ).value->ToString(),
aPinNetNames );
}
std::vector<wxString> SIM_MODEL_IDEAL::getPinNames() const
{ {
return { "+", "-" }; return { "+", "-" };
} }

View File

@ -31,13 +31,16 @@
class SIM_MODEL_IDEAL : public SIM_MODEL class SIM_MODEL_IDEAL : public SIM_MODEL
{ {
public: public:
template <typename T = void> SIM_MODEL_IDEAL( TYPE aType );
SIM_MODEL_IDEAL( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
void WriteCode( wxString& aCode ) override; wxString GenerateSpiceIncludeLine( const wxString& aLibraryFilename ) const override;
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
wxString GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aPinNetNames ) const override;
private: private:
std::vector<wxString> getPinNames() override; std::vector<wxString> getPinNames() const override;
static PARAM::INFO makeParamInfo( wxString aName, wxString aDescription, wxString aUnit ); static PARAM::INFO makeParamInfo( wxString aName, wxString aDescription, wxString aUnit );
}; };

View File

@ -27,49 +27,26 @@
using TYPE = SIM_MODEL::TYPE; using TYPE = SIM_MODEL::TYPE;
template SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount, SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType )
const std::vector<void>* aFields );
template SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount,
const std::vector<SCH_FIELD>* aFields );
template SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount,
const std::vector<LIB_FIELD>* aFields );
template <typename T>
SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount,
const std::vector<T>* aFields )
: SIM_MODEL( aType ) : SIM_MODEL( aType )
{ {
const NGSPICE::MODEL_INFO& modelInfo = NGSPICE::ModelInfo( getModelType() ); const NGSPICE::MODEL_INFO& modelInfo = NGSPICE::ModelInfo( getModelType() );
for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.modelParams ) for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.modelParams )
{ AddParam( paramInfo, getIsOtherVariant() );
Params().emplace_back( paramInfo );
Params().back().isOtherVariant = getIsOtherVariant();
}
for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams ) for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams )
{ AddParam( paramInfo, getIsOtherVariant() );
Params().emplace_back( paramInfo );
Params().back().isOtherVariant = getIsOtherVariant();
}
ReadDataFields( symbolPinCount, aFields );
} }
void SIM_MODEL_NGSPICE::WriteCode( wxString& aCode ) std::vector<wxString> SIM_MODEL_NGSPICE::getPinNames() const
{
// TODO
}
std::vector<wxString> SIM_MODEL_NGSPICE::getPinNames()
{ {
return NGSPICE::ModelInfo( getModelType() ).pinNames; return NGSPICE::ModelInfo( getModelType() ).pinNames;
} }
NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType() NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType() const
{ {
switch( GetType() ) switch( GetType() )
{ {

View File

@ -32,15 +32,12 @@
class SIM_MODEL_NGSPICE : public SIM_MODEL class SIM_MODEL_NGSPICE : public SIM_MODEL
{ {
public: public:
template <typename T = void> SIM_MODEL_NGSPICE( TYPE aType );
SIM_MODEL_NGSPICE( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
void WriteCode( wxString& aCode ) override;
private: private:
std::vector<wxString> getPinNames() override; std::vector<wxString> getPinNames() const override;
NGSPICE::MODEL_TYPE getModelType(); NGSPICE::MODEL_TYPE getModelType() const;
bool getIsOtherVariant(); bool getIsOtherVariant();
}; };

View File

@ -23,25 +23,49 @@
*/ */
#include <sim/sim_model_rawspice.h> #include <sim/sim_model_rawspice.h>
#include <pegtl.hpp>
#include <pegtl/contrib/parse_tree.hpp>
template SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount, SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType )
const std::vector<void>* aFields );
template SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount,
const std::vector<SCH_FIELD>* aFields );
template SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount,
const std::vector<LIB_FIELD>* aFields );
template <typename T>
SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount,
const std::vector<T>* aFields )
: SIM_MODEL( aType ) : SIM_MODEL( aType )
{ {
ReadDataFields( symbolPinCount, aFields );
} }
void SIM_MODEL_RAWSPICE::WriteCode( wxString& aCode ) bool SIM_MODEL_RAWSPICE::setParamFromSpiceCode( const wxString& aParamName,
const wxString& aParamValue )
{ {
// TODO int i = 0;
for(; i < GetParamCount(); ++i )
{
if( GetParam( i ).info.name == aParamName.Lower() )
break;
}
if( i == GetParamCount() )
{
// No parameter with this name found. Create a new one.
std::unique_ptr<PARAM::INFO> paramInfo = std::make_unique<PARAM::INFO>();
paramInfo->name = aParamName.Lower();
paramInfo->type = SIM_VALUE_BASE::TYPE::STRING;
m_paramInfos.push_back( std::move( paramInfo ) );
AddParam( *m_paramInfos.back() );
}
try
{
GetParam( i ).value->FromString( wxString( aParamValue ) );
}
catch( KI_PARAM_ERROR& e )
{
// Shouldn't happen since it's TYPE::STRING.
return false;
}
return true;
} }

View File

@ -31,10 +31,14 @@
class SIM_MODEL_RAWSPICE : public SIM_MODEL class SIM_MODEL_RAWSPICE : public SIM_MODEL
{ {
public: public:
template <typename T = void> SIM_MODEL_RAWSPICE( TYPE aType );
SIM_MODEL_RAWSPICE( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
void WriteCode( wxString& aCode ) override; //bool ReadSpiceCode( const std::string& aSpiceCode ) override;
private:
bool setParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue ) override;
std::vector<std::unique_ptr<PARAM::INFO>> m_paramInfos;
}; };
#endif // SIM_MODEL_RAWSPICE_H #endif // SIM_MODEL_RAWSPICE_H

View File

@ -27,21 +27,38 @@
using PARAM = SIM_MODEL::PARAM; using PARAM = SIM_MODEL::PARAM;
template SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount, SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType )
const std::vector<void>* aFields );
template SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount,
const std::vector<SCH_FIELD>* aFields );
template SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount,
const std::vector<LIB_FIELD>* aFields );
template <typename T>
SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount, const std::vector<T>* aFields )
: SIM_MODEL( aType ) : SIM_MODEL( aType )
{ {
for( const PARAM::INFO& paramInfo : makeParams( aType ) ) for( const PARAM::INFO& paramInfo : makeParams( aType ) )
Params().emplace_back( paramInfo ); AddParam( paramInfo );
}
ReadDataFields( symbolPinCount, aFields );
wxString SIM_MODEL_SOURCE::GenerateSpiceIncludeLine( const wxString& aLibraryFilename ) const
{
return "";
}
wxString SIM_MODEL_SOURCE::GenerateSpiceModelLine( const wxString& aModelName ) const
{
return "";
}
wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aPinNetNames ) const
{
wxString argList = "";
for( int i = 0; i < GetParamCount(); ++i )
argList << GetParam( i ).value->ToString() << " ";
wxString model = wxString::Format( GetSpiceInfo().inlineTypeString + "( %s)", argList );
return SIM_MODEL::GenerateSpiceItemLine( aRefName, model, aPinNetNames );
} }
@ -122,9 +139,31 @@ const std::vector<PARAM::INFO>& SIM_MODEL_SOURCE::makeParams( TYPE aType )
} }
void SIM_MODEL_SOURCE::WriteCode( wxString& aCode ) bool SIM_MODEL_SOURCE::SetParamValue( int aParamIndex, const wxString& aValue )
{ {
// TODO // Sources are special. All preceding parameter values must be filled. If they are not, fill
// them out automatically. If a value is nulled, delete everything after it.
if( aValue.IsEmpty() )
{
for( int i = aParamIndex; i < GetParamCount(); ++i )
SIM_MODEL::SetParamValue( i, "" );
}
else
{
for( int i = 0; i < aParamIndex; ++i )
{
if( GetParam( i ).value->ToString().IsEmpty() )
SIM_MODEL::SetParamValue( i, "0" );
}
}
return SIM_MODEL::SetParamValue( aParamIndex, aValue );
}
std::vector<wxString> SIM_MODEL_SOURCE::getPinNames() const
{
return { "+", "-" };
} }

View File

@ -31,12 +31,21 @@
class SIM_MODEL_SOURCE : public SIM_MODEL class SIM_MODEL_SOURCE : public SIM_MODEL
{ {
public: public:
template <typename T = void> SIM_MODEL_SOURCE( TYPE aType );
SIM_MODEL_SOURCE( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
void WriteCode( wxString& aCode ) override; wxString GenerateSpiceIncludeLine( const wxString& aLibraryFilename ) const override;
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
wxString GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aPinNetNames ) const override;
bool SetParamValue( int aParamIndex, const wxString& aValue ) override;
bool HasAutofill() const override { return true; }
private: private:
std::vector<wxString> getPinNames() const override;
static const std::vector<PARAM::INFO>& makeParams( TYPE aType ); static const std::vector<PARAM::INFO>& makeParams( TYPE aType );
static std::vector<PARAM::INFO> makePulse( wxString aPrefix, wxString aUnit ); static std::vector<PARAM::INFO> makePulse( wxString aPrefix, wxString aUnit );

View File

@ -25,23 +25,7 @@
#include <sim/sim_model_subcircuit.h> #include <sim/sim_model_subcircuit.h>
template SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount, SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType )
const std::vector<void>* aFields );
template SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount,
const std::vector<SCH_FIELD>* aFields );
template SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount,
const std::vector<LIB_FIELD>* aFields );
template <typename T>
SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount,
const std::vector<T>* aFields )
: SIM_MODEL( aType ) : SIM_MODEL( aType )
{ {
ReadDataFields( symbolPinCount, aFields );
}
void SIM_MODEL_SUBCIRCUIT::WriteCode( wxString& aCode )
{
// TODO
} }

View File

@ -31,10 +31,7 @@
class SIM_MODEL_SUBCIRCUIT : public SIM_MODEL class SIM_MODEL_SUBCIRCUIT : public SIM_MODEL
{ {
public: public:
template <typename T = void> SIM_MODEL_SUBCIRCUIT( TYPE aType );
SIM_MODEL_SUBCIRCUIT( TYPE aType, int symbolPinCount, const std::vector<T>* aFields = nullptr );
void WriteCode( wxString& aCode ) override;
}; };
#endif // SIM_MODEL_SUBCIRCUIT_H #endif // SIM_MODEL_SUBCIRCUIT_H

View File

@ -38,7 +38,7 @@ wxEND_EVENT_TABLE()
SIM_VALIDATOR::SIM_VALIDATOR( SIM_VALUE_BASE::TYPE aValueType, SIM_VALIDATOR::SIM_VALIDATOR( SIM_VALUE_BASE::TYPE aValueType,
SIM_VALUE_PARSER::NOTATION aNotation ) SIM_VALUE_GRAMMAR::NOTATION aNotation )
: wxValidator(), : wxValidator(),
m_valueType( aValueType ), m_valueType( aValueType ),
m_notation( aNotation ) m_notation( aNotation )
@ -85,7 +85,7 @@ bool SIM_VALIDATOR::TransferFromWindow()
bool SIM_VALIDATOR::isValid( const wxString& aString ) bool SIM_VALIDATOR::isValid( const wxString& aString )
{ {
return SIM_VALUE_PARSER::IsValid( aString, m_valueType, m_notation ); return SIM_VALUE_GRAMMAR::IsValid( aString, m_valueType, m_notation );
} }
@ -151,14 +151,19 @@ void SIM_VALIDATOR::onMouse( wxMouseEvent& aEvent )
SIM_PROPERTY::SIM_PROPERTY( const wxString& aLabel, const wxString& aName, SIM_PROPERTY::SIM_PROPERTY( const wxString& aLabel, const wxString& aName,
SIM_VALUE_BASE& aValue, std::shared_ptr<SIM_LIBRARY> aLibrary,
std::shared_ptr<SIM_MODEL> aModel,
int aParamIndex,
SIM_VALUE_BASE::TYPE aValueType, SIM_VALUE_BASE::TYPE aValueType,
SIM_VALUE_PARSER::NOTATION aNotation ) SIM_VALUE_GRAMMAR::NOTATION aNotation )
: wxStringProperty( aLabel, aName, aValue.ToString() ), : wxStringProperty( aLabel, aName ),
m_valueType( aValueType ), m_valueType( aValueType ),
m_notation( aNotation ), m_notation( aNotation ),
m_value( aValue ) m_library( aLibrary ),
m_model( aModel ),
m_paramIndex( aParamIndex )
{ {
SetValueFromString( GetParam().value->ToString() );
} }
@ -172,7 +177,19 @@ bool SIM_PROPERTY::StringToValue( wxVariant& aVariant, const wxString& aText, in
{ {
try try
{ {
m_value.FromString( aText ); wxString paramValueStr = m_model->GetBaseParam( m_paramIndex ).value->ToString();
// TODO: Don't use string comparison.
if( m_model->GetBaseModel() && ( aText.IsEmpty() || aText == paramValueStr ) )
{
m_model->SetParamValue( m_paramIndex, "" ); // Nullify.
aVariant = paramValueStr; // Use the inherited value (if it exists) if null.
}
else
{
m_model->SetParamValue( m_paramIndex, aText );
aVariant = GetParam().value->ToString();
}
} }
catch( KI_PARAM_ERROR& e ) catch( KI_PARAM_ERROR& e )
{ {
@ -180,6 +197,5 @@ bool SIM_PROPERTY::StringToValue( wxVariant& aVariant, const wxString& aText, in
return false; return false;
} }
aVariant = m_value.ToString();
return true; return true;
} }

View File

@ -25,14 +25,14 @@
#ifndef SIM_PROPERTY_H #ifndef SIM_PROPERTY_H
#define SIM_PROPERTY_H #define SIM_PROPERTY_H
#include <sim/sim_value.h> #include <sim/sim_model.h>
#include <wx/propgrid/props.h> #include <wx/propgrid/props.h>
class SIM_VALIDATOR : public wxValidator class SIM_VALIDATOR : public wxValidator
{ {
public: public:
SIM_VALIDATOR( SIM_VALUE_BASE::TYPE aValueType, SIM_VALUE_PARSER::NOTATION aNotation ); SIM_VALIDATOR( SIM_VALUE_BASE::TYPE aValueType, SIM_VALUE_GRAMMAR::NOTATION aNotation );
SIM_VALIDATOR( const SIM_VALIDATOR& aValidator ) = default; SIM_VALIDATOR( const SIM_VALIDATOR& aValidator ) = default;
wxObject* Clone() const override; wxObject* Clone() const override;
@ -51,7 +51,7 @@ private:
void onMouse( wxMouseEvent& aEvent ); void onMouse( wxMouseEvent& aEvent );
SIM_VALUE_BASE::TYPE m_valueType; SIM_VALUE_BASE::TYPE m_valueType;
SIM_VALUE_PARSER::NOTATION m_notation; SIM_VALUE_GRAMMAR::NOTATION m_notation;
wxString m_prevText; wxString m_prevText;
long m_prevInsertionPoint; long m_prevInsertionPoint;
@ -62,19 +62,28 @@ private:
class SIM_PROPERTY : public wxStringProperty class SIM_PROPERTY : public wxStringProperty
{ {
public: public:
SIM_PROPERTY( const wxString& aLabel, const wxString& aName, SIM_VALUE_BASE& aValue, // We pass shared_ptrs because we need to make sure they are destroyed only after the last time
// SIM_PROPERTY uses them.
SIM_PROPERTY( const wxString& aLabel, const wxString& aName,
std::shared_ptr<SIM_LIBRARY> aLibrary,
std::shared_ptr<SIM_MODEL> aModel,
int aParamIndex,
SIM_VALUE_BASE::TYPE aValueType = SIM_VALUE_BASE::TYPE::FLOAT, SIM_VALUE_BASE::TYPE aValueType = SIM_VALUE_BASE::TYPE::FLOAT,
SIM_VALUE_PARSER::NOTATION aNotation = SIM_VALUE_PARSER::NOTATION::SI ); SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SI );
wxValidator* DoGetValidator() const override; wxValidator* DoGetValidator() const override;
bool StringToValue( wxVariant& aVariant, const wxString& aText, int aArgFlags = 0 ) bool StringToValue( wxVariant& aVariant, const wxString& aText, int aArgFlags = 0 )
const override; const override;
const SIM_MODEL::PARAM& GetParam() const { return m_model->GetParam( m_paramIndex ); }
protected: protected:
SIM_VALUE_BASE::TYPE m_valueType; SIM_VALUE_BASE::TYPE m_valueType;
SIM_VALUE_PARSER::NOTATION m_notation; SIM_VALUE_GRAMMAR::NOTATION m_notation;
SIM_VALUE_BASE& m_value; std::shared_ptr<SIM_LIBRARY> m_library;
std::shared_ptr<SIM_MODEL> m_model;
int m_paramIndex;
}; };
#endif // SIM_PROPERTY_H #endif // SIM_PROPERTY_H

View File

@ -71,13 +71,56 @@
} }
namespace SIM_VALUE_PARSER
{
using namespace SIM_VALUE_GRAMMAR;
template <typename Rule>
struct numberSelector : std::false_type {};
template <> struct numberSelector<SIM_VALUE_GRAMMAR::significand<SIM_VALUE_BASE::TYPE::INT>>
: std::true_type {};
template <> struct numberSelector<SIM_VALUE_GRAMMAR::significand<SIM_VALUE_BASE::TYPE::FLOAT>>
: std::true_type {};
template <> struct numberSelector<intPart> : std::true_type {};
template <> struct numberSelector<fracPart> : std::true_type {};
template <> struct numberSelector<exponent> : std::true_type {};
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::INT, NOTATION::SI>>
: std::true_type {};
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::INT, NOTATION::SPICE>>
: std::true_type {};
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SI>>
: std::true_type {};
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SPICE>>
: std::true_type {};
struct PARSE_RESULT
{
bool isEmpty = true;
std::string significand;
OPT<long> intPart;
OPT<long> fracPart;
OPT<long> exponent;
OPT<long> metricSuffixExponent;
};
PARSE_RESULT Parse( const wxString& aString,
SIM_VALUE_BASE::TYPE aValueType = SIM_VALUE_BASE::TYPE::FLOAT,
NOTATION aNotation = NOTATION::SI );
long MetricSuffixToExponent( std::string aMetricSuffix, NOTATION aNotation = NOTATION::SI );
wxString ExponentToMetricSuffix( double aExponent, long& aReductionExponent,
NOTATION aNotation = NOTATION::SI );
}
template <SIM_VALUE_BASE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation> template <SIM_VALUE_BASE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
static inline void doIsValid( tao::pegtl::string_input<>& aIn ) static inline void doIsValid( tao::pegtl::string_input<>& aIn )
{ {
tao::pegtl::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>>( aIn ); tao::pegtl::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>>( aIn );
} }
bool SIM_VALUE_PARSER::IsValid( const wxString& aString, bool SIM_VALUE_GRAMMAR::IsValid( const wxString& aString,
SIM_VALUE_BASE::TYPE aValueType, SIM_VALUE_BASE::TYPE aValueType,
NOTATION aNotation ) NOTATION aNotation )
{ {
@ -163,8 +206,10 @@ SIM_VALUE_PARSER::PARSE_RESULT SIM_VALUE_PARSER::Parse( const wxString& aString,
try try
{ {
for( const auto& node : root->children ) for( const auto& node : root->children )
{
CALL_INSTANCE( aValueType, aNotation, handleNodeForParse, *node, result ); CALL_INSTANCE( aValueType, aNotation, handleNodeForParse, *node, result );
} }
}
catch( std::invalid_argument& e ) catch( std::invalid_argument& e )
{ {
throw KI_PARAM_ERROR( wxString::Format( _( "Failed to parse '%s': %s" ), aString, throw KI_PARAM_ERROR( wxString::Format( _( "Failed to parse '%s': %s" ), aString,
@ -482,14 +527,19 @@ wxString SIM_VALUE<long>::ToString() const
if( m_value.has_value() ) if( m_value.has_value() )
{ {
double exponent = std::log10( *m_value ); long value = *m_value;
long reductionExponent = 0; long exponent = 0;
wxString metricSuffix = SIM_VALUE_PARSER::ExponentToMetricSuffix( exponent, while( value % 1000 == 0 )
reductionExponent ); {
long reducedValue = *m_value / static_cast<long>( std::pow( 10, reductionExponent ) ); exponent += 3;
value /= 1000;
}
return wxString::Format( "%d%s", reducedValue, metricSuffix ); long dummy = 0;
wxString metricSuffix = SIM_VALUE_PARSER::ExponentToMetricSuffix(
static_cast<double>( exponent ), dummy );
return wxString::Format( "%d%s", value, metricSuffix );
} }
return ""; return "";

View File

@ -86,7 +86,7 @@ private:
}; };
namespace SIM_VALUE_PARSER namespace SIM_VALUE_GRAMMAR
{ {
using namespace tao::pegtl; using namespace tao::pegtl;
@ -100,7 +100,6 @@ namespace SIM_VALUE_PARSER
wxString allowedIntChars; wxString allowedIntChars;
struct spaces : plus<space> {};
struct digits : plus<tao::pegtl::digit> {}; // For some reason it fails on just "digit". struct digits : plus<tao::pegtl::digit> {}; // For some reason it fails on just "digit".
struct sign : one<'+', '-'> {}; struct sign : one<'+', '-'> {};
@ -165,43 +164,9 @@ namespace SIM_VALUE_PARSER
struct numberGrammar : must<opt<number<ValueType, Notation>>, eof> {}; struct numberGrammar : must<opt<number<ValueType, Notation>>, eof> {};
template <typename Rule>
struct numberSelector : std::false_type {};
template <> struct numberSelector<significand<SIM_VALUE_BASE::TYPE::INT>> : std::true_type {};
template <> struct numberSelector<significand<SIM_VALUE_BASE::TYPE::FLOAT>> : std::true_type {};
template <> struct numberSelector<intPart> : std::true_type {};
template <> struct numberSelector<fracPart> : std::true_type {};
template <> struct numberSelector<exponent> : std::true_type {};
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::INT, NOTATION::SI>>
: std::true_type {};
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::INT, NOTATION::SPICE>>
: std::true_type {};
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SI>>
: std::true_type {};
template <> struct numberSelector<metricSuffix<SIM_VALUE_BASE::TYPE::FLOAT, NOTATION::SPICE>>
: std::true_type {};
struct PARSE_RESULT
{
bool isEmpty = true;
std::string significand;
OPT<long> intPart;
OPT<long> fracPart;
OPT<long> exponent;
OPT<long> metricSuffixExponent;
};
bool IsValid( const wxString& aString, bool IsValid( const wxString& aString,
SIM_VALUE_BASE::TYPE aValueType = SIM_VALUE_BASE::TYPE::FLOAT, SIM_VALUE_BASE::TYPE aValueType = SIM_VALUE_BASE::TYPE::FLOAT,
NOTATION aNotation = NOTATION::SI ); NOTATION aNotation = NOTATION::SI );
PARSE_RESULT Parse( const wxString& aString,
SIM_VALUE_BASE::TYPE aValueType = SIM_VALUE_BASE::TYPE::FLOAT,
NOTATION aNotation = NOTATION::SI );
long MetricSuffixToExponent( std::string aMetricSuffix, NOTATION aNotation = NOTATION::SI );
wxString ExponentToMetricSuffix( double aExponent, long& aReductionExponent,
NOTATION aNotation = NOTATION::SI );
} }
#endif // SIM_VALUE_H #endif // SIM_VALUE_H

View File

@ -0,0 +1,156 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Mikolaj Wielgus
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* https://www.gnu.org/licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef SPICE_GRAMMAR_H
#define SPICE_GRAMMAR_H
#include <sim/sim_value.h>
namespace SPICE_GRAMMAR
{
using namespace SIM_VALUE_GRAMMAR;
struct eolComment : seq<one<';'>, until<eol>> {};
struct commentLine : seq<one<'*', ';'>, until<eol>> {};
struct linespaces : plus<not_at<eol>,
space> {};
struct newline : seq<sor<eol,
eolComment>,
not_at<one<'+'>>> {};
struct continuation : seq<opt<linespaces>,
sor<eol,
eolComment>,
star<commentLine>,
one<'+'>,
opt<linespaces>> {};
struct sep : sor<continuation,
linespaces> {};
struct param : plus<alnum> {};
template <SIM_VALUE_BASE::TYPE Type, NOTATION Notation>
struct paramValuePair : seq<param,
opt<sep>,
one<'='>,
opt<sep>,
number<Type, Notation>> {};
template <NOTATION Notation>
struct paramValuePairs : seq<opt<paramValuePair<SIM_VALUE_BASE::TYPE::FLOAT,
Notation>,
star<sep,
paramValuePair<SIM_VALUE_BASE::TYPE::FLOAT,
Notation>>>> {};
struct modelName : plus<alnum,
star<sor<alnum,
one<'!', '#', '$', '%', '[', ']', '_'>>>> {};
/*seq<alpha,
star<sor<alnum,
one<'!', '#', '$', '%', '[', ']', '_'>>>> {};*/
struct dotModelType : sor<TAO_PEGTL_ISTRING( "R" ),
TAO_PEGTL_ISTRING( "C" ),
TAO_PEGTL_ISTRING( "L" ),
TAO_PEGTL_ISTRING( "SW" ),
TAO_PEGTL_ISTRING( "CSW" ),
TAO_PEGTL_ISTRING( "URC" ),
TAO_PEGTL_ISTRING( "LTRA" ),
TAO_PEGTL_ISTRING( "D" ),
TAO_PEGTL_ISTRING( "NPN" ),
TAO_PEGTL_ISTRING( "PNP" ),
TAO_PEGTL_ISTRING( "NJF" ),
TAO_PEGTL_ISTRING( "PJF" ),
TAO_PEGTL_ISTRING( "NMOS" ),
TAO_PEGTL_ISTRING( "PMOS" ),
TAO_PEGTL_ISTRING( "NMF" ),
TAO_PEGTL_ISTRING( "PMF" ),
TAO_PEGTL_ISTRING( "VDMOS" )> {};
struct dotModel : seq<opt<sep>,
TAO_PEGTL_ISTRING( ".model" ),
sep,
modelName,
sep,
dotModelType,
sor<seq<opt<sep>,
one<'('>,
opt<sep>,
paramValuePairs<NOTATION::SPICE>,
opt<sep>,
// Ngspice doesn't require the parentheses to match, though.
one<')'>>,
seq<sep,
paramValuePairs<NOTATION::SPICE>>>,
opt<sep>,
newline> {};
struct dotSubcktPinNumber : digits {};
struct dotSubcktPinSequence : seq<opt<sep>,
opt<dotSubcktPinNumber,
star<sep,
dotSubcktPinNumber>>,
opt<sep>> {};
struct dotSubcktEnd : seq<TAO_PEGTL_ISTRING( ".ends" ),
opt<sep>,
newline> {};
struct dotSubckt : seq<opt<sep>,
TAO_PEGTL_ISTRING( ".subckt" ),
sep,
modelName,
sep,
dotSubcktPinSequence,
opt<sep>,
newline,
until<dotSubcktEnd>> {};
struct modelUnit : sor<dotModel,
dotSubckt> {};
struct dotLine : seq<opt<sep>,
one<'.'>,
until<newline>> {};
struct unknownLine : until<newline> {};
struct spiceUnit : sor<modelUnit,
dotLine,
unknownLine> {};
struct spiceUnitGrammar : must<spiceUnit, eof> {};
}
#endif // SPICE_GRAMMAR_H