Sim Model Editor: Display model parameters

This commit adds parameter display functionality, via a wxPropertyGrid
widget, to the Sim Model Editor. To faciliate that, a SIM_VALUE class is
created to serialize, deserialize, and validate numeric values in the
new parameter grid.

SPICE_MODEL is renamed to SIM_MODEL and split into several subclasses
that correspond to different model kinds.
This commit is contained in:
Mikolaj Wielgus 2022-02-21 04:58:31 +01:00
parent 229e5c9e0f
commit c5a256291e
33 changed files with 11804 additions and 9115 deletions

View File

@ -319,8 +319,16 @@ if( KICAD_SPICE )
sim/sim_plot_frame_base.cpp
sim/sim_plot_panel.cpp
sim/sim_workbook.cpp
sim/sim_model.cpp
sim/sim_model_behavioral.cpp
sim/sim_model_codemodel.cpp
sim/sim_model_ideal.cpp
sim/sim_model_ngspice.cpp
sim/sim_model_rawspice.cpp
sim/sim_model_source.cpp
sim/sim_model_subcircuit.cpp
sim/sim_value.cpp
sim/spice_simulator.cpp
sim/spice_model.cpp
sim/spice_value.cpp
widgets/tuner_slider.cpp
widgets/tuner_slider_base.cpp

View File

@ -609,7 +609,7 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnEditSpiceModel( wxCommandEvent& event )
int diff = m_fields->size();
auto symbol = SCH_SYMBOL( *m_libEntry, m_libEntry->GetLibId(), nullptr, 0 );
DIALOG_SPICE_MODEL dialog( this, symbol, m_fields );
DIALOG_SPICE_MODEL dialog( this, symbol, *m_fields );
if( dialog.ShowModal() != wxID_OK )
return;

View File

@ -26,32 +26,36 @@
#include <dialog_spice_model.h>
#include <confirm.h>
using TYPE = SIM_VALUE_BASE::TYPE;
using CATEGORY = SIM_MODEL::PARAM::CATEGORY;
template class DIALOG_SPICE_MODEL<SCH_FIELD>;
template class DIALOG_SPICE_MODEL<LIB_FIELD>;
template <typename T>
DIALOG_SPICE_MODEL<T>::DIALOG_SPICE_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbol,
std::vector<T>* aFields )
std::vector<T>& aFields )
: DIALOG_SPICE_MODEL_BASE( aParent ),
m_symbol( aSymbol ),
m_fields( aFields )
m_fields( aFields ),
m_firstCategory( nullptr )
{
try
{
SPICE_MODEL::TYPE typeFromFields = SPICE_MODEL::ReadTypeFromFields( aFields );
SIM_MODEL::TYPE typeFromFields = SIM_MODEL::ReadTypeFromFields( aFields );
for( SPICE_MODEL::TYPE type : SPICE_MODEL::TYPE_ITERATOR() )
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
{
if( type == typeFromFields )
{
m_models.emplace_back( aFields );
m_models.push_back( SIM_MODEL::Create( aFields ) );
m_curModelType = type;
}
else
m_models.emplace_back( type );
m_models.push_back( SIM_MODEL::Create( type ) );
SPICE_MODEL::DEVICE_TYPE deviceType = SPICE_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 ) )
@ -67,8 +71,11 @@ DIALOG_SPICE_MODEL<T>::DIALOG_SPICE_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbo
m_typeChoice->Clear();
for( SPICE_MODEL::DEVICE_TYPE deviceType : SPICE_MODEL::DEVICE_TYPE_ITERATOR() )
m_deviceTypeChoice->Append( SPICE_MODEL::DeviceTypeInfo( deviceType ).description );
for( SIM_MODEL::DEVICE_TYPE deviceType : SIM_MODEL::DEVICE_TYPE_ITERATOR() )
m_deviceTypeChoice->Append( SIM_MODEL::DeviceTypeInfo( deviceType ).description );
m_paramGrid = m_paramGridMgr->AddPage();
m_scintillaTricks = std::make_unique<SCINTILLA_TRICKS>( m_codePreview, wxT( "{}" ), false );
@ -82,7 +89,7 @@ bool DIALOG_SPICE_MODEL<T>::TransferDataFromWindow()
if( !DIALOG_SPICE_MODEL_BASE::TransferDataFromWindow() )
return false;
m_models[static_cast<int>( m_curModelType )].WriteFields( m_fields );
m_models[static_cast<int>( m_curModelType )]->WriteFields( m_fields );
return true;
}
@ -93,8 +100,8 @@ bool DIALOG_SPICE_MODEL<T>::TransferDataToWindow()
{
try
{
m_models[static_cast<int>( SPICE_MODEL::ReadTypeFromFields( m_fields ) )]
= SPICE_MODEL( m_fields );
m_models[static_cast<int>( SIM_MODEL::ReadTypeFromFields( m_fields ) )]
= SIM_MODEL::Create( m_fields );
}
catch( KI_PARAM_ERROR& e )
{
@ -111,17 +118,17 @@ bool DIALOG_SPICE_MODEL<T>::TransferDataToWindow()
template <typename T>
void DIALOG_SPICE_MODEL<T>::updateWidgets()
{
SPICE_MODEL::DEVICE_TYPE deviceType = SPICE_MODEL::TypeInfo( m_curModelType ).deviceType;
SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( m_curModelType ).deviceType;
m_deviceTypeChoice->SetSelection( static_cast<int>( deviceType ) );
m_typeChoice->Clear();
for( SPICE_MODEL::TYPE type : SPICE_MODEL::TYPE_ITERATOR() )
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
{
if( SPICE_MODEL::TypeInfo( type ).deviceType == deviceType )
if( SIM_MODEL::TypeInfo( type ).deviceType == deviceType )
{
wxString description = SPICE_MODEL::TypeInfo( type ).description;
wxString description = SIM_MODEL::TypeInfo( type ).description;
if( !description.IsEmpty() )
m_typeChoice->Append( description );
@ -131,34 +138,60 @@ void DIALOG_SPICE_MODEL<T>::updateWidgets()
}
}
//m_typeChoice->SetSelection( static_cast<int>( m_curModelType ) );
m_paramGrid->ClearRows();
// This wxPropertyGridManager stuff has to be here because it segfaults in the constructor.
//if( m_model.Get
m_paramGridMgr->SetColumnCount( static_cast<int>( COLUMN::END_ ) );
/*if( m_model.GetSubtype() != SPICE_MODEL::SUBTYPE::NONE )
{
m_paramGrid->AppendRows( 1 );
m_paramGridMgr->SetColumnTitle( static_cast<int>( COLUMN::UNIT ), "Unit" );
m_paramGridMgr->SetColumnTitle( static_cast<int>( COLUMN::DEFAULT ), "Default" );
m_paramGridMgr->SetColumnTitle( static_cast<int>( COLUMN::TYPE ), "Type" );
m_paramGrid->SetReadOnly( 0, COLUMN::DESCRIPTION );
m_paramGrid->SetReadOnly( 0, COLUMN::NAME );
m_paramGrid->SetReadOnly( 0, COLUMN::UNIT );
m_paramGridMgr->ShowHeader();
m_paramGrid->SetCellValue( 0, COLUMN::VALUE,
SPICE_MODEL::SubtypeInfo( m_model.GetSubtype() ).description );
}*/
m_paramGrid->Clear();
m_firstCategory = m_paramGrid->Append( new wxPropertyCategory( "DC" ) );
m_paramGrid->HideProperty( "DC" );
m_paramGrid->Append( new wxPropertyCategory( "Temperature" ) );
m_paramGrid->HideProperty( "Temperature" );
m_paramGrid->Append( new wxPropertyCategory( "Noise" ) );
m_paramGrid->HideProperty( "Noise" );
m_paramGrid->Append( new wxPropertyCategory( "Distributed Quantities" ) );
m_paramGrid->HideProperty( "Distributed Quantities" );
m_paramGrid->Append( new wxPropertyCategory( "Geometry" ) );
m_paramGrid->HideProperty( "Geometry" );
m_paramGrid->Append( new wxPropertyCategory( "Limiting Values" ) );
m_paramGrid->HideProperty( "Limiting Values" );
m_paramGrid->Append( new wxPropertyCategory( "Advanced" ) );
m_paramGrid->HideProperty( "Advanced" );
m_paramGrid->Append( new wxPropertyCategory( "Flags" ) );
m_paramGrid->HideProperty( "Flags" );
SIM_MODEL& curModel = *m_models[static_cast<int>( m_curModelType )];
for( const SIM_MODEL::PARAM& param : curModel.Params() )
addParamPropertyIfRelevant( param );
m_paramGrid->CollapseAll();
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onDeviceTypeChoice( wxCommandEvent& aEvent )
{
//SPICE_MODEL::DEVICE_TYPE deviceType = SPICE_MODEL::TypeInfo( m_curModelType ).deviceType;
SPICE_MODEL::DEVICE_TYPE deviceType =
static_cast<SPICE_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
SIM_MODEL::DEVICE_TYPE deviceType =
static_cast<SIM_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
m_curModelType = m_curModelTypeOfDeviceType[deviceType];
m_curModelType = m_curModelTypeOfDeviceType.at( deviceType );
updateWidgets();
}
@ -167,28 +200,142 @@ void DIALOG_SPICE_MODEL<T>::onDeviceTypeChoice( wxCommandEvent& aEvent )
template <typename T>
void DIALOG_SPICE_MODEL<T>::onTypeChoice( wxCommandEvent& aEvent )
{
SPICE_MODEL::DEVICE_TYPE deviceType =
static_cast<SPICE_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
SIM_MODEL::DEVICE_TYPE deviceType =
static_cast<SIM_MODEL::DEVICE_TYPE>( m_deviceTypeChoice->GetSelection() );
wxString typeDescription = m_typeChoice->GetString( m_typeChoice->GetSelection() );
for( SPICE_MODEL::TYPE type : SPICE_MODEL::TYPE_ITERATOR() )
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
{
if( deviceType == SPICE_MODEL::TypeInfo( type ).deviceType
&& typeDescription == SPICE_MODEL::TypeInfo( type ).description )
if( deviceType == SIM_MODEL::TypeInfo( type ).deviceType
&& typeDescription == SIM_MODEL::TypeInfo( type ).description )
{
m_curModelType = type;
break;
}
}
m_curModelTypeOfDeviceType[deviceType] = m_curModelType;
m_curModelTypeOfDeviceType.at( deviceType ) = m_curModelType;
updateWidgets();
}
template <typename T>
void DIALOG_SPICE_MODEL<T>::onGridCellChange( wxGridEvent& aEvent )
void DIALOG_SPICE_MODEL<T>::addParamPropertyIfRelevant( const SIM_MODEL::PARAM& aParam )
{
/*updateModel();
updateWidgets();*/
if( aParam.info.dir == SIM_MODEL::PARAM::DIR::OUT )
return;
switch( aParam.info.category )
{
case CATEGORY::DC:
m_paramGrid->HideProperty( "DC", false );
m_paramGrid->AppendIn( "DC", newParamProperty( aParam ) );
break;
case CATEGORY::CAPACITANCE:
m_paramGrid->HideProperty( "Capacitance", false );
m_paramGrid->AppendIn( "Capacitance", newParamProperty( aParam ) );
break;
case CATEGORY::TEMPERATURE:
m_paramGrid->HideProperty( "Temperature", false );
m_paramGrid->AppendIn( "Temperature", newParamProperty( aParam ) );
break;
case CATEGORY::NOISE:
m_paramGrid->HideProperty( "Noise", false );
m_paramGrid->AppendIn( "Noise", newParamProperty( aParam ) );
break;
case CATEGORY::DISTRIBUTED_QUANTITIES:
m_paramGrid->HideProperty( "Distributed Quantities", false );
m_paramGrid->AppendIn( "Distributed Quantities", newParamProperty( aParam ) );
break;
case CATEGORY::GEOMETRY:
m_paramGrid->HideProperty( "Geometry", false );
m_paramGrid->AppendIn( "Geometry", newParamProperty( aParam ) );
break;
case CATEGORY::LIMITING_VALUES:
m_paramGrid->HideProperty( "Limiting Values", false );
m_paramGrid->AppendIn( "Limiting Values", newParamProperty( aParam ) );
break;
case CATEGORY::ADVANCED:
m_paramGrid->HideProperty( "Advanced", false );
m_paramGrid->AppendIn( "Advanced", newParamProperty( aParam ) );
break;
case CATEGORY::FLAGS:
m_paramGrid->HideProperty( "Flags", false );
m_paramGrid->AppendIn( "Flags", newParamProperty( aParam ) );
break;
default:
//m_paramGrid->AppendIn( nullptr, newParamProperty( aParam ) );
m_paramGrid->Insert( m_firstCategory, newParamProperty( aParam ) );
//m_paramGrid->Append( newParamProperty( aParam ) );
break;
case CATEGORY::INITIAL_CONDITIONS:
case CATEGORY::SUPERFLUOUS:
return;
}
}
template <typename T>
wxPGProperty* DIALOG_SPICE_MODEL<T>::newParamProperty( const SIM_MODEL::PARAM& aParam ) const
{
wxString paramDescription = wxString::Format( "%s (%s)",
aParam.info.description,
aParam.info.name );
wxPGProperty* prop = nullptr;
switch( aParam.info.type )
{
case TYPE::INT:
prop = new wxIntProperty( paramDescription );
break;
case TYPE::FLOAT:
prop = new wxFloatProperty( paramDescription );
break;
case TYPE::BOOL:
prop = new wxBoolProperty( paramDescription );
prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX, true );
break;
default:
prop = new wxStringProperty( paramDescription );
break;
}
prop->SetAttribute( wxPG_ATTR_UNITS, aParam.info.unit );
// Legacy due to the way we extracted parameters from Ngspice.
if( aParam.isOtherVariant )
prop->SetCell( 3, aParam.info.defaultValueOfOtherVariant );
else
prop->SetCell( 3, aParam.info.defaultValue );
wxString typeStr;
switch( aParam.info.type )
{
case TYPE::BOOL: typeStr = wxString( "Bool" ); break;
case TYPE::INT: typeStr = wxString( "Integer" ); break;
case TYPE::FLOAT: typeStr = wxString( "Float" ); break;
case TYPE::COMPLEX: typeStr = wxString( "Complex" ); break;
case TYPE::STRING: typeStr = wxString( "String" ); break;
case TYPE::BOOL_VECTOR: typeStr = wxString( "Bool Vector" ); break;
case TYPE::INT_VECTOR: typeStr = wxString( "Int Vector" ); break;
case TYPE::FLOAT_VECTOR: typeStr = wxString( "Float Vector" ); break;
case TYPE::COMPLEX_VECTOR: typeStr = wxString( "Complex Vector" ); break;
}
prop->SetCell( static_cast<int>( COLUMN::TYPE ), typeStr );
return prop;
}

View File

@ -29,17 +29,21 @@
#include <netlist_exporter_pspice.h>
#include <scintilla_tricks.h>
#include <sim/spice_model.h>
#include <sim/sim_model.h>
#include <sch_symbol.h>
// Some probable wxWidgets bugs encountered when writing this class:
// 1. There are rendering problems with wxPropertyGrid on Linux, GTK, Xorg when
// wxPG_NATIVE_DOUBLE_BUFFERING flag is not set.
// 2. wxPropertyGridManager->ShowHeader() segfaults when called from this dialog's constructor.
template <typename T>
class DIALOG_SPICE_MODEL : public DIALOG_SPICE_MODEL_BASE
{
public:
enum COLUMN { DESCRIPTION, NAME, VALUE, UNIT };
enum class COLUMN : int { DESCRIPTION = 0, VALUE, UNIT, DEFAULT, TYPE, END_ };
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:
bool TransferDataFromWindow() override;
@ -50,15 +54,19 @@ private:
void onDeviceTypeChoice( wxCommandEvent& aEvent ) override;
void onTypeChoice( wxCommandEvent& aEvent ) override;
void onGridCellChange( wxGridEvent& aEvent ) override;
void addParamPropertyIfRelevant( const SIM_MODEL::PARAM& aParam );
wxPGProperty* newParamProperty( const SIM_MODEL::PARAM& aParam ) const;
SCH_SYMBOL& m_symbol;
std::vector<T>* m_fields;
std::vector<T>& m_fields;
std::vector<SPICE_MODEL> m_models;
std::map<SPICE_MODEL::DEVICE_TYPE, SPICE_MODEL::TYPE> m_curModelTypeOfDeviceType;
SPICE_MODEL::TYPE m_curModelType = SPICE_MODEL::TYPE::NONE;
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
std::map<SIM_MODEL::DEVICE_TYPE, SIM_MODEL::TYPE> m_curModelTypeOfDeviceType;
SIM_MODEL::TYPE m_curModelType = SIM_MODEL::TYPE::NONE;
wxPropertyGridPage* m_paramGrid;
wxPGProperty* m_firstCategory; // Used to add principal parameters to root (any better ideas?)
std::unique_ptr<SCINTILLA_TRICKS> m_scintillaTricks;
};

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.0)
// C++ code generated with wxFormBuilder (version 3.10.1)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -94,40 +94,9 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
bSizer12->Add( fgSizer16, 0, wxEXPAND, 5 );
m_paramGrid = new WX_GRID( m_parametersPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
// Grid
m_paramGrid->CreateGrid( 0, 4 );
m_paramGrid->EnableEditing( true );
m_paramGrid->EnableGridLines( true );
m_paramGrid->EnableDragGridSize( false );
m_paramGrid->SetMargins( 0, 0 );
// Columns
m_paramGrid->SetColSize( 0, 300 );
m_paramGrid->SetColSize( 1, 80 );
m_paramGrid->SetColSize( 2, 80 );
m_paramGrid->SetColSize( 3, 50 );
m_paramGrid->EnableDragColMove( true );
m_paramGrid->EnableDragColSize( true );
m_paramGrid->SetColLabelValue( 0, wxT("Description") );
m_paramGrid->SetColLabelValue( 1, wxT("Name") );
m_paramGrid->SetColLabelValue( 2, wxT("Value") );
m_paramGrid->SetColLabelValue( 3, wxT("Unit") );
m_paramGrid->SetColLabelSize( 22 );
m_paramGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Rows
m_paramGrid->EnableDragRowSize( false );
m_paramGrid->SetRowLabelSize( 0 );
m_paramGrid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Label Appearance
m_paramGrid->SetLabelFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
// Cell Defaults
m_paramGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
bSizer12->Add( m_paramGrid, 1, wxALL|wxEXPAND, 5 );
m_paramGridMgr = new wxPropertyGridManager(m_parametersPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPGMAN_DEFAULT_STYLE);
m_paramGridMgr->SetExtraStyle( wxPG_EX_MODE_BUTTONS|wxPG_EX_NATIVE_DOUBLE_BUFFERING );
bSizer12->Add( m_paramGridMgr, 1, wxALL|wxEXPAND, 5 );
m_parametersPanel->SetSizer( bSizer12 );
@ -251,14 +220,12 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
this->SetSizer( bSizer8 );
this->Layout();
bSizer8->Fit( this );
this->Centre( wxBOTH );
// Connect Events
m_deviceTypeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
m_typeChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoice ), NULL, this );
m_paramGrid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SPICE_MODEL_BASE::onGridCellChange ), NULL, this );
}
DIALOG_SPICE_MODEL_BASE::~DIALOG_SPICE_MODEL_BASE()
@ -266,6 +233,5 @@ DIALOG_SPICE_MODEL_BASE::~DIALOG_SPICE_MODEL_BASE()
// Disconnect Events
m_deviceTypeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onDeviceTypeChoice ), NULL, this );
m_typeChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onTypeChoice ), NULL, this );
m_paramGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SPICE_MODEL_BASE::onGridCellChange ), NULL, this );
}

View File

@ -47,7 +47,7 @@
<property name="minimum_size"></property>
<property name="name">DIALOG_SPICE_MODEL_BASE</property>
<property name="pos"></property>
<property name="size"></property>
<property name="size">600,800</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxSTAY_ON_TOP</property>
<property name="subclass">; ; forward_declare</property>
<property name="title">Spice Model Editor</property>
@ -997,7 +997,7 @@
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxGrid" expanded="1">
<object class="wxPropertyGridManager" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -1006,50 +1006,27 @@
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="autosize_cols">0</property>
<property name="autosize_rows">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="cell_bg"></property>
<property name="cell_font"></property>
<property name="cell_horiz_alignment">wxALIGN_LEFT</property>
<property name="cell_text"></property>
<property name="cell_vert_alignment">wxALIGN_TOP</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
<property name="col_label_size">22</property>
<property name="col_label_values">&quot;Description&quot; &quot;Name&quot; &quot;Value&quot; &quot;Unit&quot;</property>
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
<property name="cols">4</property>
<property name="column_sizes">300,80,80,50</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="drag_col_move">1</property>
<property name="drag_col_size">1</property>
<property name="drag_grid_size">0</property>
<property name="drag_row_size">0</property>
<property name="editing">1</property>
<property name="enabled">1</property>
<property name="extra_style">wxPG_EX_MODE_BUTTONS|wxPG_EX_NATIVE_DOUBLE_BUFFERING</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="grid_line_color"></property>
<property name="grid_lines">1</property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label_bg"></property>
<property name="label_font">,90,92,-1,70,0</property>
<property name="label_text"></property>
<property name="margin_height">0</property>
<property name="margin_width">0</property>
<property name="include_advanced">1</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
@ -1057,7 +1034,7 @@
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_paramGrid</property>
<property name="name">m_paramGridMgr</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
@ -1065,21 +1042,15 @@
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="row_label_horiz_alignment">wxALIGN_CENTER</property>
<property name="row_label_size">0</property>
<property name="row_label_values"></property>
<property name="row_label_vert_alignment">wxALIGN_CENTER</property>
<property name="row_sizes"></property>
<property name="rows">0</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property>
<property name="style">wxPGMAN_DEFAULT_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>
<event name="OnGridCellChange">onGridCellChange</event>
</object>
</object>
</object>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.0)
// C++ code generated with wxFormBuilder (version 3.10.1)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -26,10 +26,13 @@ class WX_GRID;
#include <wx/statbox.h>
#include <wx/checkbox.h>
#include <wx/choice.h>
#include <wx/grid.h>
#include <wx/propgrid/propgrid.h>
#include <wx/propgrid/manager.h>
#include <wx/propgrid/advprops.h>
#include <wx/panel.h>
#include <wx/stc/stc.h>
#include <wx/notebook.h>
#include <wx/grid.h>
#include <wx/statline.h>
#include <wx/dialog.h>
@ -58,7 +61,7 @@ class DIALOG_SPICE_MODEL_BASE : public wxDialog
wxChoice* m_deviceTypeChoice;
wxStaticText* m_staticText8;
wxChoice* m_typeChoice;
WX_GRID* m_paramGrid;
wxPropertyGridManager* m_paramGridMgr;
wxPanel* m_codePanel;
wxStyledTextCtrl* m_codePreview;
wxPanel* m_pinAssignmentsPanel;
@ -72,12 +75,11 @@ class DIALOG_SPICE_MODEL_BASE : public wxDialog
// Virtual event handlers, override them in your derived class
virtual void onDeviceTypeChoice( wxCommandEvent& event ) { event.Skip(); }
virtual void onTypeChoice( wxCommandEvent& event ) { event.Skip(); }
virtual void onGridCellChange( wxGridEvent& event ) { event.Skip(); }
public:
DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Spice Model Editor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxSTAY_ON_TOP );
DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Spice Model Editor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 600,800 ), long style = wxDEFAULT_DIALOG_STYLE|wxSTAY_ON_TOP );
~DIALOG_SPICE_MODEL_BASE();

View File

@ -544,7 +544,7 @@ void DIALOG_SYMBOL_PROPERTIES::OnEditSpiceModel( wxCommandEvent& event )
#ifdef KICAD_SPICE
int diff = m_fields->size();
DIALOG_SPICE_MODEL dialog( this, *m_symbol, m_fields );
DIALOG_SPICE_MODEL dialog( this, *m_symbol, *m_fields );
if( dialog.ShowModal() != wxID_OK )
return;

View File

@ -1,371 +0,0 @@
#!/bin/bash
# This script is disgusting (very slow and hacky). Please rewrite it in Python if you have time.
MODELS=$(cat << END
resistor R - R 2 0 0
capacitor C - C 2 0 0
inductor L - L 2 0 0
ltra LTRA - O 4 0 0
tranline - - T 4 0 0
urc URC - U 3 0 0
transline - - Y 4 0 0
diode D - D 2 0 0
bjt NPN PNP Q 3 1 0
vbic NPN PNP Q 3 4 0
hicum2 NPN PNP Q 3 8 0
jfet NJF PJF J 3 1 0
jfet2 NJF PJF J 3 2 0
mes NMF PMF Z 3 1 0
mesa NMF PMF Z 3 2 0
hfet1 NMF PMF Z 3 5 0
hfet2 NMF PMF Z 3 6 0
mos1 NMOS PMOS M 4 1 0
mos2 NMOS PMOS M 4 2 0
mos3 NMOS PMOS M 4 3 0
bsim1 NMOS PMOS M 4 4 0
bsim2 NMOS PMOS M 4 5 0
mos6 NMOS PMOS M 4 6 0
bsim3 NMOS PMOS M 4 8 3.3.0
mos9 NMOS PMOS M 4 9 0
b4soi NMOS PMOS M 4 10 0
bsim4 NMOS PMOS M 4 14 4.8.1
b3soifd NMOS PMOS M 4 55 0
b3soidd NMOS PMOS M 4 56 0
b3soipd NMOS PMOS M 4 57 0
hisim2 NMOS PMOS M 4 68 0
hisimhv1 NMOS PMOS M 4 73 1.2.4
hisimhv2 NMOS PMOS M 4 73 2.2.0
END
)
UNITS=$(cat << END
%/deg C
exponent alternative
-
exponent
ohm/m
sheet resistance
resistance per unit length
ohm
resistance
resistor model default value
F/m^2
cap per area
F/m
capacitance per meter
overlap cap
capacitance per unit length
capacitance grading coefficient per unit length
F
capacitance
cap\.
H
inductance
1/W
coef of thermal current reduction
sqrt V
bulk effect coefficient 1
bulk threshold parameter
1/V
channel length modulation
vgs dependence on mobility
V/cm
Crit. field for mob. degradation
V
voltage
potential
A/V^2
transconductance parameter
A/m^2
current density
A/m
current per unit length
A
current
ohm/deg C^2
second order temp. coefficient
ohm/deg C
first order temp. coefficient
1/deg C^2
grading coefficient 1st temp. coeff
1/deg C
grading coefficient 2nd temp. coeff
deg C/W
thermal resistance
deg C
temperature
eV
energy
cm^2/V^2 s
VBS dependence on muz
VBS dependence on mus
VDS dependence on mus
cm^2/V s
zero field mobility
surface mobility
um/V^2
VDS depence of u1
um
.* in um
1/cm^3
substrate doping
1/cm^2
surface state density
fast surface state density
m/s
velocity
m
length
width
thickness
narrowing of
shortening of
C
epi charge parameter
s
time
deg
excess phase
-
.*
END
)
run_ngspice()
{
ngspice -n 2>/dev/null << END
*
$1
.control
$2
.endc
END
}
{
echo "// Generated using the $(basename $0) script."
echo "// Modify that script instead of this file if you want to make changes."
echo ""
echo "#include <sim/ngspice.h>"
echo ""
echo "enum class NGSPICE::MODEL_TYPE"
echo "{"
echo "$MODELS" | while read -r model_name model_primitive model_level model_version; do
if [ -n "$model_name" ]; then
echo " ${model_name^^},"
fi
done
echo "};"
echo ""
echo "NGSPICE::MODEL_INFO NGSPICE::GetModelInfo( NGSPICE::MODEL_TYPE aType )"
echo "{"
echo " switch( aType )"
echo " {"
echo "$MODELS" | while read -r model_name \
model_type1 \
model_type2 \
model_primitive \
model_pin_count \
model_level \
model_version
do
if [ -n "$model_name" ]; then
# Print model description.
run_ngspice "" "devhelp -type $model_name" | while read -r name sep description; do
if [ "$sep" = "-" ]; then
echo -n " case NGSPICE::MODEL_TYPE::${model_name^^}:"
echo -n " return { \"$name\","
for model_type in "$model_type1" "$model_type2"; do
if [ "$model_type" != "-" ]; then
echo -n " \"$model_type\","
else
echo -n " \"\","
fi
done
echo " \"$description\","
fi
done
# Print model parameter ID, name, direction, type, unit, and description.
run_ngspice "" "devhelp -type $model_name" | while read -r param_id \
param_name \
param_dir \
param_type \
param_description
do
if [ "$param_id" = "Model" ] && [ "$param_name" = "Parameters" ]; then
echo " // Model parameters"
echo " {"
elif [ "$param_id" = "Instance" ] && [ "$param_name" = "Parameters" ]; then
echo " },"
echo " // Instance parameters"
echo " {"
elif [ "$param_id" -eq "$param_id" ] 2>/dev/null \
&& [ -n "$param_name" ] \
&& [ -n "$param_dir" ] \
&& [ -n "$param_description" ]
then
echo -n " { \"${param_name,,}\","
echo -n " { $param_id,"
echo -n " NGSPICE::PARAM_DIR::${param_dir^^},"
echo -n " NGSPICE::PARAM_TYPE::${param_type^^},"
unit=""
# Non-reals are unlikely to have units.
if [ "$param_type" = "real" ]; then
# Don't use a pipe here because it creates a subshell, as it prevents the
# changes to the variables from propagating upwards. Bash is cursed.
while read -r pattern; do
if [ "$unit" = "" ]; then
unit="$pattern"
elif [ -z "$pattern" ]; then
unit=""
elif grep -iE "$pattern" <<< "$param_description" >/dev/null; then
break
fi
done <<< "$UNITS"
fi
if [ "$unit" = "-" ]; then
unit=""
fi
echo -n " \"$unit\","
for model_type in "$model_type1" "$model_type2"; do
if [ "$model_type" = "-" ]; then
echo -n " \"\","
continue
fi
# For a given primitive, Ngspice determines the device model to be used
# from two parameters: "level" and "version".
params=""
if [ "$model_level" != 0 ]; then
params="$params level=$model_level"
fi
if [ "$model_version" != 0 ]; then
params="$params version=$model_version"
fi
netlist=$(cat << END
.model $model_type $model_type($params)
${model_primitive}1 $(seq -s ' ' $model_pin_count) $model_type
END
)
control=$(cat << END
op
showmod ${model_primitive}1 : $param_name
END
)
was_model_line=0
was_echoed=0
# Don't use a pipe here either.
while read -r name value; do
# Ngspice displays only the first 11 characters of the variable name.
# We also convert to lowercase because a few parameter names have
# uppercase characters in them.
lowercase_name=${name,,}
lowercase_param_name=${param_name,,}
if [ "$was_model_line" = 0 ] && [ "$lowercase_name" = "model" ]; then
was_model_line=1
elif [ "$was_model_line" = 1 ] \
&& [ "$lowercase_name" = "${lowercase_param_name:0:11}" ]
then
if [ "$value" = "<<NAN, error = 7>>" ]; then
value="NaN"
elif [ "$value" = "?????????" ]; then
value=""
fi
was_echoed=1
echo -n " \"$value\","
fi
done < <(run_ngspice "$netlist" "$control")
if [ "$was_echoed" = 0 ]; then
echo ""
echo "Error! Default value not found."
exit 1
fi
done
echo " \"$param_description\" } },"
fi
done
echo " } };"
fi
done
echo " }"
echo ""
echo " wxFAIL;"
echo " return {};"
echo "}"
} > $(dirname "$0")/ngspice_models.cpp

View File

@ -27,10 +27,13 @@
#ifndef NGSPICE_H
#define NGSPICE_H
#include "spice_simulator.h"
#include <sim/spice_simulator.h>
#include <sim/sim_model.h>
#include <sim/sim_value.h>
#include <wx/dynlib.h>
#include <ngspice/sharedspice.h>
#include <enum_vector.h>
// We have an issue here where NGSPICE incorrectly used bool for years
// and defined it to be int when in C-mode. We cannot adjust the function
@ -47,56 +50,59 @@ class wxDynamicLibrary;
class NGSPICE : public SPICE_SIMULATOR
{
public:
enum class PARAM_DIR
{
IN,
OUT,
INOUT
};
enum class PARAM_TYPE
{
FLAG,
INTEGER,
REAL,
COMPLEX,
NODE,
INSTANCE,
STRING,
PARSETREE,
VECTOR,
FLAGVEC,
INTVEC,
REALVEC,
CPLXVEC,
NODEVEC,
INSTVEC,
STRINGVEC
};
struct PARAM_INFO
{
unsigned int id;
PARAM_DIR dir;
PARAM_TYPE type;
wxString unit;
wxString defaultValueOfVariant1;
wxString defaultValueOfVariant2;
wxString description;
};
enum class MODEL_TYPE; // Defined in ngspice_devices.cpp.
DEFINE_ENUM_CLASS_WITH_ITERATOR( MODEL_TYPE,
NONE,
RESISTOR,
CAPACITOR,
INDUCTOR,
LTRA,
TRANLINE,
URC,
TRANSLINE,
SWITCH,
CSWITCH,
DIODE,
BJT,
VBIC,
HICUM2,
JFET,
JFET2,
MES,
MESA,
HFET1,
HFET2,
MOS1,
MOS2,
MOS3,
BSIM1,
BSIM2,
MOS6,
BSIM3,
MOS9,
B4SOI,
BSIM4,
B3SOIFD,
B3SOIDD,
B3SOIPD,
HISIM2,
HISIMHV1,
HISIMHV2
)
// May be moved to the SPICE_MODEL class later.
struct MODEL_INFO
{
wxString name;
wxString variant1;
wxString variant2;
wxString description;
std::map<wxString, PARAM_INFO> modelParams;
std::map<wxString, PARAM_INFO> instanceParams;
std::vector<SIM_MODEL::PARAM::INFO> modelParams;
std::vector<SIM_MODEL::PARAM::INFO> instanceParams;
};
static const MODEL_INFO& ModelInfo( MODEL_TYPE aType );
NGSPICE();
virtual ~NGSPICE();
@ -142,8 +148,6 @@ public:
///< @copydoc SPICE_SIMULATOR::GetPhasePlot()
std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) override final;
MODEL_INFO GetModelInfo( MODEL_TYPE aDeviceType );
std::vector<std::string> GetSettingCommands() const override final;
///< @copydoc SPICE_SIMULATOR::GetNetlist()

File diff suppressed because it is too large Load Diff

1128
eeschema/sim/sim_model.cpp Normal file

File diff suppressed because it is too large Load Diff

354
eeschema/sim/sim_model.h Normal file
View File

@ -0,0 +1,354 @@
/*
* 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_MODEL_H
#define SIM_MODEL_H
#include <map>
#include <stdexcept>
#include <enum_vector.h>
#include <sch_field.h>
#include <lib_field.h>
#include <sim/sim_value.h>
#include <wx/string.h>
class SIM_MODEL
{
public:
static constexpr auto DEVICE_TYPE_FIELD = "Model_Device";
static constexpr auto TYPE_FIELD = "Model_Type";
static constexpr auto FILE_FIELD = "Model_File";
static constexpr auto PARAMS_FIELD = "Model_Params";
DEFINE_ENUM_CLASS_WITH_ITERATOR( DEVICE_TYPE,
NONE,
RESISTOR,
CAPACITOR,
INDUCTOR,
TLINE,
SWITCH,
DIODE,
NPN,
PNP,
NJF,
PJF,
NMES,
PMES,
NMOS,
PMOS,
VSOURCE,
ISOURCE,
SUBCIRCUIT,
CODEMODEL,
RAWSPICE
)
struct DEVICE_INFO
{
wxString fieldValue;
wxString description;
};
DEFINE_ENUM_CLASS_WITH_ITERATOR( TYPE,
NONE,
RESISTOR_IDEAL,
RESISTOR_ADVANCED,
RESISTOR_BEHAVIORAL,
CAPACITOR_IDEAL,
CAPACITOR_ADVANCED,
CAPACITOR_BEHAVIORAL,
INDUCTOR_IDEAL,
INDUCTOR_ADVANCED,
INDUCTOR_BEHAVIORAL,
TLINE_LOSSY,
TLINE_LOSSLESS,
TLINE_UNIFORM_RC,
TLINE_KSPICE,
SWITCH_VCTRL,
SWITCH_ICTRL,
DIODE,
NPN_GUMMEL_POON,
PNP_GUMMEL_POON,
NPN_VBIC,
PNP_VBIC,
//NPN_MEXTRAM,
//PNP_MEXTRAM,
NPN_HICUM_L2,
PNP_HICUM_L2,
//NPN_HICUM_L0,
//PNP_HICUM_L0,
NJF_SHICHMAN_HODGES,
PJF_SHICHMAN_HODGES,
NJF_PARKER_SKELLERN,
PJF_PARKER_SKELLERN,
NMES_STATZ,
PMES_STATZ,
NMES_YTTERDAL,
PMES_YTTERDAL,
NMES_HFET1,
PMES_HFET1,
NMES_HFET2,
PMES_HFET2,
NMOS_MOS1,
PMOS_MOS1,
NMOS_MOS2,
PMOS_MOS2,
NMOS_MOS3,
PMOS_MOS3,
NMOS_BSIM1,
PMOS_BSIM1,
NMOS_BSIM2,
PMOS_BSIM2,
NMOS_MOS6,
PMOS_MOS6,
NMOS_MOS9,
PMOS_MOS9,
NMOS_BSIM3,
PMOS_BSIM3,
NMOS_B4SOI,
PMOS_B4SOI,
NMOS_BSIM4,
PMOS_BSIM4,
//NMOS_EKV2_6,
//PMOS_EKV2_6,
//NMOS_PSP,
//PMOS_PSP,
NMOS_B3SOIFD,
PMOS_B3SOIFD,
NMOS_B3SOIDD,
PMOS_B3SOIDD,
NMOS_B3SOIPD,
PMOS_B3SOIPD,
//NMOS_STAG,
//PMOS_STAG,
NMOS_HISIM2,
PMOS_HISIM2,
NMOS_HISIM_HV1,
PMOS_HISIM_HV1,
NMOS_HISIM_HV2,
PMOS_HISIM_HV2,
VSOURCE_PULSE,
VSOURCE_SIN,
VSOURCE_EXP,
VSOURCE_SFAM,
VSOURCE_SFFM,
VSOURCE_PWL,
VSOURCE_WHITE_NOISE,
VSOURCE_PINK_NOISE,
VSOURCE_BURST_NOISE,
VSOURCE_RANDOM_UNIFORM,
VSOURCE_RANDOM_NORMAL,
VSOURCE_RANDOM_EXP,
VSOURCE_RANDOM_POISSON,
VSOURCE_BEHAVIORAL,
ISOURCE_PULSE,
ISOURCE_SIN,
ISOURCE_EXP,
ISOURCE_SFAM,
ISOURCE_SFFM,
ISOURCE_PWL,
ISOURCE_WHITE_NOISE,
ISOURCE_PINK_NOISE,
ISOURCE_BURST_NOISE,
ISOURCE_RANDOM_UNIFORM,
ISOURCE_RANDOM_NORMAL,
ISOURCE_RANDOM_EXP,
ISOURCE_RANDOM_POISSON,
ISOURCE_BEHAVIORAL,
SUBCIRCUIT,
CODEMODEL,
RAWSPICE
)
struct INFO
{
DEVICE_TYPE deviceType;
wxString fieldValue;
wxString description;
};
struct PARAM
{
enum class DIR
{
IN,
OUT,
INOUT
};
enum class CATEGORY
{
PRINCIPAL,
DC,
CAPACITANCE,
TEMPERATURE,
NOISE,
DISTRIBUTED_QUANTITIES,
GEOMETRY,
LIMITING_VALUES,
ADVANCED,
FLAGS,
INITIAL_CONDITIONS,
SUPERFLUOUS
};
struct FLAGS {}; // Legacy.
struct INFO
{
wxString name;
unsigned int id = 0; // Legacy.
DIR dir;
SIM_VALUE_BASE::TYPE type;
FLAGS flags = {}; // Legacy
wxString unit;
CATEGORY category;
wxString defaultValue = "";
wxString defaultValueOfOtherVariant = ""; // Legacy.
wxString description;
};
std::unique_ptr<SIM_VALUE_BASE> value;
const INFO& info;
bool isOtherVariant = false; // Legacy.
PARAM( const INFO& aInfo ) :
value( SIM_VALUE_BASE::Create( aInfo.type ) ),
info( aInfo )
{}
};
static DEVICE_INFO DeviceTypeInfo( DEVICE_TYPE aDeviceType );
static INFO TypeInfo( TYPE aType );
template <typename T>
static TYPE ReadTypeFromFields( const std::vector<T>& aFields );
template <typename T>
static std::unique_ptr<SIM_MODEL> Create( const std::vector<T>& aFields );
static std::unique_ptr<SIM_MODEL> Create( TYPE aType );
// Move semantics.
// Rule of five.
virtual ~SIM_MODEL() = default;
SIM_MODEL() = delete;
SIM_MODEL( const SIM_MODEL& aOther ) = delete;
SIM_MODEL( SIM_MODEL&& aOther ) = default;
SIM_MODEL& operator=(SIM_MODEL&& aOther ) = default;
SIM_MODEL( TYPE aType );
template <typename T>
SIM_MODEL( const std::vector<T>& aFields );
template <typename T>
void WriteFields( std::vector<T>& aFields );
// C++ doesn't allow virtual template methods, so we do this:
virtual void DoWriteSchFields( std::vector<SCH_FIELD>& aFields );
virtual void DoWriteLibFields( std::vector<LIB_FIELD>& aFields );
virtual void WriteCode( wxString& aCode ) = 0;
TYPE GetType() { return m_type; }
wxString GetFile() { return m_file; }
void SetFile( const wxString& aFile ) { m_file = aFile; }
std::vector<PARAM>& Params() { return m_params; }
private:
TYPE m_type;
wxString m_file;
std::vector<PARAM> m_params;
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 );
virtual wxString generateParamValuePairs();
virtual void parseParamValuePairs( const wxString& aParamValuePairs );
};
#endif // SIM_MODEL_H

View File

@ -0,0 +1,66 @@
/*
* 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_model_behavioral.h>
SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType ) : SIM_MODEL( aType )
{
static PARAM::INFO resistor = makeParamInfo( "r", "Expression for resistance", "ohm" );
static PARAM::INFO capacitor = makeParamInfo( "c", "Expression for capacitance", "F" );
static PARAM::INFO inductor = makeParamInfo( "l", "Expression for inductance", "H" );
static PARAM::INFO vsource = makeParamInfo( "v", "Expression for voltage", "V" );
static PARAM::INFO isource = makeParamInfo( "i", "Expression for current", "A" );
switch( aType )
{
case TYPE::RESISTOR_BEHAVIORAL: Params().emplace_back( resistor ); break;
case TYPE::CAPACITOR_BEHAVIORAL: Params().emplace_back( capacitor ); break;
case TYPE::INDUCTOR_BEHAVIORAL: Params().emplace_back( inductor ); break;
case TYPE::VSOURCE_BEHAVIORAL: Params().emplace_back( vsource ); break;
case TYPE::ISOURCE_BEHAVIORAL: Params().emplace_back( isource ); break;
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_IDEAL" );
}
}
void SIM_MODEL_BEHAVIORAL::WriteCode( wxString& aCode )
{
// TODO
}
SIM_MODEL::PARAM::INFO SIM_MODEL_BEHAVIORAL::makeParamInfo( wxString name, wxString description,
wxString unit )
{
SIM_MODEL::PARAM::INFO paramInfo = {};
paramInfo.name = name;
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = unit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.description = description;
return paramInfo;
}

View File

@ -0,0 +1,42 @@
/*
* 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_MODEL_BEHAVIORAL_H
#define SIM_MODEL_BEHAVIORAL_H
#include <sim/sim_model.h>
class SIM_MODEL_BEHAVIORAL : public SIM_MODEL
{
public:
SIM_MODEL_BEHAVIORAL( TYPE aType );
void WriteCode( wxString& aCode ) override;
private:
static PARAM::INFO makeParamInfo( wxString name, wxString description, wxString unit );
};
#endif // SIM_MODEL_BEHAVIORAL_H

View File

@ -0,0 +1,35 @@
/*
* 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_model_codemodel.h>
SIM_MODEL_CODEMODEL::SIM_MODEL_CODEMODEL( TYPE aType ) : SIM_MODEL( aType )
{
}
void SIM_MODEL_CODEMODEL::WriteCode( wxString& aCode )
{
// TODO
}

View File

@ -0,0 +1,39 @@
/*
* 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_MODEL_CODEMODEL_H
#define SIM_MODEL_CODEMODEL_H
#include <sim/sim_model.h>
class SIM_MODEL_CODEMODEL : public SIM_MODEL
{
public:
SIM_MODEL_CODEMODEL( TYPE aType );
void WriteCode( wxString& aCode ) override;
};
#endif // SIM_MODEL_CODEMODEL_H

View File

@ -0,0 +1,64 @@
/*
* 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_model_ideal.h>
using PARAM = SIM_MODEL::PARAM;
SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) : SIM_MODEL( aType )
{
static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "ohm" );
static PARAM::INFO capacitor = makeParamInfo( "c", "Capacitance", "F" );
static PARAM::INFO inductor = makeParamInfo( "l", "Inductance", "H" );
switch( aType )
{
case TYPE::RESISTOR_IDEAL: Params().emplace_back( resistor ); break;
case TYPE::CAPACITOR_IDEAL: Params().emplace_back( capacitor ); break;
case TYPE::INDUCTOR_IDEAL: Params().emplace_back( inductor ); break;
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_IDEAL" );
}
}
void SIM_MODEL_IDEAL::WriteCode( wxString& aCode )
{
// TODO
}
PARAM::INFO SIM_MODEL_IDEAL::makeParamInfo( wxString aName, wxString aDescription, wxString aUnit )
{
SIM_MODEL::PARAM::INFO paramInfo = {};
paramInfo.name = aName;
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.description = aDescription;
return paramInfo;
}

View File

@ -0,0 +1,42 @@
/*
* 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_MODEL_IDEAL_H
#define SIM_MODEL_IDEAL_H
#include <sim/sim_model.h>
class SIM_MODEL_IDEAL : public SIM_MODEL
{
public:
SIM_MODEL_IDEAL( TYPE aType );
void WriteCode( wxString& aCode ) override;
private:
static PARAM::INFO makeParamInfo( wxString aName, wxString aDescription, wxString aUnit );
};
#endif // SIM_MODEL_IDEAL_H

View File

@ -0,0 +1,165 @@
/*
* 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_model_ngspice.h>
using TYPE = SIM_MODEL::TYPE;
SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType ) : SIM_MODEL( aType )
{
const NGSPICE::MODEL_INFO& modelInfo = NGSPICE::ModelInfo( getModelType() );
for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.modelParams )
{
Params().emplace_back( paramInfo );
Params().back().isOtherVariant = getIsOtherVariant();
}
for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams )
{
Params().emplace_back( paramInfo );
Params().back().isOtherVariant = getIsOtherVariant();
}
}
void SIM_MODEL_NGSPICE::WriteCode( wxString& aCode )
{
// TODO
}
NGSPICE::MODEL_TYPE SIM_MODEL_NGSPICE::getModelType()
{
switch( GetType() )
{
case TYPE::NONE: return NGSPICE::MODEL_TYPE::NONE;
case TYPE::RESISTOR_ADVANCED: return NGSPICE::MODEL_TYPE::RESISTOR;
case TYPE::CAPACITOR_ADVANCED: return NGSPICE::MODEL_TYPE::CAPACITOR;
case TYPE::INDUCTOR_ADVANCED: return NGSPICE::MODEL_TYPE::INDUCTOR;
case TYPE::TLINE_LOSSY: return NGSPICE::MODEL_TYPE::LTRA;
case TYPE::TLINE_LOSSLESS: return NGSPICE::MODEL_TYPE::TRANLINE;
case TYPE::TLINE_UNIFORM_RC: return NGSPICE::MODEL_TYPE::URC;
case TYPE::TLINE_KSPICE: return NGSPICE::MODEL_TYPE::TRANSLINE;
case TYPE::SWITCH_VCTRL: return NGSPICE::MODEL_TYPE::SWITCH;
case TYPE::SWITCH_ICTRL: return NGSPICE::MODEL_TYPE::CSWITCH;
case TYPE::DIODE: return NGSPICE::MODEL_TYPE::DIODE;
case TYPE::NPN_GUMMEL_POON:
case TYPE::PNP_GUMMEL_POON: return NGSPICE::MODEL_TYPE::BJT;
case TYPE::NPN_VBIC:
case TYPE::PNP_VBIC: return NGSPICE::MODEL_TYPE::VBIC;
case TYPE::NPN_HICUM_L2:
case TYPE::PNP_HICUM_L2: return NGSPICE::MODEL_TYPE::HICUM2;
case TYPE::NJF_SHICHMAN_HODGES:
case TYPE::PJF_SHICHMAN_HODGES: return NGSPICE::MODEL_TYPE::JFET;
case TYPE::NJF_PARKER_SKELLERN:
case TYPE::PJF_PARKER_SKELLERN: return NGSPICE::MODEL_TYPE::JFET2;
case TYPE::NMES_STATZ:
case TYPE::PMES_STATZ: return NGSPICE::MODEL_TYPE::MES;
case TYPE::NMES_YTTERDAL:
case TYPE::PMES_YTTERDAL: return NGSPICE::MODEL_TYPE::MESA;
case TYPE::NMES_HFET1:
case TYPE::PMES_HFET1: return NGSPICE::MODEL_TYPE::HFET1;
case TYPE::PMES_HFET2:
case TYPE::NMES_HFET2: return NGSPICE::MODEL_TYPE::HFET2;
case TYPE::NMOS_MOS1:
case TYPE::PMOS_MOS1: return NGSPICE::MODEL_TYPE::MOS1;
case TYPE::NMOS_MOS2:
case TYPE::PMOS_MOS2: return NGSPICE::MODEL_TYPE::MOS2;
case TYPE::NMOS_MOS3:
case TYPE::PMOS_MOS3: return NGSPICE::MODEL_TYPE::MOS3;
case TYPE::NMOS_BSIM1:
case TYPE::PMOS_BSIM1: return NGSPICE::MODEL_TYPE::BSIM1;
case TYPE::NMOS_BSIM2:
case TYPE::PMOS_BSIM2: return NGSPICE::MODEL_TYPE::BSIM2;
case TYPE::NMOS_MOS6:
case TYPE::PMOS_MOS6: return NGSPICE::MODEL_TYPE::MOS6;
case TYPE::NMOS_BSIM3:
case TYPE::PMOS_BSIM3: return NGSPICE::MODEL_TYPE::BSIM3;
case TYPE::NMOS_MOS9:
case TYPE::PMOS_MOS9: return NGSPICE::MODEL_TYPE::MOS9;
case TYPE::NMOS_B4SOI:
case TYPE::PMOS_B4SOI: return NGSPICE::MODEL_TYPE::B4SOI;
case TYPE::NMOS_BSIM4:
case TYPE::PMOS_BSIM4: return NGSPICE::MODEL_TYPE::BSIM4;
case TYPE::NMOS_B3SOIFD:
case TYPE::PMOS_B3SOIFD: return NGSPICE::MODEL_TYPE::B3SOIFD;
case TYPE::NMOS_B3SOIDD:
case TYPE::PMOS_B3SOIDD: return NGSPICE::MODEL_TYPE::B3SOIDD;
case TYPE::NMOS_B3SOIPD:
case TYPE::PMOS_B3SOIPD: return NGSPICE::MODEL_TYPE::B3SOIPD;
case TYPE::NMOS_HISIM2:
case TYPE::PMOS_HISIM2: return NGSPICE::MODEL_TYPE::HISIM2;
case TYPE::NMOS_HISIM_HV1:
case TYPE::PMOS_HISIM_HV1: return NGSPICE::MODEL_TYPE::HISIMHV1;
case TYPE::NMOS_HISIM_HV2:
case TYPE::PMOS_HISIM_HV2: return NGSPICE::MODEL_TYPE::HISIMHV2;
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_NGSPICE" );
return NGSPICE::MODEL_TYPE::NONE;
}
}
bool SIM_MODEL_NGSPICE::getIsOtherVariant()
{
switch( GetType() )
{
case TYPE::PNP_GUMMEL_POON:
case TYPE::PNP_VBIC:
case TYPE::PNP_HICUM_L2:
case TYPE::PJF_SHICHMAN_HODGES:
case TYPE::PJF_PARKER_SKELLERN:
case TYPE::PMES_STATZ:
case TYPE::PMES_YTTERDAL:
case TYPE::PMES_HFET1:
case TYPE::PMES_HFET2:
case TYPE::PMOS_MOS1:
case TYPE::PMOS_MOS2:
case TYPE::PMOS_MOS3:
case TYPE::PMOS_BSIM1:
case TYPE::PMOS_BSIM2:
case TYPE::PMOS_MOS6:
case TYPE::PMOS_BSIM3:
case TYPE::PMOS_MOS9:
case TYPE::PMOS_B4SOI:
case TYPE::PMOS_BSIM4:
case TYPE::PMOS_B3SOIFD:
case TYPE::PMOS_B3SOIDD:
case TYPE::PMOS_B3SOIPD:
case TYPE::PMOS_HISIM2:
case TYPE::PMOS_HISIM_HV1:
case TYPE::PMOS_HISIM_HV2:
return true;
default:
return false;
}
}

View File

@ -0,0 +1,44 @@
/*
* 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_MODEL_NGSPICE_H
#define SIM_MODEL_NGSPICE_H
#include <sim/sim_model.h>
#include <sim/ngspice.h>
class SIM_MODEL_NGSPICE : public SIM_MODEL
{
public:
SIM_MODEL_NGSPICE( TYPE aType );
void WriteCode( wxString& aCode ) override;
private:
NGSPICE::MODEL_TYPE getModelType();
bool getIsOtherVariant();
};
#endif /* SIM_MODEL_NGSPICE_H */

View File

@ -0,0 +1,36 @@
/*
* 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_model_rawspice.h>
SIM_MODEL_RAWSPICE::SIM_MODEL_RAWSPICE( TYPE aType ) : SIM_MODEL( aType )
{
}
void SIM_MODEL_RAWSPICE::WriteCode( wxString& aCode )
{
// TODO
}

View File

@ -0,0 +1,39 @@
/*
* 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_MODEL_RAWSPICE_H
#define SIM_MODEL_RAWSPICE_H
#include <sim/sim_model.h>
class SIM_MODEL_RAWSPICE : public SIM_MODEL
{
public:
SIM_MODEL_RAWSPICE( TYPE aType );
void WriteCode( wxString& aCode ) override;
};
#endif // SIM_MODEL_RAWSPICE_H

View File

@ -0,0 +1,690 @@
/*
* 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_model_source.h>
using PARAM = SIM_MODEL::PARAM;
SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType ) : SIM_MODEL( aType )
{
for( const PARAM::INFO& paramInfo : makeParams( aType ) )
Params().emplace_back( paramInfo );
}
const std::vector<PARAM::INFO>& SIM_MODEL_SOURCE::makeParams( TYPE aType )
{
static std::vector<PARAM::INFO> vpulse = makePulse( "v", "V" );
static std::vector<PARAM::INFO> ipulse = makePulse( "i", "A" );
static std::vector<PARAM::INFO> vsin = makeSin( "v", "V" );
static std::vector<PARAM::INFO> isin = makeSin( "i", "A" );
static std::vector<PARAM::INFO> vexp = makeExp( "v", "V" );
static std::vector<PARAM::INFO> iexp = makeExp( "i", "A" );
static std::vector<PARAM::INFO> vsfam = makeSfam( "v", "V" );
static std::vector<PARAM::INFO> isfam = makeSfam( "i", "A" );
static std::vector<PARAM::INFO> vsffm = makeSffm( "v", "V" );
static std::vector<PARAM::INFO> isffm = makeSffm( "i", "A" );
static std::vector<PARAM::INFO> vpwl = makePwl( "v", "Voltage", "V" );
static std::vector<PARAM::INFO> ipwl = makePwl( "i", "Current", "A" );
static std::vector<PARAM::INFO> vwhitenoise = makeWhiteNoise( "v", "V" );
static std::vector<PARAM::INFO> iwhitenoise = makeWhiteNoise( "i", "A" );
static std::vector<PARAM::INFO> vpinknoise = makePinkNoise( "v", "V" );
static std::vector<PARAM::INFO> ipinknoise = makePinkNoise( "i", "A" );
static std::vector<PARAM::INFO> vburstnoise = makeBurstNoise( "v", "V" );
static std::vector<PARAM::INFO> iburstnoise = makeBurstNoise( "i", "A" );
static std::vector<PARAM::INFO> vrandomuniform = makeRandomUniform( "v", "V" );
static std::vector<PARAM::INFO> irandomuniform = makeRandomUniform( "i", "A" );
static std::vector<PARAM::INFO> vrandomnormal = makeRandomNormal( "v", "V" );
static std::vector<PARAM::INFO> irandomnormal = makeRandomNormal( "i", "A" );
static std::vector<PARAM::INFO> vrandomexp = makeRandomExp( "v", "V" );
static std::vector<PARAM::INFO> irandomexp = makeRandomExp( "i", "A" );
static std::vector<PARAM::INFO> vrandompoisson = makeRandomPoisson( "v", "V" );
static std::vector<PARAM::INFO> irandompoisson = makeRandomPoisson( "i", "A" );
switch( aType )
{
case TYPE::VSOURCE_PULSE: return vpulse;
case TYPE::ISOURCE_PULSE: return ipulse;
case TYPE::VSOURCE_SIN: return vsin;
case TYPE::ISOURCE_SIN: return isin;
case TYPE::VSOURCE_EXP: return vexp;
case TYPE::ISOURCE_EXP: return iexp;
case TYPE::VSOURCE_SFAM: return vsfam;
case TYPE::ISOURCE_SFAM: return isfam;
case TYPE::VSOURCE_SFFM: return vsffm;
case TYPE::ISOURCE_SFFM: return isffm;
case TYPE::VSOURCE_PWL: return vpwl;
case TYPE::ISOURCE_PWL: return ipwl;
case TYPE::VSOURCE_WHITE_NOISE: return vwhitenoise;
case TYPE::ISOURCE_WHITE_NOISE: return iwhitenoise;
case TYPE::VSOURCE_PINK_NOISE: return vpinknoise;
case TYPE::ISOURCE_PINK_NOISE: return ipinknoise;
case TYPE::VSOURCE_BURST_NOISE: return vburstnoise;
case TYPE::ISOURCE_BURST_NOISE: return iburstnoise;
case TYPE::VSOURCE_RANDOM_UNIFORM: return vrandomuniform;
case TYPE::ISOURCE_RANDOM_UNIFORM: return irandomuniform;
case TYPE::VSOURCE_RANDOM_NORMAL: return vrandomnormal;
case TYPE::ISOURCE_RANDOM_NORMAL: return irandomnormal;
case TYPE::VSOURCE_RANDOM_EXP: return vrandomexp;
case TYPE::ISOURCE_RANDOM_EXP: return irandomexp;
case TYPE::VSOURCE_RANDOM_POISSON: return vrandompoisson;
case TYPE::ISOURCE_RANDOM_POISSON: return irandompoisson;
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_SOURCE" );
static std::vector<PARAM::INFO> empty;
return empty;
}
}
void SIM_MODEL_SOURCE::WriteCode( wxString& aCode )
{
// TODO
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makePulse( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = aPrefix + "1";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Initial value";
paramInfos.push_back( paramInfo );
paramInfo.name = aPrefix + "2";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Initial value";
paramInfos.push_back( paramInfo );
paramInfo.name = "td";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Delay";
paramInfos.push_back( paramInfo );
paramInfo.name = "tr";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "tstep";
paramInfo.description = "Rise time";
paramInfos.push_back( paramInfo );
paramInfo.name = "tf";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "tstep";
paramInfo.description = "Fall time";
paramInfos.push_back( paramInfo );
paramInfo.name = "pw";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "tstop";
paramInfo.description = "Pulse width";
paramInfos.push_back( paramInfo );
paramInfo.name = "per";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "tstop";
paramInfo.description = "Period";
paramInfos.push_back( paramInfo );
paramInfo.name = "phase";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "deg";
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Phase";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeSin( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = aPrefix + "o";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "DC offset";
paramInfos.push_back( paramInfo );
paramInfo.name = aPrefix + "a";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Amplitude";
paramInfos.push_back( paramInfo );
paramInfo.name = "freq";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "Hz";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "1/tstop";
paramInfo.description = "Frequency";
paramInfos.push_back( paramInfo );
paramInfo.name = "td";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Delay";
paramInfos.push_back( paramInfo );
paramInfo.name = "theta";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "1/s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Damping factor";
paramInfos.push_back( paramInfo );
paramInfo.name = "phase";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "deg";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Phase";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeExp( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = aPrefix + "1";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Initial value";
paramInfos.push_back( paramInfo );
paramInfo.name = aPrefix + "2";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Pulsed value";
paramInfos.push_back( paramInfo );
paramInfo.name = "td1";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Rise delay time";
paramInfos.push_back( paramInfo );
paramInfo.name = "tau1";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "tstep";
paramInfo.description = "Rise time constant";
paramInfos.push_back( paramInfo );
paramInfo.name = "td2";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "td1+tstep";
paramInfo.description = "Fall delay time";
paramInfos.push_back( paramInfo );
paramInfo.name = "tau2";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "tstep";
paramInfo.description = "Fall time constant";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeSfam( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = aPrefix + "o";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "DC offset";
paramInfo.name = aPrefix + "a";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Amplitude";
paramInfos.push_back( paramInfo );
paramInfo.name = "mo";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Modulating signal offset";
paramInfos.push_back( paramInfo );
paramInfo.name = "fc";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "Hz";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Carrier frequency";
paramInfos.push_back( paramInfo );
paramInfo.name = "mf";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "Hz";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Modulating frequency";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeSffm( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = aPrefix + "o";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "DC offset";
paramInfos.push_back( paramInfo );
paramInfo.name = aPrefix + "a";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Amplitude";
paramInfos.push_back( paramInfo );
paramInfo.name = "fc";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "Hz";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "1/tstop";
paramInfo.description = "Carrier frequency";
paramInfos.push_back( paramInfo );
paramInfo.name = "mdi";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Modulation index";
paramInfos.push_back( paramInfo );
paramInfo.name = "fs";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "Hz";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "1/tstop";
paramInfo.description = "Signal frequency";
paramInfos.push_back( paramInfo );
paramInfo.name = "phasec";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "deg";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Carrier phase";
paramInfos.push_back( paramInfo );
paramInfo.name = "phases";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "deg";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Signal phase";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makePwl( wxString aPrefix, wxString aQuantity,
wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = "t";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT_VECTOR;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Time vector";
paramInfos.push_back( paramInfo );
paramInfo.name = aPrefix;
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT_VECTOR;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = aQuantity + " vector";
paramInfos.push_back( paramInfo );
paramInfo.name = "repeat";
paramInfo.type = SIM_VALUE_BASE::TYPE::BOOL;
paramInfo.unit = "";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "Repeat forever";
paramInfos.push_back( paramInfo );
paramInfo.name = "td";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Delay";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeWhiteNoise( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = aPrefix + "o";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "";
paramInfo.description = "DC offset";
paramInfos.push_back( paramInfo );
paramInfo.name = "na";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "White noise RMS amplitude";
paramInfos.push_back( paramInfo );
paramInfo.name = "rtsam";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Burst noise amplitude";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makePinkNoise( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = "nalpha";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "1/f noise exponent";
paramInfos.push_back( paramInfo );
paramInfo.name = "namp";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "1/f noise RMS amplitude";
paramInfos.push_back( paramInfo );
paramInfo.name = "nt";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Time step";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeBurstNoise( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = "rtscapt";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Burst noise trap capture time";
paramInfos.push_back( paramInfo );
paramInfo.name = "rtsemt";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Burst noise trap emission time";
paramInfos.push_back( paramInfo );
paramInfo.name = "nt";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Time step";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeRandomUniform( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = "min";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "-0.5";
paramInfo.description = "Min. value";
paramInfos.push_back( paramInfo );
paramInfo.name = "max";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0.5";
paramInfo.description = "Max. value";
paramInfos.push_back( paramInfo );
paramInfo.name = "td";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Delay";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeRandomNormal( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = "mean";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Mean";
paramInfos.push_back( paramInfo );
paramInfo.name = "stddev";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "1";
paramInfo.description = "Standard deviation";
paramInfos.push_back( paramInfo );
paramInfo.name = "td";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Delay";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeRandomExp( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = "offset";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Offset";
paramInfos.push_back( paramInfo );
paramInfo.name = "mean";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "1";
paramInfo.description = "Mean";
paramInfos.push_back( paramInfo );
paramInfo.name = "td";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Delay";
paramInfos.push_back( paramInfo );
return paramInfos;
}
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeRandomPoisson( wxString aPrefix, wxString aUnit )
{
std::vector<PARAM::INFO> paramInfos;
PARAM::INFO paramInfo;
paramInfo.name = "offset";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Offset";
paramInfos.push_back( paramInfo );
paramInfo.name = "lambda";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = aUnit;
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "1";
paramInfo.description = "Mean";
paramInfos.push_back( paramInfo );
paramInfo.name = "td";
paramInfo.type = SIM_VALUE_BASE::TYPE::FLOAT;
paramInfo.unit = "s";
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
paramInfo.defaultValue = "0";
paramInfo.description = "Delay";
paramInfos.push_back( paramInfo );
return paramInfos;
}

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_MODEL_SOURCE_H
#define SIM_MODEL_SOURCE_H
#include <sim/sim_model.h>
class SIM_MODEL_SOURCE : public SIM_MODEL
{
public:
SIM_MODEL_SOURCE( TYPE aType );
void WriteCode( wxString& aCode ) override;
private:
static const std::vector<PARAM::INFO>& makeParams( TYPE aType );
static std::vector<PARAM::INFO> makePulse( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makeSin( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makeExp( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makeSfam( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makeSffm( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makePwl( wxString aPrefix, wxString aQuantity, wxString aUnit );
static std::vector<PARAM::INFO> makeWhiteNoise( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makePinkNoise( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makeBurstNoise( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makeRandomUniform( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makeRandomNormal( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makeRandomExp( wxString aPrefix, wxString aUnit );
static std::vector<PARAM::INFO> makeRandomPoisson( wxString aPrefix, wxString aUnit );
};
#endif // SIM_MODEL_SOURCE_H

View File

@ -0,0 +1,35 @@
/*
* 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_model_subcircuit.h>
SIM_MODEL_SUBCIRCUIT::SIM_MODEL_SUBCIRCUIT( TYPE aType ) : SIM_MODEL( aType )
{
}
void SIM_MODEL_SUBCIRCUIT::WriteCode( wxString& aCode )
{
// TODO
}

View File

@ -0,0 +1,39 @@
/*
* 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_MODEL_SUBCIRCUIT_H
#define SIM_MODEL_SUBCIRCUIT_H
#include <sim/sim_model.h>
class SIM_MODEL_SUBCIRCUIT : public SIM_MODEL
{
public:
SIM_MODEL_SUBCIRCUIT( TYPE aType );
void WriteCode( wxString& aCode ) override;
};
#endif // SIM_MODEL_SUBCIRCUIT_H

143
eeschema/sim/sim_value.cpp Normal file
View File

@ -0,0 +1,143 @@
/*
* 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_value.h>
#include <locale_io.h>
#include <complex>
std::unique_ptr<SIM_VALUE_BASE> SIM_VALUE_BASE::Create( TYPE aType, wxString aString )
{
std::unique_ptr<SIM_VALUE_BASE> value = SIM_VALUE_BASE::Create( aType );
value->FromString( aString );
return value;
}
std::unique_ptr<SIM_VALUE_BASE> SIM_VALUE_BASE::Create( TYPE aType )
{
switch( aType )
{
case TYPE::BOOL: return std::make_unique<SIM_VALUE<bool>>();
case TYPE::INT: return std::make_unique<SIM_VALUE<long>>();
case TYPE::FLOAT: return std::make_unique<SIM_VALUE<double>>();
case TYPE::COMPLEX: return std::make_unique<SIM_VALUE<std::complex<double>>>();
case TYPE::STRING: return std::make_unique<SIM_VALUE<wxString>>();
case TYPE::BOOL_VECTOR: return std::make_unique<SIM_VALUE<bool>>();
case TYPE::INT_VECTOR: return std::make_unique<SIM_VALUE<long>>();
case TYPE::FLOAT_VECTOR: return std::make_unique<SIM_VALUE<double>>();
case TYPE::COMPLEX_VECTOR: return std::make_unique<SIM_VALUE<std::complex<double>>>();
}
wxFAIL_MSG( "Unknown SIM_VALUE type" );
return nullptr;
}
void SIM_VALUE_BASE::operator=( const wxString& aString )
{
FromString( aString );
}
template <typename T>
SIM_VALUE<T>::SIM_VALUE( const T& aValue ) : m_value(aValue)
{
}
template <typename T>
void SIM_VALUE<T>::FromString( const wxString& aString )
{
LOCALE_IO toggle;
}
template <typename T>
wxString SIM_VALUE<T>::ToString() const
{
static_assert( std::is_same<T, std::vector<T>>::value );
wxString string = "";
for( auto it = m_value.cbegin(); it != m_value.cend(); it++ )
{
string += SIM_VALUE<T>( *it ).ToString();
string += ",";
}
return string;
}
template <>
wxString SIM_VALUE<bool>::ToString() const
{
LOCALE_IO toggle;
return wxString::Format( "%d", m_value );
}
template <>
wxString SIM_VALUE<long>::ToString() const
{
LOCALE_IO toggle;
return wxString::Format( "%d", m_value );
}
template <>
wxString SIM_VALUE<double>::ToString() const
{
LOCALE_IO toggle;
return wxString::Format( "%f", m_value );
}
template <>
wxString SIM_VALUE<std::complex<double>>::ToString() const
{
LOCALE_IO toggle;
return wxString::Format( "%f+%fi", m_value.real(), m_value.imag() );
}
template <>
wxString SIM_VALUE<wxString>::ToString() const
{
LOCALE_IO toggle;
return m_value;
}
template <typename T>
bool SIM_VALUE<T>::operator==( const SIM_VALUE_BASE& aOther ) const
{
const SIM_VALUE* otherNumber = dynamic_cast<const SIM_VALUE*>( &aOther );
if( otherNumber )
return m_value == otherNumber->m_value;
return false;
}

76
eeschema/sim/sim_value.h Normal file
View File

@ -0,0 +1,76 @@
/*
* 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_VALUE_H
#define SIM_VALUE_H
#include <memory>
#include <wx/string.h>
class SIM_VALUE_BASE
{
public:
enum class TYPE
{
BOOL,
INT,
FLOAT,
COMPLEX,
STRING,
BOOL_VECTOR,
INT_VECTOR,
FLOAT_VECTOR,
COMPLEX_VECTOR
};
static std::unique_ptr<SIM_VALUE_BASE> Create( TYPE aType, wxString aString );
static std::unique_ptr<SIM_VALUE_BASE> Create( TYPE aType );
void operator=( const wxString& aString );
virtual bool operator==( const SIM_VALUE_BASE& aOther ) const = 0;
virtual void FromString( const wxString& aString ) = 0;
virtual wxString ToString() const = 0;
};
template <typename T>
class SIM_VALUE : public SIM_VALUE_BASE
{
public:
SIM_VALUE() = default;
SIM_VALUE( const T& aValue );
void FromString( const wxString& aString ) override;
wxString ToString() const override;
void operator=( const T& aValue );
bool operator==( const SIM_VALUE_BASE& aOther ) const override;
private:
T m_value;
};
#endif /* SIM_VALUE_H */

View File

@ -1,309 +0,0 @@
/*
* 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 <iterator>
#include <sim/spice_model.h>
#include <pegtl.hpp>
#include <pegtl/contrib/parse_tree.hpp>
#include <locale_io.h>
#include <lib_symbol.h>
/*namespace SPICE_MODEL_PARSER
{
using namespace tao::pegtl;
struct directive : sor<TAO_PEGTL_ISTRING( ".model" ),
TAO_PEGTL_ISTRING( ".param" ),
TAO_PEGTL_ISTRING( ".subckt" )> {};*//*
struct spaces : star<space> {};
struct identifierNotFirstChar : sor<alnum, one<'!', '#', '$', '%', '[', ']', '_'>> {};
struct identifier : seq<alpha, star<identifierNotFirstChar>> {};
struct digits : plus<digit> {};
struct sign : opt<one<'+', '-'>> {};
struct significand : sor<seq<digits, one<'.'>, opt<digits>>, seq<one<'.'>, digits>> {};
struct exponent : opt<one<'e', 'E'>, sign, digits> {};
struct metricSuffix : sor<TAO_PEGTL_ISTRING( "T" ),
TAO_PEGTL_ISTRING( "G" ),
TAO_PEGTL_ISTRING( "Meg" ),
TAO_PEGTL_ISTRING( "K" ),
TAO_PEGTL_ISTRING( "mil" ),
TAO_PEGTL_ISTRING( "m" ),
TAO_PEGTL_ISTRING( "u" ),
TAO_PEGTL_ISTRING( "n" ),
TAO_PEGTL_ISTRING( "p" ),
TAO_PEGTL_ISTRING( "f" )> {};
struct number : seq<sign, significand, exponent, metricSuffix> {};
struct modelModelType : 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 paramValuePair : seq<alnum, spaces, one<'='>, spaces, number> {};
struct paramValuePairs : opt<paramValuePair, star<spaces, paramValuePair>> {};
struct modelModelSpec : seq<modelModelType,
spaces,
one<'('>,
spaces,
paramValuePairs,
spaces,
one<')'>,
spaces> {};
struct modelModel : seq<TAO_PEGTL_ISTRING( ".model" ), identifier, modelModelSpec> {};
struct model : modelModel {};
//struct model : sor<modelModel, paramModel, subcircuitModel> {};
}*/
namespace SPICE_MODEL_PARSER
{
using namespace tao::pegtl;
struct spaces : star<space> {};
struct digits : plus<digit> {};
struct sign : opt<one<'+', '-'>> {};
struct significand : sor<seq<digits, opt<one<'.'>, opt<digits>>>, seq<one<'.'>, digits>> {};
struct exponent : opt<one<'e', 'E'>, sign, digits> {};
struct metricSuffix : opt<sor<TAO_PEGTL_ISTRING( "T" ),
TAO_PEGTL_ISTRING( "G" ),
TAO_PEGTL_ISTRING( "Meg" ),
TAO_PEGTL_ISTRING( "K" ),
TAO_PEGTL_ISTRING( "mil" ),
TAO_PEGTL_ISTRING( "m" ),
TAO_PEGTL_ISTRING( "u" ),
TAO_PEGTL_ISTRING( "n" ),
TAO_PEGTL_ISTRING( "p" ),
TAO_PEGTL_ISTRING( "f" )>> {};
// TODO: Move the `number` grammar to the SPICE_VALUE class.
struct number : seq<sign, significand, exponent, metricSuffix> {};
struct param : seq<alnum> {};
struct paramValuePair : seq<param, spaces, one<'='>, spaces, number> {};
struct paramValuePairs : opt<paramValuePair, star<spaces, paramValuePair>> {};
template <typename Rule> struct paramValuePairsSelector : std::false_type {};
template <> struct paramValuePairsSelector<param> : std::true_type {};
template <> struct paramValuePairsSelector<number> : std::true_type {};
}
template SPICE_MODEL::TYPE SPICE_MODEL::ReadTypeFromFields( const std::vector<SCH_FIELD>* aFields );
template SPICE_MODEL::TYPE SPICE_MODEL::ReadTypeFromFields( const std::vector<LIB_FIELD>* aFields );
template <typename T>
SPICE_MODEL::TYPE SPICE_MODEL::ReadTypeFromFields( const std::vector<T>* aFields )
{
wxString typeFieldValue = getFieldValue( aFields, TYPE_FIELD );
wxString deviceTypeFieldValue = getFieldValue( aFields, DEVICE_TYPE_FIELD );
bool typeFound = false;
for( TYPE type : TYPE_ITERATOR() )
{
if( typeFieldValue == TypeInfo( type ).fieldValue )
{
typeFound = true;
if( deviceTypeFieldValue == DeviceTypeInfo( TypeInfo( type ).deviceType ).fieldValue )
return type;
}
}
if( !typeFound )
throw KI_PARAM_ERROR( wxString::Format( _( "Invalid \"%s\" field value: \"%s\"" ),
TYPE_FIELD, typeFieldValue ) );
throw KI_PARAM_ERROR( wxString::Format( _( "Invalid \"%s\" field value: \"%s\"" ),
DEVICE_TYPE_FIELD, deviceTypeFieldValue ) );
}
SPICE_MODEL::SPICE_MODEL( TYPE aType ) : m_type( aType )
{
}
template SPICE_MODEL::SPICE_MODEL( const std::vector<SCH_FIELD>* aFields );
template SPICE_MODEL::SPICE_MODEL( const std::vector<LIB_FIELD>* aFields );
template <typename T>
SPICE_MODEL::SPICE_MODEL( const std::vector<T>* aFields )
: m_type( ReadTypeFromFields( aFields ) )
{
SetFile( getFieldValue( aFields, "Model_File" ) );
parseParamValuePairs( getFieldValue( aFields, "Model_Params" ) );
}
SPICE_MODEL::SPICE_MODEL( const wxString& aCode )
{
}
template void SPICE_MODEL::WriteFields( std::vector<SCH_FIELD>* aFields );
template void SPICE_MODEL::WriteFields( std::vector<LIB_FIELD>* aFields );
template <typename T>
void SPICE_MODEL::WriteFields( std::vector<T>* aFields )
{
setFieldValue( aFields, DEVICE_TYPE_FIELD,
DeviceTypeInfo( TypeInfo( m_type ).deviceType ).fieldValue );
setFieldValue( aFields, TYPE_FIELD, TypeInfo( m_type ).fieldValue );
setFieldValue( aFields, FILE_FIELD, GetFile() );
setFieldValue( aFields, PARAMS_FIELD, generateParamValuePairs() );
}
void SPICE_MODEL::WriteCode( wxString& aCode )
{
}
void SPICE_MODEL::parseParamValuePairs( const wxString& aParamValuePairs )
{
LOCALE_IO toggle;
tao::pegtl::string_input<> in( aParamValuePairs.ToStdString(), "from_input" );
auto root = tao::pegtl::parse_tree::parse<SPICE_MODEL_PARSER::paramValuePairs,
SPICE_MODEL_PARSER::paramValuePairsSelector>( in );
wxString paramName = "";
for( const auto& node : root->children )
{
if( node->is_type<SPICE_MODEL_PARSER::param>() )
paramName = node->string();
else if( node->is_type<SPICE_MODEL_PARSER::number>() )
{
wxASSERT( paramName != "" );
try
{
SPICE_VALUE value( node->string() );
/*if( !SetParamValue( paramName, value ) )
{
m_params.clear();
throw KI_PARAM_ERROR( wxString::Format( _( "Unknown parameter \"%s\"" ),
paramName ) );
}*/
}
catch( KI_PARAM_ERROR& e )
{
m_params.clear();
throw KI_PARAM_ERROR( wxString::Format( _( "Invalid \"%s\" parameter value: \"%s\"" ),
paramName, e.What() ) );
}
}
else
wxFAIL;
}
}
wxString SPICE_MODEL::generateParamValuePairs()
{
wxString result = "";
/*for( auto it = GetParams().cbegin(); it != GetParams().cend(); it++ )
{
result += it->first;
result += "=";
result += it->second.value.ToString();
if( std::next( it ) != GetParams().cend() )
result += " ";
}*/
return result;
}
template <typename T>
wxString SPICE_MODEL::getFieldValue( const std::vector<T>* aFields, const wxString& aFieldName )
{
static_assert( std::is_same<T, SCH_FIELD>::value || std::is_same<T, LIB_FIELD>::value );
auto fieldIt = std::find_if( aFields->begin(), aFields->end(),
[&]( const T& f )
{
return f.GetName() == aFieldName;
} );
if( fieldIt != aFields->end() )
return fieldIt->GetText();
return wxEmptyString;
}
template <typename T>
void SPICE_MODEL::setFieldValue( std::vector<T>* aFields, const wxString& aFieldName,
const wxString& aValue )
{
static_assert( std::is_same<T, SCH_FIELD>::value || std::is_same<T, LIB_FIELD>::value );
auto fieldIt = std::find_if( aFields->begin(), aFields->end(),
[&]( const T& f )
{
return f.GetName() == aFieldName;
} );
if( fieldIt != aFields->end() )
{
fieldIt->SetText( aValue );
return;
}
if constexpr( std::is_same<T, SCH_FIELD>::value )
{
wxASSERT( aFields->size() >= 1 );
SCH_ITEM* parent = static_cast<SCH_ITEM*>( aFields->at( 0 ).GetParent() );
aFields->emplace_back( wxPoint(), aFields->size(), parent, aFieldName );
}
else if constexpr( std::is_same<T, LIB_FIELD>::value )
aFields->emplace_back( aFields->size(), aFieldName );
aFields->back().SetText( aValue );
}

View File

@ -1,287 +0,0 @@
/*
* 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_MODEL_H
#define SPICE_MODEL_H
#include <map>
#include <stdexcept>
#include <enum_vector.h>
#include <sch_field.h>
#include <lib_field.h>
#include <sim/ngspice.h>
#include <sim/spice_value.h>
#include <wx/string.h>
class SPICE_MODEL
{
public:
static constexpr auto DEVICE_TYPE_FIELD = "Model_Device";
static constexpr auto TYPE_FIELD = "Model_Type";
static constexpr auto FILE_FIELD = "Model_File";
static constexpr auto PARAMS_FIELD = "Model_Params";
/*struct PARAM
{
SPICE_VALUE value;
wxString description;
wxString unit;
};*/
DEFINE_ENUM_CLASS_WITH_ITERATOR( DEVICE_TYPE,
NONE,
RESISTOR,
CAPACITOR,
INDUCTOR,
TLINE,
DIODE,
BJT,
JFET,
MESFET,
MOSFET,
VSOURCE,
ISOURCE,
SUBCIRCUIT,
CODEMODEL,
RAWSPICE
)
struct DEVICE_TYPE_INFO
{
wxString fieldValue;
wxString description;
};
static DEVICE_TYPE_INFO DeviceTypeInfo( DEVICE_TYPE aDeviceType )
{
switch( aDeviceType )
{
case DEVICE_TYPE::NONE: return {"", ""};
case DEVICE_TYPE::RESISTOR: return {"RESISTOR", "Resistor"};
case DEVICE_TYPE::CAPACITOR: return {"CAPACITOR", "Capacitor"};
case DEVICE_TYPE::INDUCTOR: return {"INDUCTOR", "Inductor"};
case DEVICE_TYPE::TLINE: return {"TLINE", "Transmission Line"};
case DEVICE_TYPE::DIODE: return {"DIODE", "Diode"};
case DEVICE_TYPE::BJT: return {"BJT", "BJT"};
case DEVICE_TYPE::JFET: return {"JFET", "JFET"};
case DEVICE_TYPE::MOSFET: return {"MOSFET", "MOSFET"};
case DEVICE_TYPE::MESFET: return {"MESFET", "MESFET"};
case DEVICE_TYPE::VSOURCE: return {"VSOURCE", "Voltage Source"};
case DEVICE_TYPE::ISOURCE: return {"ISOURCE", "Current Source"};
case DEVICE_TYPE::SUBCIRCUIT: return {"SUBCIRCUIT", "Subcircuit"};
case DEVICE_TYPE::CODEMODEL: return {"CODEMODEL", "Code Model"};
case DEVICE_TYPE::RAWSPICE: return {"RAWSPICE", "Raw Spice Element"};
case DEVICE_TYPE::_ENUM_END: break;
}
wxFAIL;
return {};
}
DEFINE_ENUM_CLASS_WITH_ITERATOR( TYPE,
NONE,
RESISTOR_IDEAL,
RESISTOR_SEMICONDUCTOR,
CAPACITOR_IDEAL,
CAPACITOR_SEMICONDUCTOR,
INDUCTOR_IDEAL,
INDUCTOR_IDEAL_COIL,
TLINE_LOSSY,
TLINE_LOSSLESS,
TLINE_DISTRIBUTED_RC,
TLINE_KSPICE_LOSSY,
DIODE,
BJT_GUMMEL_POON,
BJT_VBIC,
//BJT_MEXTRAM,
BJT_HICUM_L2,
//BJT_HICUM_L0,
JFET_SHICHMAN_HODGES,
JFET_PARKER_SKELLERN,
MESFET_STATZ,
MESFET_YTTERDAL,
MESFET_HFET1,
MESFET_HFET2,
MOSFET_MOS1,
MOSFET_MOS2,
MOSFET_MOS3,
MOSFET_BSIM1,
MOSFET_BSIM2,
MOSFET_MOS6,
MOSFET_MOS9,
MOSFET_BSIM3,
MOSFET_B4SOI,
MOSFET_BSIM4,
//MOSFET_EKV2_6,
//MOSFET_PSP,
MOSFET_B3SOIFD,
MOSFET_B3SOIDD,
MOSFET_B3SOIPD,
//MOSFET_STAG,
MOSFET_HISIM2,
MOSFET_HISIM_HV,
VSOURCE,
ISOURCE,
SUBCIRCUIT,
CODEMODEL,
RAWSPICE
)
struct TYPE_INFO
{
DEVICE_TYPE deviceType;
//NGSPICE::MODEL_TYPE ngspiceModelType;
wxString ngspicePrimitive;
unsigned int ngspiceLevel;
wxString fieldValue;
wxString description;
};
static TYPE_INFO TypeInfo( TYPE aType )
{
switch( aType )
{
case TYPE::NONE: return { DEVICE_TYPE::NONE, "", 0, "", "" };
case TYPE::RESISTOR_IDEAL: return { DEVICE_TYPE::RESISTOR, "R", 0, "IDEAL", "Ideal model" };
case TYPE::RESISTOR_SEMICONDUCTOR: return { DEVICE_TYPE::RESISTOR, "R", 0, "SEMICONDUCTOR", "Semiconductor model" };
case TYPE::CAPACITOR_IDEAL: return { DEVICE_TYPE::CAPACITOR, "C", 0, "IDEAL", "Ideal model" };
case TYPE::CAPACITOR_SEMICONDUCTOR: return { DEVICE_TYPE::CAPACITOR, "C", 0, "SEMICONDUCTOR", "Semiconductor model" };
case TYPE::INDUCTOR_IDEAL: return { DEVICE_TYPE::INDUCTOR, "L", 0, "IDEAL", "Ideal model" };
case TYPE::INDUCTOR_IDEAL_COIL: return { DEVICE_TYPE::INDUCTOR, "L", 0, "LOSSLESS_COIL", "Lossless coil model" };
case TYPE::TLINE_LOSSY: return { DEVICE_TYPE::TLINE, "O", 0, "LOSSY", "Lossy model" };
case TYPE::TLINE_LOSSLESS: return { DEVICE_TYPE::TLINE, "T", 0, "LOSSLESS", "Lossless model" };
case TYPE::TLINE_DISTRIBUTED_RC: return { DEVICE_TYPE::TLINE, "U", 0, "DISTRIBUTED_RC", "Uniformly distributed RC model" };
case TYPE::TLINE_KSPICE_LOSSY: return { DEVICE_TYPE::TLINE, "Y", 0, "KSPICE_LOSSY", "KSPICE lossy model" };
case TYPE::DIODE: return { DEVICE_TYPE::DIODE, "D", 0, "", "" };
case TYPE::BJT_GUMMEL_POON: return { DEVICE_TYPE::BJT, "Q", 1, "GUMMEL_POON", "Gummel-Poon model" };
case TYPE::BJT_VBIC: return { DEVICE_TYPE::BJT, "Q", 4, "VBIC", "VBIC model" };
//case TYPE::BJT_MEXTRAM: return { DEVICE_TYPE::BJT, "Q", 6, "MEXTRAM", "MEXTRAM model" };
case TYPE::BJT_HICUM_L2: return { DEVICE_TYPE::BJT, "Q", 8, "HICUM_L2", "HICUM Level 2 model" };
//case TYPE::BJT_HICUM_L0: return { DEVICE_TYPE::BJT, "Q", 7, "HICUM_L0", "HICUM Level 0 model" };
case TYPE::JFET_SHICHMAN_HODGES: return { DEVICE_TYPE::JFET, "J", 1, "SHICHMAN_HODGES", "Shichman-Hodges model" };
case TYPE::JFET_PARKER_SKELLERN: return { DEVICE_TYPE::JFET, "J", 2, "PARKER_SKELLERN", "Parker-Skellern model" };
case TYPE::MESFET_STATZ: return { DEVICE_TYPE::MESFET, "Z", 1, "STATZ", "Statz model" };
case TYPE::MESFET_YTTERDAL: return { DEVICE_TYPE::MESFET, "Z", 2, "YTTERDAL", "Ytterdal model" };
case TYPE::MESFET_HFET1: return { DEVICE_TYPE::MESFET, "Z", 5, "HFET1", "HFET1 model" };
case TYPE::MESFET_HFET2: return { DEVICE_TYPE::MESFET, "Z", 6, "HFET2", "HFET2 model" };
case TYPE::MOSFET_MOS1: return { DEVICE_TYPE::MOSFET, "M", 1, "MOS1", "Classical quadratic model (MOS1)" };
case TYPE::MOSFET_MOS2: return { DEVICE_TYPE::MOSFET, "M", 2, "MOS2", "Grove-Frohman model (MOS2)" };
case TYPE::MOSFET_MOS3: return { DEVICE_TYPE::MOSFET, "M", 3, "MOS3", "MOS3 model" };
case TYPE::MOSFET_BSIM1: return { DEVICE_TYPE::MOSFET, "M", 4, "BSIM1", "BSIM1 model" };
case TYPE::MOSFET_BSIM2: return { DEVICE_TYPE::MOSFET, "M", 5, "BSIM2", "BSIM2 model" };
case TYPE::MOSFET_MOS6: return { DEVICE_TYPE::MOSFET, "M", 6, "MOS6", "MOS6 model" };
case TYPE::MOSFET_BSIM3: return { DEVICE_TYPE::MOSFET, "M", 8, "BSIM3", "BSIM3 model" };
case TYPE::MOSFET_MOS9: return { DEVICE_TYPE::MOSFET, "M", 9, "MOS9", "MOS9 model" };
case TYPE::MOSFET_B4SOI: return { DEVICE_TYPE::MOSFET, "M", 10, "B4SOI", "BSIM4 SOI model (B4SOI)" };
case TYPE::MOSFET_BSIM4: return { DEVICE_TYPE::MOSFET, "M", 14, "BSIM4", "BSIM4 model" };
//case TYPE::MOSFET_EKV2_6: return { DEVICE_TYPE::MOSFET, "M", 44, "EKV2.6", "EKV2.6 model" };
//case TYPE::MOSFET_PSP: return { DEVICE_TYPE::MOSFET, "M", 45, "PSP", "PSP model" };
case TYPE::MOSFET_B3SOIFD: return { DEVICE_TYPE::MOSFET, "M", 55, "B3SOIFD", "B3SOIFD (BSIM3 fully depleted SOI) model" };
case TYPE::MOSFET_B3SOIDD: return { DEVICE_TYPE::MOSFET, "M", 56, "B3SOIDD", "B3SOIDD (BSIM3 SOI, both fully and partially depleted) model" };
case TYPE::MOSFET_B3SOIPD: return { DEVICE_TYPE::MOSFET, "M", 57, "B3SOIPD", "B3SOIPD (BSIM3 partially depleted SOI) model" };
//case TYPE::MOSFET_STAG: return { DEVICE_TYPE::MOSFET, "M", 60, "STAG", "STAG model" };
case TYPE::MOSFET_HISIM2: return { DEVICE_TYPE::MOSFET, "M", 68, "HiSIM2", "HiSIM2 model" };
case TYPE::MOSFET_HISIM_HV: return { DEVICE_TYPE::MOSFET, "M", 73, "HiSIM_HV", "HiSIM_HV model" };
case TYPE::VSOURCE: return { DEVICE_TYPE::VSOURCE, "V", 0, "", "" };
case TYPE::ISOURCE: return { DEVICE_TYPE::ISOURCE, "V", 0, "", "" };
case TYPE::SUBCIRCUIT: return { DEVICE_TYPE::SUBCIRCUIT, "X", 0, "", "" };
case TYPE::CODEMODEL: return { DEVICE_TYPE::CODEMODEL, "A", 0, "", "" };
case TYPE::RAWSPICE: return { DEVICE_TYPE::RAWSPICE, "", 0, "", "" };
case TYPE::_ENUM_END: break;
}
wxFAIL;
return { };
}
template <typename T>
static TYPE ReadTypeFromFields( const std::vector<T>* aFields );
SPICE_MODEL( TYPE aType );
template <typename T>
SPICE_MODEL( const std::vector<T>* aFields );
SPICE_MODEL( const wxString& aCode );
template <typename T>
void WriteFields( std::vector<T>* aFields );
void WriteCode( wxString& aCode );
wxString GetFile() { return m_file; }
void SetFile( const wxString& aFile ) { m_file = aFile; }
private:
TYPE m_type;
wxString m_file;
std::map<wxString, double> m_params;
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 );
wxString generateParamValuePairs();
void parseParamValuePairs( const wxString& aParamValuePairs );
};
#endif /* SPICE_MODEL_H */

View File

@ -74,6 +74,7 @@ if( KICAD_SPICE )
set( QA_EESCHEMA_SRCS
${QA_EESCHEMA_SRCS}
# Simulation tests
sim/test_ngspice.cpp
sim/test_ngspice_helpers.cpp
)
endif()

View File

@ -0,0 +1,221 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* 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 2
* 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:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <qa_utils/wx_utils/unit_test_utils.h>
#include <sim/ngspice.h>
BOOST_AUTO_TEST_SUITE( Ngspice )
BOOST_AUTO_TEST_CASE( Models )
{
// Count the total number of model and instance parameters for each model so that there will be
// an error if someone accidentally removes a parameter.
for( NGSPICE::MODEL_TYPE type : NGSPICE::MODEL_TYPE_ITERATOR() )
{
unsigned int modelParamCount = NGSPICE::ModelInfo( type ).modelParams.size();
unsigned int instanceParamCount = NGSPICE::ModelInfo( type ).instanceParams.size();
switch( type )
{
case NGSPICE::MODEL_TYPE::NONE:
case NGSPICE::MODEL_TYPE::_ENUM_END:
break;
case NGSPICE::MODEL_TYPE::RESISTOR:
BOOST_CHECK_EQUAL( modelParamCount, 22 );
BOOST_CHECK_EQUAL( instanceParamCount, 25 );
break;
case NGSPICE::MODEL_TYPE::CAPACITOR:
BOOST_CHECK_EQUAL( modelParamCount, 19 );
BOOST_CHECK_EQUAL( instanceParamCount, 22 );
break;
case NGSPICE::MODEL_TYPE::INDUCTOR:
BOOST_CHECK_EQUAL( modelParamCount, 9 );
BOOST_CHECK_EQUAL( instanceParamCount, 20 );
break;
case NGSPICE::MODEL_TYPE::LTRA:
BOOST_CHECK_EQUAL( modelParamCount, 18 );
BOOST_CHECK_EQUAL( instanceParamCount, 9 );
break;
case NGSPICE::MODEL_TYPE::TRANLINE:
BOOST_CHECK_EQUAL( modelParamCount, 0 );
BOOST_CHECK_EQUAL( instanceParamCount, 17 );
break;
case NGSPICE::MODEL_TYPE::URC:
BOOST_CHECK_EQUAL( modelParamCount, 7 );
BOOST_CHECK_EQUAL( instanceParamCount, 5 );
break;
case NGSPICE::MODEL_TYPE::TRANSLINE:
BOOST_CHECK_EQUAL( modelParamCount, 6 );
BOOST_CHECK_EQUAL( instanceParamCount, 3 );
break;
case NGSPICE::MODEL_TYPE::DIODE:
BOOST_CHECK_EQUAL( modelParamCount, 76 );
BOOST_CHECK_EQUAL( instanceParamCount, 30 );
break;
case NGSPICE::MODEL_TYPE::BJT:
BOOST_CHECK_EQUAL( modelParamCount, 152 );
BOOST_CHECK_EQUAL( instanceParamCount, 52 );
break;
case NGSPICE::MODEL_TYPE::VBIC:
BOOST_CHECK_EQUAL( modelParamCount, 117 );
BOOST_CHECK_EQUAL( instanceParamCount, 44 );
break;
case NGSPICE::MODEL_TYPE::HICUM2:
BOOST_CHECK_EQUAL( modelParamCount, 149 );
BOOST_CHECK_EQUAL( instanceParamCount, 60 );
break;
case NGSPICE::MODEL_TYPE::JFET:
BOOST_CHECK_EQUAL( modelParamCount, 28 );
BOOST_CHECK_EQUAL( instanceParamCount, 28 );
break;
case NGSPICE::MODEL_TYPE::JFET2:
BOOST_CHECK_EQUAL( modelParamCount, 39 );
BOOST_CHECK_EQUAL( instanceParamCount, 30 );
break;
case NGSPICE::MODEL_TYPE::MES:
BOOST_CHECK_EQUAL( modelParamCount, 22 );
BOOST_CHECK_EQUAL( instanceParamCount, 25 );
break;
case NGSPICE::MODEL_TYPE::MESA:
BOOST_CHECK_EQUAL( modelParamCount, 51 );
BOOST_CHECK_EQUAL( instanceParamCount, 30 );
break;
case NGSPICE::MODEL_TYPE::HFET1:
BOOST_CHECK_EQUAL( modelParamCount, 22 );
BOOST_CHECK_EQUAL( instanceParamCount, 28 );
break;
case NGSPICE::MODEL_TYPE::HFET2:
BOOST_CHECK_EQUAL( modelParamCount, 19 );
BOOST_CHECK_EQUAL( instanceParamCount, 28 );
break;
case NGSPICE::MODEL_TYPE::MOS1:
BOOST_CHECK_EQUAL( modelParamCount, 35 );
BOOST_CHECK_EQUAL( instanceParamCount, 76 );
break;
case NGSPICE::MODEL_TYPE::MOS2:
BOOST_CHECK_EQUAL( modelParamCount, 42 );
BOOST_CHECK_EQUAL( instanceParamCount, 76 );
break;
case NGSPICE::MODEL_TYPE::MOS3:
BOOST_CHECK_EQUAL( modelParamCount, 48 );
BOOST_CHECK_EQUAL( instanceParamCount, 81 );
break;
case NGSPICE::MODEL_TYPE::BSIM1:
BOOST_CHECK_EQUAL( modelParamCount, 81 );
BOOST_CHECK_EQUAL( instanceParamCount, 14 );
break;
case NGSPICE::MODEL_TYPE::BSIM2:
BOOST_CHECK_EQUAL( modelParamCount, 137 );
BOOST_CHECK_EQUAL( instanceParamCount, 14 );
break;
case NGSPICE::MODEL_TYPE::MOS6:
BOOST_CHECK_EQUAL( modelParamCount, 42 );
BOOST_CHECK_EQUAL( instanceParamCount, 78 );
break;
case NGSPICE::MODEL_TYPE::BSIM3:
BOOST_CHECK_EQUAL( modelParamCount, 429 );
BOOST_CHECK_EQUAL( instanceParamCount, 46 );
break;
case NGSPICE::MODEL_TYPE::MOS9:
BOOST_CHECK_EQUAL( modelParamCount, 48 );
BOOST_CHECK_EQUAL( instanceParamCount, 81 );
break;
case NGSPICE::MODEL_TYPE::B4SOI:
BOOST_CHECK_EQUAL( modelParamCount, 915 );
BOOST_CHECK_EQUAL( instanceParamCount, 74 );
break;
case NGSPICE::MODEL_TYPE::BSIM4:
BOOST_CHECK_EQUAL( modelParamCount, 892 );
BOOST_CHECK_EQUAL( instanceParamCount, 84 );
break;
case NGSPICE::MODEL_TYPE::B3SOIFD:
BOOST_CHECK_EQUAL( modelParamCount, 393 );
BOOST_CHECK_EQUAL( instanceParamCount, 27 );
break;
case NGSPICE::MODEL_TYPE::B3SOIDD:
BOOST_CHECK_EQUAL( modelParamCount, 393 );
BOOST_CHECK_EQUAL( instanceParamCount, 27 );
break;
case NGSPICE::MODEL_TYPE::B3SOIPD:
BOOST_CHECK_EQUAL( modelParamCount, 470 );
BOOST_CHECK_EQUAL( instanceParamCount, 36 );
break;
case NGSPICE::MODEL_TYPE::HISIM2:
BOOST_CHECK_EQUAL( modelParamCount, 486 );
BOOST_CHECK_EQUAL( instanceParamCount, 59 );
break;
case NGSPICE::MODEL_TYPE::HISIMHV1:
BOOST_CHECK_EQUAL( modelParamCount, 536 );
BOOST_CHECK_EQUAL( instanceParamCount, 66 );
break;
case NGSPICE::MODEL_TYPE::HISIMHV2:
BOOST_CHECK_EQUAL( modelParamCount, 630 );
BOOST_CHECK_EQUAL( instanceParamCount, 68 );
break;
default:
BOOST_FAIL( wxString::Format(
"Unhandled type: %d "
"(if you created a new type you need to handle it in this switch statement)",
type ) );
}
}
}
BOOST_AUTO_TEST_SUITE_END()