mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-18 20:09:18 +00:00
Sim Model Editor improvements
- Tab-switching, - Automatic expansion of categories on tab-switch, - Various minor simulation improvements, - Various new simulation-related bugfixes.
This commit is contained in:
parent
6984f63af8
commit
739b9255d9
demos/simulation/subsheets
eeschema
CMakeLists.txt
dialogs
netlist_exporters
sim
ngspice.cppngspice_helpers.cppngspice_helpers.hsim_library.cppsim_library.hsim_library_spice.cppsim_library_spice.hsim_model.cppsim_model.hsim_model_behavioral.cppsim_model_behavioral.hsim_model_ideal.cppsim_model_passive.cppsim_model_passive.hsim_model_source.cppsim_model_source.hsim_model_subckt.cppsim_model_tline.cppsim_model_tline.hsim_plot_frame.cppsim_property.cppsim_property.hsim_value.hspice_grammar.h
tools
qa
data/eeschema/spice_netlists
chirp
npn_ce_amp
opamp
rectifier
tlines
unittests/eeschema
@ -1,337 +0,0 @@
|
||||
{
|
||||
"board": {
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"board_outline_line_width": 0.1,
|
||||
"copper_line_width": 0.2,
|
||||
"copper_text_size_h": 1.5,
|
||||
"copper_text_size_v": 1.5,
|
||||
"copper_text_thickness": 0.3,
|
||||
"other_line_width": 0.15,
|
||||
"silk_line_width": 0.15,
|
||||
"silk_text_size_h": 1.0,
|
||||
"silk_text_size_v": 1.0,
|
||||
"silk_text_thickness": 0.15
|
||||
},
|
||||
"diff_pair_dimensions": [],
|
||||
"drc_exclusions": [],
|
||||
"rules": {
|
||||
"min_copper_edge_clearance": 0.0,
|
||||
"solder_mask_clearance": 0.0,
|
||||
"solder_mask_min_width": 0.0
|
||||
},
|
||||
"track_widths": [],
|
||||
"via_dimensions": []
|
||||
},
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_label_syntax": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"extra_units": "error",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_dangling": "error",
|
||||
"lib_symbol_issues": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "warning",
|
||||
"no_connect_dangling": "warning",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "warning",
|
||||
"power_pin_not_driven": "error",
|
||||
"similar_labels": "warning",
|
||||
"unannotated": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "subsheets.kicad_pro",
|
||||
"version": 1
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12.0,
|
||||
"clearance": 0.2,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.25,
|
||||
"via_diameter": 0.8,
|
||||
"via_drill": 0.4,
|
||||
"wire_width": 6.0
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 2
|
||||
},
|
||||
"net_colors": null
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"field_names": [],
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.375,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.15
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"ngspice": {
|
||||
"fix_include_paths": true,
|
||||
"fix_passive_vals": false,
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"model_mode": 0,
|
||||
"workbook_filename": ""
|
||||
},
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"e63e39d7-6ac0-4ffd-8aa3-1841a4541b55",
|
||||
""
|
||||
],
|
||||
[
|
||||
"51ab3a6c-36b1-4056-a2d2-39c83ee99c02",
|
||||
"subsheet1"
|
||||
],
|
||||
[
|
||||
"cd8140cb-ee2c-44d2-bab6-19a75f861228",
|
||||
"subsheet2"
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
}
|
@ -327,7 +327,6 @@ if( KICAD_SPICE )
|
||||
sim/sim_model_xspice.cpp
|
||||
sim/sim_model_ideal.cpp
|
||||
sim/sim_model_ngspice.cpp
|
||||
sim/sim_model_passive.cpp
|
||||
sim/sim_model_spice.cpp
|
||||
sim/sim_model_source.cpp
|
||||
sim/sim_model_subckt.cpp
|
||||
|
@ -46,8 +46,11 @@ DIALOG_SIM_MODEL<T>::DIALOG_SIM_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbol,
|
||||
m_fields( aFields ),
|
||||
m_library( std::make_shared<SIM_LIBRARY_SPICE>() ),
|
||||
m_prevModel( nullptr ),
|
||||
m_firstCategory( nullptr )
|
||||
m_firstCategory( nullptr ),
|
||||
m_prevParamGridSelection( nullptr )
|
||||
{
|
||||
m_browseButton->SetBitmap( KiBitmap( BITMAPS::small_folder ) );
|
||||
|
||||
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||
{
|
||||
m_models.push_back( SIM_MODEL::Create( type, m_symbol.GetAllPins().size() ) );
|
||||
@ -67,7 +70,8 @@ DIALOG_SIM_MODEL<T>::DIALOG_SIM_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbol,
|
||||
|
||||
m_scintillaTricks = std::make_unique<SCINTILLA_TRICKS>( m_codePreview, wxT( "{}" ), false );
|
||||
|
||||
m_paramGridMgr->Bind( wxEVT_PG_SELECTED, &DIALOG_SIM_MODEL::onSelectionChange, this );
|
||||
m_paramGridMgr->Bind( wxEVT_PG_SELECTED, &DIALOG_SIM_MODEL::onParamGridSelectionChange,
|
||||
this );
|
||||
|
||||
m_paramGrid->SetValidationFailureBehavior( wxPG_VFB_STAY_IN_PROPERTY
|
||||
| wxPG_VFB_BEEP
|
||||
@ -81,17 +85,14 @@ DIALOG_SIM_MODEL<T>::DIALOG_SIM_MODEL( wxWindow* aParent, SCH_SYMBOL& aSymbol,
|
||||
|
||||
if( wxPropertyGrid* grid = m_paramGrid->GetGrid() )
|
||||
{
|
||||
grid->Bind( wxEVT_SET_FOCUS, &DIALOG_SIM_MODEL::onParamGridSetFocus, this );
|
||||
|
||||
grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_RETURN );
|
||||
grid->DedicateKey( WXK_RETURN );
|
||||
grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RETURN );
|
||||
|
||||
grid->DedicateKey( WXK_UP );
|
||||
grid->DedicateKey( WXK_DOWN );
|
||||
|
||||
// Doesn't work for some reason.
|
||||
//grid->DedicateKey( WXK_TAB );
|
||||
//grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_TAB );
|
||||
//grid->AddActionTrigger( wxPG_ACTION_PREV_PROPERTY, WXK_TAB, wxMOD_SHIFT );
|
||||
}
|
||||
else
|
||||
wxFAIL;
|
||||
@ -191,25 +192,29 @@ void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
|
||||
if( &curModel() != m_prevModel )
|
||||
{
|
||||
SIM_MODEL::DEVICE_TYPE deviceType = SIM_MODEL::TypeInfo( curModel().GetType() ).deviceType;
|
||||
m_deviceTypeChoice->SetSelection( static_cast<int>( deviceType ) );
|
||||
|
||||
m_typeChoice->Clear();
|
||||
|
||||
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||
// Change the Type choice to match the current device type.
|
||||
if( !m_prevModel || deviceType != m_prevModel->GetDeviceType() )
|
||||
{
|
||||
if( SIM_MODEL::TypeInfo( type ).deviceType == deviceType )
|
||||
m_deviceTypeChoice->SetSelection( static_cast<int>( deviceType ) );
|
||||
|
||||
m_typeChoice->Clear();
|
||||
|
||||
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
|
||||
{
|
||||
wxString description = SIM_MODEL::TypeInfo( type ).description;
|
||||
if( SIM_MODEL::TypeInfo( type ).deviceType == deviceType )
|
||||
{
|
||||
wxString description = SIM_MODEL::TypeInfo( type ).description;
|
||||
|
||||
if( !description.IsEmpty() )
|
||||
m_typeChoice->Append( description );
|
||||
if( !description.IsEmpty() )
|
||||
m_typeChoice->Append( description );
|
||||
|
||||
if( type == curModel().GetType() )
|
||||
m_typeChoice->SetSelection( m_typeChoice->GetCount() - 1 );
|
||||
if( type == curModel().GetType() )
|
||||
m_typeChoice->SetSelection( m_typeChoice->GetCount() - 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This wxPropertyGridManager column and header stuff has to be here because it segfaults in
|
||||
// the constructor.
|
||||
|
||||
@ -224,7 +229,10 @@ void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
|
||||
|
||||
m_paramGrid->Clear();
|
||||
|
||||
m_firstCategory = m_paramGrid->Append( new wxPropertyCategory( "DC" ) );
|
||||
m_firstCategory = m_paramGrid->Append( new wxPropertyCategory( "AC" ) );
|
||||
m_paramGrid->HideProperty( "AC" );
|
||||
|
||||
m_paramGrid->Append( new wxPropertyCategory( "DC" ) );
|
||||
m_paramGrid->HideProperty( "DC" );
|
||||
|
||||
m_paramGrid->Append( new wxPropertyCategory( "Capacitance" ) );
|
||||
@ -251,10 +259,10 @@ void DIALOG_SIM_MODEL<T>::updateModelParamsTab()
|
||||
m_paramGrid->Append( new wxPropertyCategory( "Flags" ) );
|
||||
m_paramGrid->HideProperty( "Flags" );
|
||||
|
||||
m_paramGrid->CollapseAll();
|
||||
|
||||
for( unsigned i = 0; i < curModel().GetParamCount(); ++i )
|
||||
addParamPropertyIfRelevant( i );
|
||||
|
||||
m_paramGrid->CollapseAll();
|
||||
}
|
||||
|
||||
// Either enable all properties or disable all except the principal ones.
|
||||
@ -397,11 +405,15 @@ void DIALOG_SIM_MODEL<T>::loadLibrary( const wxString& aFilePath )
|
||||
{
|
||||
const wxString absolutePath = Prj().AbsolutePath( aFilePath );
|
||||
|
||||
if( !m_library->ReadFile( Prj().AbsolutePath( aFilePath ) ) )
|
||||
try
|
||||
{
|
||||
DisplayErrorMessage( this, wxString::Format( _( "Error loading model library '%s'" ),
|
||||
Prj().AbsolutePath( aFilePath ), aFilePath ),
|
||||
m_library->GetErrorMessage() );
|
||||
m_library->ReadFile( absolutePath );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
DisplayErrorMessage( this, wxString::Format( _( "Failed reading model library '%s'." ),
|
||||
absolutePath ),
|
||||
e.What() );
|
||||
}
|
||||
|
||||
m_libraryPathInput->SetValue( aFilePath );
|
||||
@ -427,6 +439,12 @@ void DIALOG_SIM_MODEL<T>::addParamPropertyIfRelevant( int aParamIndex )
|
||||
|
||||
switch( curModel().GetParam( aParamIndex ).info.category )
|
||||
{
|
||||
case CATEGORY::AC:
|
||||
m_paramGrid->HideProperty( "AC", false );
|
||||
m_paramGrid->AppendIn( "AC", newParamProperty( aParamIndex ) );
|
||||
m_paramGrid->Expand( "AC" );
|
||||
break;
|
||||
|
||||
case CATEGORY::DC:
|
||||
m_paramGrid->HideProperty( "DC", false );
|
||||
m_paramGrid->AppendIn( "DC", newParamProperty( aParamIndex ) );
|
||||
@ -790,9 +808,10 @@ void DIALOG_SIM_MODEL<T>::onTypeChoiceUpdate( wxUpdateUIEvent& aEvent )
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SIM_MODEL<T>::onSelectionChange( wxPropertyGridEvent& aEvent )
|
||||
void DIALOG_SIM_MODEL<T>::onParamGridSetFocus( wxFocusEvent& aEvent )
|
||||
{
|
||||
// TODO: Activate also when the whole property grid is selected with tab key.
|
||||
// By default, when a property grid is focused, the textbox is not immediately focused, until
|
||||
// Tab key is pressed. This is inconvenient, so we fix that here.
|
||||
|
||||
wxPropertyGrid* grid = m_paramGrid->GetGrid();
|
||||
if( !grid )
|
||||
@ -801,35 +820,81 @@ void DIALOG_SIM_MODEL<T>::onSelectionChange( wxPropertyGridEvent& aEvent )
|
||||
return;
|
||||
}
|
||||
|
||||
wxWindow* editorControl = grid->GetEditorControl();
|
||||
if( !editorControl )
|
||||
wxPGProperty* selected = grid->GetSelection();
|
||||
|
||||
if( !selected )
|
||||
selected = grid->wxPropertyGridInterface::GetFirst();
|
||||
|
||||
if( selected )
|
||||
grid->DoSelectProperty( selected, wxPG_SEL_FOCUS );
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void DIALOG_SIM_MODEL<T>::onParamGridSelectionChange( wxPropertyGridEvent& aEvent )
|
||||
{
|
||||
wxPropertyGrid* grid = m_paramGrid->GetGrid();
|
||||
if( !grid )
|
||||
{
|
||||
wxFAIL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Without this, the user had to press tab before they could edit the field.
|
||||
editorControl->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
/*template <typename T>
|
||||
void DIALOG_SPICE_MODEL<T>::onPropertyChanged( wxPropertyGridEvent& aEvent )
|
||||
{
|
||||
wxString name = aEvent.GetPropertyName();
|
||||
|
||||
for( SIM_MODEL::PARAM& param : getCurModel().Params() )
|
||||
// Jump over categories.
|
||||
if( grid->GetSelection() && grid->GetSelection()->IsCategory() )
|
||||
{
|
||||
if( param.info.name == name )
|
||||
wxPGProperty* selection = grid->GetSelection();
|
||||
|
||||
// If the new selection is immediately above the previous selection, we jump up. Otherwise
|
||||
// we jump down. We do this by simulating up or down arrow keys.
|
||||
|
||||
wxPropertyGridIterator it = grid->GetIterator( wxPG_ITERATE_VISIBLE, selection );
|
||||
it.Next();
|
||||
|
||||
wxKeyEvent* keyEvent = new wxKeyEvent( wxEVT_KEY_DOWN );
|
||||
|
||||
if( *it == m_prevParamGridSelection )
|
||||
{
|
||||
try
|
||||
if( !selection->IsExpanded() )
|
||||
{
|
||||
param.value->FromString( m_paramGrid->GetPropertyValueAsString( param.info.name ) );
|
||||
grid->Expand( selection );
|
||||
keyEvent->m_keyCode = WXK_DOWN;
|
||||
wxQueueEvent( grid, keyEvent );
|
||||
|
||||
// Does not work for some reason.
|
||||
/*m_paramGrid->DoSelectProperty( selection->Item( selection->GetChildCount() - 1 ),
|
||||
wxPG_SEL_FOCUS );*/
|
||||
}
|
||||
catch( KI_PARAM_ERROR& e )
|
||||
else
|
||||
{
|
||||
DisplayErrorMessage( this, e.What() );
|
||||
keyEvent->m_keyCode = WXK_UP;
|
||||
wxQueueEvent( grid, keyEvent );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !selection->IsExpanded() )
|
||||
grid->Expand( selection );
|
||||
|
||||
keyEvent->m_keyCode = WXK_DOWN;
|
||||
wxQueueEvent( grid, keyEvent );
|
||||
}
|
||||
|
||||
m_prevParamGridSelection = grid->GetSelection();
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
wxWindow* editorControl = grid->GetEditorControl();
|
||||
if( !editorControl )
|
||||
{
|
||||
wxFAIL;
|
||||
m_prevParamGridSelection = grid->GetSelection();
|
||||
return;
|
||||
}
|
||||
|
||||
// Without this the user had to press tab before they could edit the field.
|
||||
editorControl->SetFocus();
|
||||
m_prevParamGridSelection = grid->GetSelection();
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ private:
|
||||
void onDeviceTypeChoiceUpdate( wxUpdateUIEvent& aEvent ) override;
|
||||
void onTypeChoiceUpdate( wxUpdateUIEvent& aEvent ) override;
|
||||
|
||||
virtual void onSelectionChange( wxPropertyGridEvent& aEvent );
|
||||
//void onPropertyChanged( wxPropertyGridEvent& aEvent ) override;
|
||||
void onParamGridSetFocus( wxFocusEvent& aEvent );
|
||||
void onParamGridSelectionChange( wxPropertyGridEvent& aEvent );
|
||||
|
||||
|
||||
SCH_SYMBOL& m_symbol;
|
||||
@ -101,8 +101,10 @@ private:
|
||||
std::vector<std::shared_ptr<SIM_MODEL>> m_libraryModels;
|
||||
const SIM_MODEL* m_prevModel;
|
||||
|
||||
wxPGProperty* m_firstCategory; // Used to add principal parameters to root (any better ideas?)
|
||||
wxPGProperty* m_firstCategory; // Used to add principal parameters to root.
|
||||
std::unique_ptr<SCINTILLA_TRICKS> m_scintillaTricks;
|
||||
|
||||
wxPGProperty* m_prevParamGridSelection;
|
||||
};
|
||||
|
||||
#endif /* DIALOG_SPICE_MODEL_H */
|
||||
|
@ -24,9 +24,8 @@
|
||||
*/
|
||||
|
||||
#include "netlist_exporter_spice.h"
|
||||
#include <pegtl.hpp>
|
||||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
#include <sim/sim_model_spice.h>
|
||||
#include <sim/spice_grammar.h>
|
||||
#include <common.h>
|
||||
#include <confirm.h>
|
||||
#include <pgm_base.h>
|
||||
@ -36,6 +35,8 @@
|
||||
#include <sch_text.h>
|
||||
#include <sch_textbox.h>
|
||||
#include <string_utils.h>
|
||||
#include <pegtl.hpp>
|
||||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
|
||||
|
||||
namespace NETLIST_EXPORTER_SPICE_PARSER
|
||||
@ -197,8 +198,20 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives()
|
||||
if( node->is_type<NETLIST_EXPORTER_SPICE_PARSER::dotTitle>() )
|
||||
m_title = node->children.at( 0 )->string();
|
||||
else if( node->is_type<NETLIST_EXPORTER_SPICE_PARSER::dotInclude>() )
|
||||
m_libraries[node->children.at( 0 )->string()] =
|
||||
SIM_LIBRARY::Create( node->children.at( 0 )->string() );
|
||||
{
|
||||
wxString path = node->children.at( 0 )->string();
|
||||
|
||||
try
|
||||
{
|
||||
m_libraries.try_emplace( path, SIM_LIBRARY::Create( path ) );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
DisplayErrorMessage( nullptr,
|
||||
wxString::Format( "Failed reading model library '%s'.", path ),
|
||||
e.What() );
|
||||
}
|
||||
}
|
||||
else
|
||||
m_directives.emplace_back( node->string() );
|
||||
}
|
||||
@ -219,13 +232,26 @@ void NETLIST_EXPORTER_SPICE::readLibraryField( SCH_SYMBOL& aSymbol, SPICE_ITEM&
|
||||
// Special case for legacy models.
|
||||
unsigned libParamIndex = static_cast<unsigned>( SIM_MODEL_SPICE::SPICE_PARAM::LIB );
|
||||
path = model->GetParam( libParamIndex ).value->ToString();
|
||||
|
||||
m_rawIncludes.push_back( path );
|
||||
return;
|
||||
}
|
||||
|
||||
if( path.IsEmpty() )
|
||||
return;
|
||||
|
||||
if( auto library = SIM_LIBRARY::Create( m_schematic->Prj().AbsolutePath( path ) ) )
|
||||
m_libraries.try_emplace( path, std::move( library ) );
|
||||
wxString absolutePath = m_schematic->Prj().AbsolutePath( path );
|
||||
|
||||
try
|
||||
{
|
||||
m_libraries.try_emplace( path, SIM_LIBRARY::Create( absolutePath ) );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
DisplayErrorMessage( nullptr, wxString::Format( "Failed reading model library '%s'.",
|
||||
absolutePath ),
|
||||
e.What() );
|
||||
}
|
||||
|
||||
aItem.libraryPath = path;
|
||||
}
|
||||
@ -306,32 +332,41 @@ void NETLIST_EXPORTER_SPICE::readPins( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem,
|
||||
}
|
||||
|
||||
|
||||
void NETLIST_EXPORTER_SPICE::writeIncludes( OUTPUTFORMATTER& aFormatter,
|
||||
unsigned aNetlistOptions )
|
||||
void NETLIST_EXPORTER_SPICE::writeInclude( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions,
|
||||
const wxString& aPath )
|
||||
{
|
||||
for( auto&& [libraryPath, library] : m_libraries )
|
||||
// First, expand env vars, if any.
|
||||
wxString expandedPath = ExpandEnvVarSubstitutions( aPath, &m_schematic->Prj() );
|
||||
wxString fullPath;
|
||||
|
||||
if( aNetlistOptions & OPTION_ADJUST_INCLUDE_PATHS )
|
||||
{
|
||||
// First, expand env vars, if any.
|
||||
wxString libName = ExpandEnvVarSubstitutions( libraryPath, &m_schematic->Prj() );
|
||||
wxString fullPath;
|
||||
|
||||
if( aNetlistOptions & OPTION_ADJUST_INCLUDE_PATHS )
|
||||
// Look for the library in known search locations.
|
||||
fullPath = ResolveFile( expandedPath, &Pgm().GetLocalEnvVariables(),
|
||||
&m_schematic->Prj() );
|
||||
|
||||
if( fullPath.IsEmpty() )
|
||||
{
|
||||
// Look for the library in known search locations.
|
||||
fullPath = ResolveFile( libName, &Pgm().GetLocalEnvVariables(), &m_schematic->Prj() );
|
||||
|
||||
if( fullPath.IsEmpty() )
|
||||
{
|
||||
DisplayErrorMessage( nullptr,
|
||||
wxString::Format( _( "Could not find library file '%s'" ), libName ) );
|
||||
fullPath = libName;
|
||||
}
|
||||
DisplayErrorMessage( nullptr,
|
||||
wxString::Format( _( "Could not find library file '%s'" ),
|
||||
expandedPath ) );
|
||||
fullPath = expandedPath;
|
||||
}
|
||||
else
|
||||
fullPath = libName;
|
||||
|
||||
aFormatter.Print( 0, ".include \"%s\"\n", TO_UTF8( fullPath ) );
|
||||
}
|
||||
else
|
||||
fullPath = expandedPath;
|
||||
|
||||
aFormatter.Print( 0, ".include \"%s\"\n", TO_UTF8( fullPath ) );
|
||||
}
|
||||
|
||||
|
||||
void NETLIST_EXPORTER_SPICE::writeIncludes( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions )
|
||||
{
|
||||
for( auto&& [path, library] : m_libraries )
|
||||
writeInclude( aFormatter, aNetlistOptions, path );
|
||||
|
||||
for( const wxString& path : m_rawIncludes )
|
||||
writeInclude( aFormatter, aNetlistOptions, path );
|
||||
}
|
||||
|
||||
|
||||
|
@ -130,6 +130,9 @@ private:
|
||||
std::set<wxString>& aRefNames );
|
||||
void readPins( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem, int& notConnectedCounter );
|
||||
|
||||
void writeInclude( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions,
|
||||
const wxString& aPath );
|
||||
|
||||
void writeIncludes( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions );
|
||||
void writeModels( OUTPUTFORMATTER& aFormatter );
|
||||
void writeItems( OUTPUTFORMATTER& aFormatter );
|
||||
@ -137,6 +140,7 @@ private:
|
||||
wxString m_title; ///< Spice simulation title found in the schematic sheet
|
||||
std::vector<wxString> m_directives; ///< Spice directives found in the schematic sheet
|
||||
std::map<wxString, std::unique_ptr<SIM_LIBRARY>> m_libraries; ///< Spice libraries
|
||||
std::vector<wxString> m_rawIncludes;
|
||||
std::set<wxString> m_nets;
|
||||
std::list<SPICE_ITEM> m_items; ///< Items representing schematic symbols in Spice world
|
||||
};
|
||||
|
@ -307,9 +307,7 @@ bool NGSPICE::LoadNetlist( const string& aNetlist )
|
||||
|
||||
bool NGSPICE::Run()
|
||||
{
|
||||
wxBusyCursor dummy;
|
||||
|
||||
LOCALE_IO c_locale; // ngspice works correctly only with C locale
|
||||
LOCALE_IO toggle; // ngspice works correctly only with C locale
|
||||
bool success = Command( "bg_run" ); // bg_* commands execute in a separate thread
|
||||
|
||||
if( success )
|
||||
|
@ -83,15 +83,9 @@ wxString NGSPICE_CIRCUIT_MODEL::GetSheetSimCommand()
|
||||
}
|
||||
|
||||
|
||||
wxString NGSPICE_CIRCUIT_MODEL::GetUsedSimCommand()
|
||||
{
|
||||
return m_simCommand.IsEmpty() ? GetSheetSimCommand() : m_simCommand;
|
||||
}
|
||||
|
||||
|
||||
SIM_TYPE NGSPICE_CIRCUIT_MODEL::GetSimType()
|
||||
{
|
||||
return CommandToSimType( GetUsedSimCommand() );
|
||||
return CommandToSimType( GetSimCommand() );
|
||||
}
|
||||
|
||||
|
||||
@ -122,7 +116,7 @@ SIM_TYPE NGSPICE_CIRCUIT_MODEL::CommandToSimType( const wxString& aCmd )
|
||||
|
||||
|
||||
bool NGSPICE_CIRCUIT_MODEL::ParseDCCommand( const wxString& aCmd, SPICE_DC_PARAMS* aSource1,
|
||||
SPICE_DC_PARAMS* aSource2 )
|
||||
SPICE_DC_PARAMS* aSource2 )
|
||||
{
|
||||
if( !aCmd.Lower().StartsWith( ".dc" ) )
|
||||
return false;
|
||||
@ -157,5 +151,7 @@ void NGSPICE_CIRCUIT_MODEL::WriteDirectives( OUTPUTFORMATTER& aFormatter,
|
||||
unsigned aNetlistOptions ) const
|
||||
{
|
||||
NETLIST_EXPORTER_SPICE::WriteDirectives( aFormatter, aNetlistOptions );
|
||||
aFormatter.Print( 0, "%s\n", TO_UTF8( GetSimCommand() ) );
|
||||
|
||||
if( GetUnderlyingSimCommand() != "" )
|
||||
aFormatter.Print( 0, "%s\n", TO_UTF8( GetUnderlyingSimCommand() ) );
|
||||
}
|
||||
|
@ -82,13 +82,19 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the simulation command directive.
|
||||
* Return the command directive that is in use (either from the sheet or from m_simCommand)
|
||||
* @return
|
||||
*/
|
||||
const wxString& GetSimCommand() const
|
||||
wxString GetSimCommand()
|
||||
{
|
||||
return m_simCommand;
|
||||
return m_simCommand.IsEmpty() ? GetSheetSimCommand() : m_simCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the simulation command directive if stored separately (not as a sheet directive).
|
||||
*/
|
||||
wxString GetUnderlyingSimCommand() const { return m_simCommand; }
|
||||
|
||||
/**
|
||||
* Clear the simulation command directive.
|
||||
*/
|
||||
@ -97,12 +103,6 @@ public:
|
||||
m_simCommand.Clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the command directive that is in use (either from the sheet or from m_simCommand
|
||||
* @return
|
||||
*/
|
||||
wxString GetUsedSimCommand();
|
||||
|
||||
/**
|
||||
* Return simulation type basing on the simulation command directives.
|
||||
*
|
||||
|
@ -29,18 +29,15 @@
|
||||
std::unique_ptr<SIM_LIBRARY> SIM_LIBRARY::Create( wxString aFilePath )
|
||||
{
|
||||
std::unique_ptr<SIM_LIBRARY> library = std::make_unique<SIM_LIBRARY_SPICE>();
|
||||
|
||||
if( !library->ReadFile( aFilePath ) )
|
||||
return nullptr;
|
||||
|
||||
library->ReadFile( aFilePath );
|
||||
return library;
|
||||
}
|
||||
|
||||
|
||||
bool SIM_LIBRARY::ReadFile( const wxString& aFilePath )
|
||||
void SIM_LIBRARY::ReadFile( const wxString& aFilePath )
|
||||
{
|
||||
m_filePath = aFilePath;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -37,9 +37,30 @@ public:
|
||||
virtual ~SIM_LIBRARY() = default;
|
||||
SIM_LIBRARY() = default;
|
||||
|
||||
/**
|
||||
* Read library from a source file (e.g. in Spice format), and return a newly constructed
|
||||
* object of an appropriate subclass.
|
||||
*
|
||||
* @param aFilePath Path to the file.
|
||||
* @return The library loaded in a newly constructed object.
|
||||
*/
|
||||
static std::unique_ptr<SIM_LIBRARY> Create( wxString aFilePath );
|
||||
|
||||
virtual bool ReadFile( const wxString& aFilePath ) = 0;
|
||||
/**
|
||||
* Read library from a source file. Must be in the format appropriate to the subclass, e.g.
|
||||
* Spice for SIM_LIBRARY_SPICE).
|
||||
*
|
||||
* @param aFilePath Path to the file.
|
||||
* @throw IO_ERROR on read or parsing error.
|
||||
*/
|
||||
virtual void ReadFile( const wxString& aFilePath ) = 0;
|
||||
|
||||
/**
|
||||
* Write library to a source file (e.g. in Spice format).
|
||||
*
|
||||
* @param aFilePath Path to the file.
|
||||
* @throw IO_ERROR on write error.
|
||||
*/
|
||||
virtual void WriteFile( const wxString& aFilePath ) = 0;
|
||||
|
||||
SIM_MODEL* FindModel( const wxString& aModelName ) const;
|
||||
@ -48,14 +69,14 @@ public:
|
||||
const std::vector<wxString>& GetModelNames() const { return m_modelNames; }
|
||||
|
||||
wxString GetFilePath() const { return m_filePath; }
|
||||
wxString GetErrorMessage() const { return m_errorMessage; }
|
||||
wxString GetError() const { return m_error; }
|
||||
|
||||
protected:
|
||||
std::vector<std::unique_ptr<SIM_MODEL>> m_models;
|
||||
std::vector<wxString> m_modelNames;
|
||||
|
||||
wxString m_filePath;
|
||||
wxString m_errorMessage;
|
||||
wxString m_error;
|
||||
};
|
||||
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <sim/sim_library_spice.h>
|
||||
#include <sim/spice_grammar.h>
|
||||
#include <ki_exception.h>
|
||||
#include <locale_io.h>
|
||||
#include <pegtl.hpp>
|
||||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
@ -48,12 +49,11 @@ namespace SIM_LIBRARY_SPICE_PARSER
|
||||
};
|
||||
|
||||
|
||||
bool SIM_LIBRARY_SPICE::ReadFile( const wxString& aFilePath )
|
||||
void SIM_LIBRARY_SPICE::ReadFile( const wxString& aFilePath )
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
|
||||
if( !SIM_LIBRARY::ReadFile( aFilePath ) )
|
||||
return false;
|
||||
SIM_LIBRARY::ReadFile( aFilePath );
|
||||
|
||||
m_models.clear();
|
||||
m_modelNames.clear();
|
||||
@ -73,11 +73,10 @@ bool SIM_LIBRARY_SPICE::ReadFile( const wxString& aFilePath )
|
||||
{
|
||||
m_models.push_back( SIM_MODEL::Create( node->string() ) );
|
||||
|
||||
if( node->children.size() != 1 )
|
||||
if( node->children.size() < 1
|
||||
|| !node->children.at( 0 )->is_type<SIM_LIBRARY_SPICE_PARSER::modelName>() )
|
||||
{
|
||||
m_errorMessage = wxString::Format(
|
||||
"Captured %d name tokens, expected one", node->children.size() );
|
||||
return false;
|
||||
THROW_IO_ERROR( wxString::Format( "Model name token not found" ) );
|
||||
}
|
||||
|
||||
m_modelNames.emplace_back( node->children.at( 0 )->string() );
|
||||
@ -88,27 +87,23 @@ bool SIM_LIBRARY_SPICE::ReadFile( const wxString& aFilePath )
|
||||
}
|
||||
else
|
||||
{
|
||||
m_errorMessage = wxString::Format( "Unhandled parse tree node: '%s'", node->string() );
|
||||
return false;
|
||||
THROW_IO_ERROR( wxString::Format( "Unhandled parse tree node: '%s'",
|
||||
node->string() ) );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch( const std::filesystem::filesystem_error& e )
|
||||
{
|
||||
m_errorMessage = wxString::Format( "Parsing failed: %s", e.what() );
|
||||
return false;
|
||||
THROW_IO_ERROR( e.what() );
|
||||
}
|
||||
catch( const tao::pegtl::parse_error& e )
|
||||
{
|
||||
m_errorMessage = wxString::Format( "Parsing failed: %s", e.what() );
|
||||
return false;
|
||||
THROW_IO_ERROR( e.what() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SIM_LIBRARY_SPICE::WriteFile( const wxString& aFilePath )
|
||||
{
|
||||
|
||||
// Not implemented yet.
|
||||
}
|
||||
|
@ -33,7 +33,10 @@ class SIM_LIBRARY_SPICE : public SIM_LIBRARY
|
||||
// We'll make SIM_LIBRARY have no subclasses probably.
|
||||
|
||||
public:
|
||||
bool ReadFile( const wxString& aFilePath ) override;
|
||||
// @copydoc SIM_LIBRARY::ReadFile()
|
||||
void ReadFile( const wxString& aFilePath ) override;
|
||||
|
||||
// @copydoc SIM_LIBRARY::WriteFile()
|
||||
void WriteFile( const wxString& aFilePath ) override;
|
||||
};
|
||||
|
||||
|
@ -28,17 +28,17 @@
|
||||
#include <sim/sim_model_behavioral.h>
|
||||
#include <sim/sim_model_ideal.h>
|
||||
#include <sim/sim_model_ngspice.h>
|
||||
#include <sim/sim_model_passive.h>
|
||||
#include <sim/sim_model_source.h>
|
||||
#include <sim/sim_model_spice.h>
|
||||
#include <sim/sim_model_subckt.h>
|
||||
#include <sim/sim_model_tline.h>
|
||||
#include <sim/sim_model_xspice.h>
|
||||
|
||||
#include <pegtl.hpp>
|
||||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
#include <sim/spice_grammar.h>
|
||||
#include <locale_io.h>
|
||||
#include <lib_symbol.h>
|
||||
#include <pegtl.hpp>
|
||||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
|
||||
using DEVICE_TYPE = SIM_MODEL::DEVICE_TYPE;
|
||||
using TYPE = SIM_MODEL::TYPE;
|
||||
@ -126,15 +126,15 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType )
|
||||
case TYPE::NONE: return { DEVICE_TYPE::NONE, "", "" };
|
||||
|
||||
case TYPE::R: return { DEVICE_TYPE::R, "", "Ideal" };
|
||||
case TYPE::R_ADV: return { DEVICE_TYPE::R, "ADV", "Advanced" };
|
||||
//case TYPE::R_ADV: return { DEVICE_TYPE::R, "ADV", "Advanced" };
|
||||
case TYPE::R_BEHAVIORAL: return { DEVICE_TYPE::R, "=", "Behavioral" };
|
||||
|
||||
case TYPE::C: return { DEVICE_TYPE::C, "", "Ideal" };
|
||||
case TYPE::C_ADV: return { DEVICE_TYPE::C, "ADV", "Advanced" };
|
||||
//case TYPE::C_ADV: return { DEVICE_TYPE::C, "ADV", "Advanced" };
|
||||
case TYPE::C_BEHAVIORAL: return { DEVICE_TYPE::C, "=", "Behavioral" };
|
||||
|
||||
case TYPE::L: return { DEVICE_TYPE::L, "", "Ideal" };
|
||||
case TYPE::L_ADV: return { DEVICE_TYPE::L, "ADV", "Advanced" };
|
||||
//case TYPE::L_ADV: return { DEVICE_TYPE::L, "ADV", "Advanced" };
|
||||
case TYPE::L_BEHAVIORAL: return { DEVICE_TYPE::L, "=", "Behavioral" };
|
||||
|
||||
case TYPE::TLINE_Z0: return { DEVICE_TYPE::TLINE, "Z0", "Characteristic impedance" };
|
||||
@ -150,8 +150,8 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType )
|
||||
case TYPE::NPN_VBIC: return { DEVICE_TYPE::NPN, "VBIC", "VBIC" };
|
||||
case TYPE::PNP_VBIC: return { DEVICE_TYPE::PNP, "VBIC", "VBIC" };
|
||||
//case TYPE::BJT_MEXTRAM: return {};
|
||||
case TYPE::NPN_HICUML2: return { DEVICE_TYPE::NPN, "HICUML2", "HICUM Level 2" };
|
||||
case TYPE::PNP_HICUML2: return { DEVICE_TYPE::PNP, "HICUML2", "HICUM Level 2" };
|
||||
case TYPE::NPN_HICUML2: return { DEVICE_TYPE::NPN, "HICUML2", "HICUM level 2" };
|
||||
case TYPE::PNP_HICUML2: return { DEVICE_TYPE::PNP, "HICUML2", "HICUM level 2" };
|
||||
//case TYPE::BJT_HICUM_L0: return {};
|
||||
|
||||
case TYPE::NJFET_SHICHMANHODGES: return { DEVICE_TYPE::NJFET, "SHICHMANHODGES", "Shichman-Hodges" };
|
||||
@ -211,12 +211,12 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType )
|
||||
case TYPE::V_SIN: return { DEVICE_TYPE::V, "SIN", "Sine" };
|
||||
case TYPE::V_PULSE: return { DEVICE_TYPE::V, "PULSE", "Pulse" };
|
||||
case TYPE::V_EXP: return { DEVICE_TYPE::V, "EXP", "Exponential" };
|
||||
case TYPE::V_SFAM: return { DEVICE_TYPE::V, "SFAM", "Single-frequency AM" };
|
||||
case TYPE::V_SFFM: return { DEVICE_TYPE::V, "SFFM", "Single-frequency FM" };
|
||||
/*case TYPE::V_SFAM: return { DEVICE_TYPE::V, "SFAM", "Single-frequency AM" };
|
||||
case TYPE::V_SFFM: return { DEVICE_TYPE::V, "SFFM", "Single-frequency FM" };*/
|
||||
case TYPE::V_PWL: return { DEVICE_TYPE::V, "PWL", "Piecewise linear" };
|
||||
case TYPE::V_WHITENOISE: return { DEVICE_TYPE::V, "WHITENOISE", "White Noise" };
|
||||
case TYPE::V_PINKNOISE: return { DEVICE_TYPE::V, "PINKNOISE", "Pink Noise (1/f)" };
|
||||
case TYPE::V_BURSTNOISE: return { DEVICE_TYPE::V, "BURSTNOISE", "Burst Noise" };
|
||||
case TYPE::V_WHITENOISE: return { DEVICE_TYPE::V, "WHITENOISE", "White noise" };
|
||||
case TYPE::V_PINKNOISE: return { DEVICE_TYPE::V, "PINKNOISE", "Pink noise (1/f)" };
|
||||
case TYPE::V_BURSTNOISE: return { DEVICE_TYPE::V, "BURSTNOISE", "Burst noise" };
|
||||
case TYPE::V_RANDUNIFORM: return { DEVICE_TYPE::V, "RANDUNIFORM", "Random uniform" };
|
||||
case TYPE::V_RANDNORMAL: return { DEVICE_TYPE::V, "RANDNORMAL", "Random normal" };
|
||||
case TYPE::V_RANDEXP: return { DEVICE_TYPE::V, "RANDEXP", "Random exponential" };
|
||||
@ -227,8 +227,8 @@ SIM_MODEL::INFO SIM_MODEL::TypeInfo( TYPE aType )
|
||||
case TYPE::I_SIN: return { DEVICE_TYPE::I, "SIN", "Sine" };
|
||||
case TYPE::I_PULSE: return { DEVICE_TYPE::I, "PULSE", "Pulse" };
|
||||
case TYPE::I_EXP: return { DEVICE_TYPE::I, "EXP", "Exponential" };
|
||||
case TYPE::I_SFAM: return { DEVICE_TYPE::I, "SFAM", "Single-frequency AM" };
|
||||
case TYPE::I_SFFM: return { DEVICE_TYPE::I, "SFFM", "Single-frequency FM" };
|
||||
/*case TYPE::I_SFAM: return { DEVICE_TYPE::I, "SFAM", "Single-frequency AM" };
|
||||
case TYPE::I_SFFM: return { DEVICE_TYPE::I, "SFFM", "Single-frequency FM" };*/
|
||||
case TYPE::I_PWL: return { DEVICE_TYPE::I, "PWL", "Piecewise linear" };
|
||||
case TYPE::I_WHITENOISE: return { DEVICE_TYPE::I, "WHITENOISE", "White Noise" };
|
||||
case TYPE::I_PINKNOISE: return { DEVICE_TYPE::I, "PINKNOISE", "Pink Noise (1/f)" };
|
||||
@ -256,15 +256,15 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
|
||||
switch( aType )
|
||||
{
|
||||
case TYPE::R: return { "R", "" };
|
||||
case TYPE::R_ADV: return { "R", "r" };
|
||||
//case TYPE::R_ADV: return { "R", "r" };
|
||||
case TYPE::R_BEHAVIORAL: return { "R", "", "", "0", false, true };
|
||||
|
||||
case TYPE::C: return { "C", "" };
|
||||
case TYPE::C_ADV: return { "C", "c", };
|
||||
//case TYPE::C_ADV: return { "C", "c", };
|
||||
case TYPE::C_BEHAVIORAL: return { "C", "", "", "0", false, true };
|
||||
|
||||
case TYPE::L: return { "L", "" };
|
||||
case TYPE::L_ADV: return { "L", "l" };
|
||||
//case TYPE::L_ADV: return { "L", "l" };
|
||||
case TYPE::L_BEHAVIORAL: return { "L", "", "", "0", false, true };
|
||||
|
||||
case TYPE::TLINE_Z0: return { "T" };
|
||||
@ -341,8 +341,8 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
|
||||
case TYPE::V_SIN: return { "V", "", "SIN" };
|
||||
case TYPE::V_PULSE: return { "V", "", "PULSE" };
|
||||
case TYPE::V_EXP: return { "V", "", "EXP" };
|
||||
case TYPE::V_SFAM: return { "V", "", "AM" };
|
||||
case TYPE::V_SFFM: return { "V", "", "SFFM" };
|
||||
/*case TYPE::V_SFAM: return { "V", "", "AM" };
|
||||
case TYPE::V_SFFM: return { "V", "", "SFFM" };*/
|
||||
case TYPE::V_PWL: return { "V", "", "PWL" };
|
||||
case TYPE::V_WHITENOISE: return { "V", "", "TRNOISE" };
|
||||
case TYPE::V_PINKNOISE: return { "V", "", "TRNOISE" };
|
||||
@ -357,8 +357,8 @@ SIM_MODEL::SPICE_INFO SIM_MODEL::SpiceInfo( TYPE aType )
|
||||
case TYPE::I_PULSE: return { "V", "", "PULSE" };
|
||||
case TYPE::I_SIN: return { "V", "", "SIN" };
|
||||
case TYPE::I_EXP: return { "V", "", "EXP" };
|
||||
case TYPE::I_SFAM: return { "V", "", "AM" };
|
||||
case TYPE::I_SFFM: return { "V", "", "SFFM" };
|
||||
/*case TYPE::I_SFAM: return { "V", "", "AM" };
|
||||
case TYPE::I_SFFM: return { "V", "", "SFFM" };*/
|
||||
case TYPE::I_PWL: return { "V", "", "PWL" };
|
||||
case TYPE::I_WHITENOISE: return { "V", "", "TRNOISE" };
|
||||
case TYPE::I_PINKNOISE: return { "V", "", "TRNOISE" };
|
||||
@ -492,7 +492,8 @@ TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<T>& aFields )
|
||||
return TYPE::NONE;
|
||||
|
||||
// No type information. For passives we infer the model from the mandatory fields in this case.
|
||||
TYPE typeFromRef = InferTypeFromRef( GetFieldValue( &aFields, REFERENCE_FIELD ) );
|
||||
TYPE typeFromRef = InferTypeFromRefAndValue( GetFieldValue( &aFields, REFERENCE_FIELD ),
|
||||
GetFieldValue( &aFields, VALUE_FIELD ) );
|
||||
if( typeFromRef != TYPE::NONE )
|
||||
return typeFromRef;
|
||||
|
||||
@ -501,18 +502,19 @@ TYPE SIM_MODEL::ReadTypeFromFields( const std::vector<T>& aFields )
|
||||
}
|
||||
|
||||
|
||||
TYPE SIM_MODEL::InferTypeFromRef( const wxString& aRef )
|
||||
TYPE SIM_MODEL::InferTypeFromRefAndValue( const wxString& aRef, const wxString& aValue )
|
||||
{
|
||||
static std::map<wxString, TYPE> refPrefixToType = {
|
||||
{ "R", TYPE::R },
|
||||
{ "C", TYPE::C },
|
||||
{ "L", TYPE::L },
|
||||
{ "TLINE", TYPE::TLINE_Z0 },
|
||||
{ "VDC", TYPE::V_DC },
|
||||
{ "VSIN", TYPE::V_SIN },
|
||||
{ "VPULSE", TYPE::V_PULSE },
|
||||
{ "VEXP", TYPE::V_EXP },
|
||||
{ "VSFAM", TYPE::V_SFAM },
|
||||
{ "VSFFM", TYPE::V_SFFM },
|
||||
/*{ "VSFAM", TYPE::V_SFAM },
|
||||
{ "VSFFM", TYPE::V_SFFM },*/
|
||||
{ "VPWL", TYPE::V_PWL },
|
||||
{ "VWHITENOISE", TYPE::V_WHITENOISE },
|
||||
{ "VPINKNOISE", TYPE::V_PINKNOISE },
|
||||
@ -526,8 +528,8 @@ TYPE SIM_MODEL::InferTypeFromRef( const wxString& aRef )
|
||||
{ "ISIN", TYPE::I_SIN },
|
||||
{ "IPULSE", TYPE::I_PULSE },
|
||||
{ "IEXP", TYPE::I_EXP },
|
||||
{ "ISFAM", TYPE::I_SFAM },
|
||||
{ "ISFFM", TYPE::I_SFFM },
|
||||
/*{ "ISFAM", TYPE::I_SFAM },
|
||||
{ "ISFFM", TYPE::I_SFFM },*/
|
||||
{ "IPWL", TYPE::I_PWL },
|
||||
{ "IWHITENOISE", TYPE::I_WHITENOISE },
|
||||
{ "IPINKNOISE", TYPE::I_PINKNOISE },
|
||||
@ -539,13 +541,69 @@ TYPE SIM_MODEL::InferTypeFromRef( const wxString& aRef )
|
||||
{ "IBEHAVIORAL", TYPE::I_BEHAVIORAL }
|
||||
};
|
||||
|
||||
for( auto&& [prefix, type] : refPrefixToType )
|
||||
TYPE type = TYPE::NONE;
|
||||
|
||||
for( auto&& [curPrefix, curType] : refPrefixToType )
|
||||
{
|
||||
if( aRef.StartsWith( prefix ) )
|
||||
return type;
|
||||
if( aRef.StartsWith( curPrefix ) )
|
||||
{
|
||||
type = curType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TYPE::NONE;
|
||||
wxString value = aValue;
|
||||
|
||||
// Some types have to be inferred from Value field.
|
||||
switch( type )
|
||||
{
|
||||
case TYPE::R:
|
||||
if( value.Trim( false ).StartsWith( "=" ) )
|
||||
type = TYPE::R_BEHAVIORAL;
|
||||
break;
|
||||
|
||||
case TYPE::C:
|
||||
if( value.Trim( false ).StartsWith( "=" ) )
|
||||
type = TYPE::C_BEHAVIORAL;
|
||||
break;
|
||||
|
||||
case TYPE::L:
|
||||
if( value.Trim( false ).StartsWith( "=" ) )
|
||||
type = TYPE::L_BEHAVIORAL;
|
||||
break;
|
||||
|
||||
case TYPE::TLINE_Z0:
|
||||
try
|
||||
{
|
||||
tao::pegtl::string_input<> in( aValue.ToStdString(), "from_content" );
|
||||
auto root = tao::pegtl::parse_tree::parse<
|
||||
SIM_MODEL_PARSER::fieldParamValuePairsGrammar,
|
||||
SIM_MODEL_PARSER::fieldParamValuePairsSelector>
|
||||
( in );
|
||||
|
||||
for( const auto& node : root->children )
|
||||
{
|
||||
if( node->is_type<SIM_MODEL_PARSER::param>()
|
||||
&& (node->string() == "r" || node->string() == "R"
|
||||
|| node->string() == "c" || node->string() == "C"
|
||||
|| node->string() == "l" || node->string() == "L" ) )
|
||||
{
|
||||
type = TYPE::TLINE_RLGC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( const tao::pegtl::parse_error& e )
|
||||
{
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
@ -868,7 +926,7 @@ wxString SIM_MODEL::GenerateSpiceModelLine( const wxString& aModelName ) const
|
||||
|
||||
wxString SIM_MODEL::GenerateSpiceItemName( const wxString& aRefName ) const
|
||||
{
|
||||
if( !aRefName.IsEmpty() && aRefName.StartsWith( GetSpiceInfo().itemType ) )
|
||||
if( aRefName != "" && aRefName.StartsWith( GetSpiceInfo().itemType ) )
|
||||
return aRefName;
|
||||
else
|
||||
return GetSpiceInfo().itemType + aRefName;
|
||||
@ -1265,11 +1323,6 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::create( TYPE aType )
|
||||
case TYPE::L:
|
||||
return std::make_unique<SIM_MODEL_IDEAL>( aType );
|
||||
|
||||
case TYPE::R_ADV:
|
||||
case TYPE::C_ADV:
|
||||
case TYPE::L_ADV:
|
||||
return std::make_unique<SIM_MODEL_PASSIVE>( aType );
|
||||
|
||||
case TYPE::R_BEHAVIORAL:
|
||||
case TYPE::C_BEHAVIORAL:
|
||||
case TYPE::L_BEHAVIORAL:
|
||||
@ -1289,10 +1342,10 @@ std::unique_ptr<SIM_MODEL> SIM_MODEL::create( TYPE aType )
|
||||
case TYPE::I_PULSE:
|
||||
case TYPE::V_EXP:
|
||||
case TYPE::I_EXP:
|
||||
case TYPE::V_SFAM:
|
||||
/*case TYPE::V_SFAM:
|
||||
case TYPE::I_SFAM:
|
||||
case TYPE::V_SFFM:
|
||||
case TYPE::I_SFFM:
|
||||
case TYPE::I_SFFM:*/
|
||||
case TYPE::V_PWL:
|
||||
case TYPE::I_PWL:
|
||||
case TYPE::V_WHITENOISE:
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef SIM_MODEL_H
|
||||
#define SIM_MODEL_H
|
||||
|
||||
#include <sim/spice_grammar.h>
|
||||
#include <sim/sim_value.h>
|
||||
#include <enum_vector.h>
|
||||
#include <sch_field.h>
|
||||
#include <lib_field.h>
|
||||
@ -133,15 +133,15 @@ public:
|
||||
NONE,
|
||||
|
||||
R,
|
||||
R_ADV,
|
||||
//R_ADV,
|
||||
R_BEHAVIORAL,
|
||||
|
||||
C,
|
||||
C_ADV,
|
||||
//C_ADV,
|
||||
C_BEHAVIORAL,
|
||||
|
||||
L,
|
||||
L_ADV,
|
||||
//L_ADV,
|
||||
L_BEHAVIORAL,
|
||||
|
||||
TLINE_Z0,
|
||||
@ -245,8 +245,8 @@ public:
|
||||
V_SIN,
|
||||
V_PULSE,
|
||||
V_EXP,
|
||||
V_SFAM,
|
||||
V_SFFM,
|
||||
/*V_SFAM,
|
||||
V_SFFM,*/
|
||||
V_PWL,
|
||||
V_WHITENOISE,
|
||||
V_PINKNOISE,
|
||||
@ -261,8 +261,8 @@ public:
|
||||
I_SIN,
|
||||
I_PULSE,
|
||||
I_EXP,
|
||||
I_SFAM,
|
||||
I_SFFM,
|
||||
/*I_SFAM,
|
||||
I_SFFM,*/
|
||||
I_PWL,
|
||||
I_WHITENOISE,
|
||||
I_PINKNOISE,
|
||||
@ -320,6 +320,7 @@ public:
|
||||
enum class CATEGORY
|
||||
{
|
||||
PRINCIPAL,
|
||||
AC,
|
||||
DC,
|
||||
CAPACITANCE,
|
||||
TEMPERATURE,
|
||||
@ -373,7 +374,7 @@ public:
|
||||
template <typename T>
|
||||
static TYPE ReadTypeFromFields( const std::vector<T>& aFields );
|
||||
|
||||
static TYPE InferTypeFromRef( const wxString& aRef );
|
||||
static TYPE InferTypeFromRefAndValue( const wxString& aRef, const wxString& aValue );
|
||||
|
||||
template <typename T>
|
||||
static TYPE InferTypeFromLegacyFields( const std::vector<T>& aFields );
|
||||
|
@ -27,7 +27,8 @@
|
||||
|
||||
|
||||
SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType )
|
||||
: SIM_MODEL( aType )
|
||||
: SIM_MODEL( aType ),
|
||||
m_isInferred( false )
|
||||
{
|
||||
static PARAM::INFO resistor = makeParams( "r", "Expression for resistance", "Ω" );
|
||||
static PARAM::INFO capacitor = makeParams( "c", "Expression for capacitance", "F" );
|
||||
@ -48,6 +49,44 @@ SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType )
|
||||
}
|
||||
|
||||
|
||||
void SIM_MODEL_BEHAVIORAL::ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields )
|
||||
{
|
||||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
void SIM_MODEL_BEHAVIORAL::ReadDataLibFields( unsigned aSymbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields )
|
||||
{
|
||||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
void SIM_MODEL_BEHAVIORAL::WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const
|
||||
{
|
||||
SIM_MODEL::WriteDataSchFields( aFields );
|
||||
|
||||
if( m_isInferred )
|
||||
inferredWriteDataFields( aFields );
|
||||
}
|
||||
|
||||
|
||||
void SIM_MODEL_BEHAVIORAL::WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const
|
||||
{
|
||||
SIM_MODEL::WriteDataLibFields( aFields );
|
||||
|
||||
if( m_isInferred )
|
||||
inferredWriteDataFields( aFields );
|
||||
}
|
||||
|
||||
|
||||
wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceModelLine( const wxString& aModelName ) const
|
||||
{
|
||||
return "";
|
||||
@ -84,6 +123,35 @@ wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceItemLine( const wxString& aRefName,
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SIM_MODEL_BEHAVIORAL::inferredReadDataFields( unsigned aSymbolPinCount,
|
||||
const std::vector<T>* aFields )
|
||||
{
|
||||
ParsePinsField( aSymbolPinCount, PINS_FIELD );
|
||||
|
||||
if( ( InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
||||
GetFieldValue( aFields, VALUE_FIELD ) ) == GetType()
|
||||
&& ParseParamsField( GetFieldValue( aFields, VALUE_FIELD ) ) )
|
||||
// If Value is device type, this is an empty model
|
||||
|| GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue )
|
||||
{
|
||||
m_isInferred = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SIM_MODEL_BEHAVIORAL::inferredWriteDataFields( std::vector<T>& aFields ) const
|
||||
{
|
||||
wxString value = GetFieldValue( &aFields, PARAMS_FIELD );
|
||||
|
||||
if( value == "" )
|
||||
value = GetDeviceTypeInfo().fieldValue;
|
||||
|
||||
WriteInferredDataFields( aFields, value );
|
||||
}
|
||||
|
||||
|
||||
SIM_MODEL::PARAM::INFO SIM_MODEL_BEHAVIORAL::makeParams( wxString aName, wxString aDescription,
|
||||
wxString aUnit )
|
||||
{
|
||||
|
@ -33,6 +33,14 @@ class SIM_MODEL_BEHAVIORAL : public SIM_MODEL
|
||||
public:
|
||||
SIM_MODEL_BEHAVIORAL( TYPE aType );
|
||||
|
||||
void ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields ) override;
|
||||
void ReadDataLibFields( unsigned aSymbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields ) override;
|
||||
|
||||
void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override;
|
||||
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
|
||||
|
||||
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
|
||||
|
||||
wxString GenerateSpiceItemLine( const wxString& aRefName,
|
||||
@ -40,9 +48,17 @@ public:
|
||||
const std::vector<wxString>& aPinNetNames ) const override;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void inferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
||||
|
||||
template <typename T>
|
||||
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
||||
|
||||
std::vector<wxString> getPinNames() const override { return { "+", "-" }; }
|
||||
|
||||
static PARAM::INFO makeParams( wxString aName, wxString aDescription, wxString aUnit );
|
||||
|
||||
bool m_isInferred;
|
||||
};
|
||||
|
||||
#endif // SIM_MODEL_BEHAVIORAL_H
|
||||
|
@ -49,7 +49,7 @@ SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType )
|
||||
void SIM_MODEL_IDEAL::ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields )
|
||||
{
|
||||
if( !GetFieldValue( aFields, PARAMS_FIELD ).IsEmpty() )
|
||||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
@ -59,7 +59,7 @@ void SIM_MODEL_IDEAL::ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
void SIM_MODEL_IDEAL::ReadDataLibFields( unsigned aSymbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields )
|
||||
{
|
||||
if( !GetFieldValue( aFields, PARAMS_FIELD ).IsEmpty() )
|
||||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
@ -94,9 +94,12 @@ wxString SIM_MODEL_IDEAL::GenerateSpiceItemLine( const wxString& aRefName,
|
||||
const wxString& aModelName,
|
||||
const std::vector<wxString>& aPinNetNames ) const
|
||||
{
|
||||
return SIM_MODEL::GenerateSpiceItemLine( aRefName,
|
||||
GetParam( 0 ).value->ToString( SIM_VALUE::NOTATION::SPICE ),
|
||||
aPinNetNames );
|
||||
wxString valueStr = GetParam( 0 ).value->ToString( SIM_VALUE::NOTATION::SPICE );
|
||||
|
||||
if( valueStr != "" )
|
||||
return SIM_MODEL::GenerateSpiceItemLine( aRefName, valueStr, aPinNetNames );
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@ -105,8 +108,10 @@ void SIM_MODEL_IDEAL::inferredReadDataFields( unsigned aSymbolPinCount, const st
|
||||
{
|
||||
ParsePinsField( aSymbolPinCount, PINS_FIELD );
|
||||
|
||||
if( ( InferTypeFromRef( GetFieldValue( aFields, REFERENCE_FIELD ) ) == GetType()
|
||||
if( ( InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
||||
GetFieldValue( aFields, VALUE_FIELD ) ) == GetType()
|
||||
&& SetParamValue( 0, GetFieldValue( aFields, VALUE_FIELD ) ) )
|
||||
// If Value is device type, this is an empty model
|
||||
|| GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue )
|
||||
{
|
||||
m_isInferred = true;
|
||||
|
@ -1,177 +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 <sim/sim_model_passive.h>
|
||||
|
||||
using PARAM = SIM_MODEL::PARAM;
|
||||
|
||||
|
||||
SIM_MODEL_PASSIVE::SIM_MODEL_PASSIVE( TYPE aType )
|
||||
: SIM_MODEL( aType )
|
||||
{
|
||||
static std::vector<PARAM::INFO> resistor = makeParamInfos( "r", "Resistance", "Ω" );
|
||||
static std::vector<PARAM::INFO> capacitor = makeParamInfos( "c", "Capacitance", "F" );
|
||||
static std::vector<PARAM::INFO> inductor = makeParamInfos( "l", "Inductance", "H" );
|
||||
|
||||
switch( aType )
|
||||
{
|
||||
case TYPE::R_ADV:
|
||||
for( const PARAM::INFO& paramInfo : resistor )
|
||||
AddParam( paramInfo );
|
||||
break;
|
||||
|
||||
case TYPE::C_ADV:
|
||||
for( const PARAM::INFO& paramInfo : capacitor )
|
||||
AddParam( paramInfo );
|
||||
break;
|
||||
|
||||
case TYPE::L_ADV:
|
||||
for( const PARAM::INFO& paramInfo : inductor )
|
||||
AddParam( paramInfo );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_PASSIVE" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SIM_MODEL_PASSIVE::SetParamFromSpiceCode( const wxString& aParamName,
|
||||
const wxString& aParamValue,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation )
|
||||
{
|
||||
if( aParamName.Lower() == "tc" )
|
||||
return SetParamFromSpiceCode( "tc1", aParamValue, aNotation );
|
||||
|
||||
switch( GetType() )
|
||||
{
|
||||
case TYPE::R_ADV:
|
||||
if( aParamName.Lower() == "tc1r" )
|
||||
return SIM_MODEL::SetParamFromSpiceCode( "tc1", aParamValue, aNotation );
|
||||
|
||||
/*if( aParamName.Lower() == "tc2r" )
|
||||
return SIM_MODEL::SetParamFromSpiceCode( "tc2", aParamValue, aNotation );*/
|
||||
|
||||
if( aParamName.Lower() == "res" )
|
||||
return SIM_MODEL::SetParamFromSpiceCode( "r", aParamValue, aNotation );
|
||||
|
||||
break;
|
||||
|
||||
case TYPE::C_ADV:
|
||||
if( aParamName.Lower() == "cap" )
|
||||
return SIM_MODEL::SetParamFromSpiceCode( "c", aParamValue, aNotation );
|
||||
|
||||
break;
|
||||
|
||||
case TYPE::L_ADV:
|
||||
if( aParamName.Lower() == "ind" )
|
||||
return SIM_MODEL::SetParamFromSpiceCode( "l", aParamValue, aNotation );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SIM_MODEL::SetParamFromSpiceCode( aParamName, aParamValue, aNotation );
|
||||
}
|
||||
|
||||
|
||||
std::vector<PARAM::INFO> SIM_MODEL_PASSIVE::makeParamInfos( wxString aName,
|
||||
wxString aDescription,
|
||||
wxString aUnit )
|
||||
{
|
||||
std::vector<PARAM::INFO> paramInfos;
|
||||
PARAM::INFO paramInfo = {};
|
||||
|
||||
paramInfo.name = "temp";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = "°C";
|
||||
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "27";
|
||||
paramInfo.description = "Temperature";
|
||||
paramInfo.isInstanceParam = true;
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = aName;
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = aUnit;
|
||||
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "";
|
||||
paramInfo.description = aDescription;
|
||||
paramInfo.isInstanceParam = false;
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = "tnom";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = "°C";
|
||||
paramInfo.category = PARAM::CATEGORY::TEMPERATURE;
|
||||
paramInfo.defaultValue = "27";
|
||||
paramInfo.description = "Nominal temperature";
|
||||
paramInfo.isInstanceParam = false;
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = "tc1";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = aUnit;
|
||||
paramInfo.category = PARAM::CATEGORY::TEMPERATURE;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "Temperature coefficient";
|
||||
paramInfo.isInstanceParam = false;
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
/*paramInfo.name = "tc2";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = aUnit;
|
||||
paramInfo.category = PARAM::CATEGORY::TEMPERATURE;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "2nd order temperature coefficient";
|
||||
paramInfo.isInstanceParam = false;
|
||||
paramInfos.push_back( paramInfo );*/
|
||||
|
||||
/*if( aName != "l" )
|
||||
{
|
||||
paramInfo.name = "bv_max";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = aUnit;
|
||||
paramInfo.category = PARAM::CATEGORY::LIMITING_VALUES;
|
||||
paramInfo.defaultValue = "";
|
||||
paramInfo.description = "Max. safe operating voltage";
|
||||
paramInfos.push_back( paramInfo );
|
||||
}*/
|
||||
|
||||
if( aName == "r" )
|
||||
{
|
||||
paramInfo.name = "noisy";
|
||||
paramInfo.type = SIM_VALUE::TYPE::BOOL;
|
||||
paramInfo.unit = "";
|
||||
paramInfo.category = PARAM::CATEGORY::NOISE;
|
||||
paramInfo.defaultValue = "True";
|
||||
paramInfo.description = "Enable thermal noise";
|
||||
paramInfo.isInstanceParam = false;
|
||||
paramInfos.push_back( paramInfo );
|
||||
}
|
||||
|
||||
return paramInfos;
|
||||
}
|
@ -1,48 +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 SIM_MODEL_PASSIVE_H
|
||||
#define SIM_MODEL_PASSIVE_H
|
||||
|
||||
#include <sim/sim_model.h>
|
||||
|
||||
|
||||
class SIM_MODEL_PASSIVE : public SIM_MODEL
|
||||
{
|
||||
public:
|
||||
SIM_MODEL_PASSIVE( TYPE aType );
|
||||
|
||||
bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation
|
||||
= SIM_VALUE_GRAMMAR::NOTATION::SPICE ) override;
|
||||
|
||||
private:
|
||||
static std::vector<PARAM::INFO> makeParamInfos( wxString aName, wxString aDescription,
|
||||
wxString aUnit );
|
||||
|
||||
std::vector<wxString> getPinNames() const override { return { "+", "-" }; }
|
||||
};
|
||||
|
||||
|
||||
#endif // SIM_MODEL_PASSIVE_H
|
@ -39,7 +39,7 @@ SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType )
|
||||
void SIM_MODEL_SOURCE::ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields )
|
||||
{
|
||||
if( !GetFieldValue( aFields, PARAMS_FIELD ).IsEmpty() )
|
||||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
@ -49,7 +49,7 @@ void SIM_MODEL_SOURCE::ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
void SIM_MODEL_SOURCE::ReadDataLibFields( unsigned aSymbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields )
|
||||
{
|
||||
if( !GetFieldValue( aFields, PARAMS_FIELD ).IsEmpty() )
|
||||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
@ -84,17 +84,30 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName,
|
||||
const wxString& aModelName,
|
||||
const std::vector<wxString>& aPinNetNames ) const
|
||||
{
|
||||
wxString argList = "";
|
||||
|
||||
for( const PARAM& param : GetParams() )
|
||||
wxString model;
|
||||
|
||||
wxString ac = FindParam( "ac" )->value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE );
|
||||
wxString ph = FindParam( "ph" )->value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE );
|
||||
|
||||
if( ac != "" )
|
||||
model << wxString::Format( "AC %s %s ", ac, ph );
|
||||
|
||||
if( GetSpiceInfo().inlineTypeString != "" )
|
||||
{
|
||||
wxString argStr = param.value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE );
|
||||
wxString argList = "";
|
||||
|
||||
for( const PARAM& param : GetParams() )
|
||||
{
|
||||
wxString argStr = param.value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE );
|
||||
|
||||
if( argStr != "" )
|
||||
argList << argStr << " ";
|
||||
if( argStr != "" )
|
||||
argList << argStr << " ";
|
||||
}
|
||||
|
||||
model << wxString::Format( "%s( %s)", GetSpiceInfo().inlineTypeString, argList );
|
||||
}
|
||||
|
||||
wxString model = wxString::Format( GetSpiceInfo().inlineTypeString + "( %s)", argList );
|
||||
else
|
||||
model << GetParam( 0 ).value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE );
|
||||
|
||||
return SIM_MODEL::GenerateSpiceItemLine( aRefName, model, aPinNetNames );
|
||||
}
|
||||
@ -114,11 +127,11 @@ const std::vector<PARAM::INFO>& SIM_MODEL_SOURCE::makeParamInfos( TYPE aType )
|
||||
static std::vector<PARAM::INFO> vexp = makeExpParamInfos( "v", "V" );
|
||||
static std::vector<PARAM::INFO> iexp = makeExpParamInfos( "i", "A" );
|
||||
|
||||
static std::vector<PARAM::INFO> vsfam = makeSfamParamInfos( "v", "V" );
|
||||
/*static std::vector<PARAM::INFO> vsfam = makeSfamParamInfos( "v", "V" );
|
||||
static std::vector<PARAM::INFO> isfam = makeSfamParamInfos( "i", "A" );
|
||||
|
||||
static std::vector<PARAM::INFO> vsffm = makeSffmParamInfos( "v", "V" );
|
||||
static std::vector<PARAM::INFO> isffm = makeSffmParamInfos( "i", "A" );
|
||||
static std::vector<PARAM::INFO> isffm = makeSffmParamInfos( "i", "A" );*/
|
||||
|
||||
static std::vector<PARAM::INFO> vpwl = makePwlParamInfos( "v", "Voltage", "V" );
|
||||
static std::vector<PARAM::INFO> ipwl = makePwlParamInfos( "i", "Current", "A" );
|
||||
@ -154,10 +167,10 @@ const std::vector<PARAM::INFO>& SIM_MODEL_SOURCE::makeParamInfos( TYPE aType )
|
||||
case TYPE::I_PULSE: return ipulse;
|
||||
case TYPE::V_EXP: return vexp;
|
||||
case TYPE::I_EXP: return iexp;
|
||||
case TYPE::V_SFAM: return vsfam;
|
||||
/*case TYPE::V_SFAM: return vsfam;
|
||||
case TYPE::I_SFAM: return isfam;
|
||||
case TYPE::V_SFFM: return vsffm;
|
||||
case TYPE::I_SFFM: return isffm;
|
||||
case TYPE::I_SFFM: return isffm;*/
|
||||
case TYPE::V_PWL: return vpwl;
|
||||
case TYPE::I_PWL: return ipwl;
|
||||
case TYPE::V_WHITENOISE: return vwhitenoise;
|
||||
@ -187,7 +200,7 @@ bool SIM_MODEL_SOURCE::SetParamValue( unsigned aParamIndex, const wxString& aVal
|
||||
{
|
||||
// Sources are special. All preceding parameter values must be filled. If they are not, fill
|
||||
// them out automatically. If a value is nulled, delete everything after it.
|
||||
if( aValue.IsEmpty() )
|
||||
if( aValue == "" )
|
||||
{
|
||||
for( unsigned i = aParamIndex; i < GetParamCount(); ++i )
|
||||
SIM_MODEL::SetParamValue( i, "", aNotation );
|
||||
@ -196,7 +209,7 @@ bool SIM_MODEL_SOURCE::SetParamValue( unsigned aParamIndex, const wxString& aVal
|
||||
{
|
||||
for( unsigned i = 0; i < aParamIndex; ++i )
|
||||
{
|
||||
if( GetParam( i ).value->ToString().IsEmpty() )
|
||||
if( GetParam( i ).value->ToString() == "" )
|
||||
SIM_MODEL::SetParamValue( i, "0", aNotation );
|
||||
}
|
||||
}
|
||||
@ -215,11 +228,13 @@ wxString SIM_MODEL_SOURCE::GenerateParamValuePair( const PARAM& aParam, bool& aI
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SIM_MODEL_SOURCE::inferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields )
|
||||
void SIM_MODEL_SOURCE::inferredReadDataFields( unsigned aSymbolPinCount,
|
||||
const std::vector<T>* aFields )
|
||||
{
|
||||
ParsePinsField( aSymbolPinCount, PINS_FIELD );
|
||||
|
||||
if( ( InferTypeFromRef( GetFieldValue( aFields, REFERENCE_FIELD ) ) == GetType()
|
||||
if( ( InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
||||
GetFieldValue( aFields, VALUE_FIELD ) ) == GetType()
|
||||
&& ParseParamsField( GetFieldValue( aFields, VALUE_FIELD ) ) )
|
||||
|| GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue )
|
||||
{
|
||||
@ -233,8 +248,8 @@ void SIM_MODEL_SOURCE::inferredWriteDataFields( std::vector<T>& aFields ) const
|
||||
{
|
||||
wxString value = GetFieldValue( &aFields, PARAMS_FIELD );
|
||||
|
||||
if( value.IsEmpty() )
|
||||
value = DeviceTypeInfo( GetDeviceType() ).fieldValue;
|
||||
if( value == "" )
|
||||
value = GetDeviceTypeInfo().fieldValue;
|
||||
|
||||
WriteInferredDataFields( aFields, value );
|
||||
}
|
||||
@ -259,6 +274,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeDcParamInfos( wxString aPrefix, w
|
||||
paramInfo.description = "DC value";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -308,14 +324,17 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeSinParamInfos( wxString aPrefix,
|
||||
paramInfo.description = "Damping factor";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = "phase";
|
||||
// "phase" is not needed. "td" is enough.
|
||||
|
||||
/*paramInfo.name = "phase";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = "deg";
|
||||
paramInfo.unit = "°";
|
||||
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "Phase";
|
||||
paramInfos.push_back( paramInfo );
|
||||
paramInfos.push_back( paramInfo );*/
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -365,7 +384,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makePulseParamInfos( wxString aPrefix
|
||||
paramInfo.description = "Fall time";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = "pw";
|
||||
paramInfo.name = "tw"; // Ngspice calls it "pw".
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = "s";
|
||||
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
|
||||
@ -381,14 +400,17 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makePulseParamInfos( wxString aPrefix
|
||||
paramInfo.description = "Period";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = "phase";
|
||||
// "phase" is not needed. "td" is enough.
|
||||
|
||||
/*paramInfo.name = "phase";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = "deg";
|
||||
paramInfo.unit = "°";
|
||||
paramInfo.category = PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "Phase";
|
||||
paramInfos.push_back( paramInfo );
|
||||
paramInfos.push_back( paramInfo );*/
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -446,11 +468,12 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeExpParamInfos( wxString aPrefix,
|
||||
paramInfo.description = "Fall time constant";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
|
||||
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeSfamParamInfos( wxString aPrefix, wxString aUnit )
|
||||
/*std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeSfamParamInfos( wxString aPrefix, wxString aUnit )
|
||||
{
|
||||
std::vector<PARAM::INFO> paramInfos;
|
||||
PARAM::INFO paramInfo;
|
||||
@ -494,6 +517,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeSfamParamInfos( wxString aPrefix,
|
||||
paramInfo.description = "Modulating frequency";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -545,7 +569,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeSffmParamInfos( wxString aPrefix,
|
||||
|
||||
paramInfo.name = "phasec";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = "deg";
|
||||
paramInfo.unit = "°";
|
||||
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "Carrier phase";
|
||||
@ -553,14 +577,15 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeSffmParamInfos( wxString aPrefix,
|
||||
|
||||
paramInfo.name = "phases";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = "deg";
|
||||
paramInfo.unit = "°";
|
||||
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::PRINCIPAL;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "Signal phase";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makePwlParamInfos( wxString aPrefix, wxString aQuantity,
|
||||
@ -601,6 +626,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makePwlParamInfos( wxString aPrefix,
|
||||
paramInfo.description = "Delay";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -635,6 +661,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeWhiteNoiseParamInfos( wxString aP
|
||||
paramInfo.description = "Time step";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -677,6 +704,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makePinkNoiseParamInfos( wxString aPr
|
||||
paramInfo.description = "Time step";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -719,6 +747,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeBurstNoiseParamInfos( wxString aP
|
||||
paramInfo.description = "Time step";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -753,6 +782,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeRandomUniformParamInfos( wxString
|
||||
paramInfo.description = "Delay";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -787,6 +817,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeRandomNormalParamInfos( wxString
|
||||
paramInfo.description = "Delay";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -821,6 +852,7 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeRandomExpParamInfos( wxString aPr
|
||||
paramInfo.description = "Delay";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
@ -855,5 +887,27 @@ std::vector<PARAM::INFO> SIM_MODEL_SOURCE::makeRandomPoissonParamInfos( wxString
|
||||
paramInfo.description = "Delay";
|
||||
paramInfos.push_back( paramInfo );
|
||||
|
||||
appendAcParamInfos( paramInfos, aUnit );
|
||||
return paramInfos;
|
||||
}
|
||||
|
||||
void SIM_MODEL_SOURCE::appendAcParamInfos( std::vector<PARAM::INFO>& aParamInfos, wxString aUnit )
|
||||
{
|
||||
PARAM::INFO paramInfo;
|
||||
|
||||
paramInfo.name = "ac";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = aUnit;
|
||||
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::AC;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "AC magnitude";
|
||||
aParamInfos.push_back( paramInfo );
|
||||
|
||||
paramInfo.name = "ph";
|
||||
paramInfo.type = SIM_VALUE::TYPE::FLOAT;
|
||||
paramInfo.unit = "°";
|
||||
paramInfo.category = SIM_MODEL::PARAM::CATEGORY::AC;
|
||||
paramInfo.defaultValue = "0";
|
||||
paramInfo.description = "AC phase";
|
||||
aParamInfos.push_back( paramInfo );
|
||||
}
|
||||
|
@ -33,8 +33,10 @@ class SIM_MODEL_SOURCE : public SIM_MODEL
|
||||
public:
|
||||
SIM_MODEL_SOURCE( TYPE aType );
|
||||
|
||||
void ReadDataSchFields( unsigned aSymbolPinCount, const std::vector<SCH_FIELD>* aFields ) override;
|
||||
void ReadDataLibFields( unsigned aSymbolPinCount, const std::vector<LIB_FIELD>* aFields ) override;
|
||||
void ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields ) override;
|
||||
void ReadDataLibFields( unsigned aSymbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields ) override;
|
||||
|
||||
void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override;
|
||||
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
|
||||
@ -67,8 +69,8 @@ private:
|
||||
static std::vector<PARAM::INFO> makeSinParamInfos( wxString aPrefix, wxString aUnit );
|
||||
static std::vector<PARAM::INFO> makePulseParamInfos( wxString aPrefix, wxString aUnit );
|
||||
static std::vector<PARAM::INFO> makeExpParamInfos( wxString aPrefix, wxString aUnit );
|
||||
static std::vector<PARAM::INFO> makeSfamParamInfos( wxString aPrefix, wxString aUnit );
|
||||
static std::vector<PARAM::INFO> makeSffmParamInfos( wxString aPrefix, wxString aUnit );
|
||||
//static std::vector<PARAM::INFO> makeSfamParamInfos( wxString aPrefix, wxString aUnit );
|
||||
//static std::vector<PARAM::INFO> makeSffmParamInfos( wxString aPrefix, wxString aUnit );
|
||||
static std::vector<PARAM::INFO> makePwlParamInfos( wxString aPrefix, wxString aQuantity,
|
||||
wxString aUnit );
|
||||
static std::vector<PARAM::INFO> makeWhiteNoiseParamInfos( wxString aPrefix, wxString aUnit );
|
||||
@ -79,6 +81,8 @@ private:
|
||||
static std::vector<PARAM::INFO> makeRandomExpParamInfos( wxString aPrefix, wxString aUnit );
|
||||
static std::vector<PARAM::INFO> makeRandomPoissonParamInfos( wxString aPrefix, wxString aUnit );
|
||||
|
||||
static void appendAcParamInfos( std::vector<PARAM::INFO>& aParamInfos, wxString aUnit );
|
||||
|
||||
bool m_isInferred;
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include <sim/sim_model_subckt.h>
|
||||
#include <sim/spice_grammar.h>
|
||||
#include <pegtl.hpp>
|
||||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
|
||||
|
@ -28,7 +28,8 @@ using PARAM = SIM_MODEL::PARAM;
|
||||
|
||||
|
||||
SIM_MODEL_TLINE::SIM_MODEL_TLINE( TYPE aType )
|
||||
: SIM_MODEL( aType )
|
||||
: SIM_MODEL( aType ),
|
||||
m_isInferred( false )
|
||||
{
|
||||
static std::vector<PARAM::INFO> z0 = makeZ0ParamInfo();
|
||||
static std::vector<PARAM::INFO> rlgc = makeRlgcParamInfo();
|
||||
@ -51,10 +52,70 @@ SIM_MODEL_TLINE::SIM_MODEL_TLINE( TYPE aType )
|
||||
}
|
||||
|
||||
|
||||
/*wxString SIM_MODEL_TLINE::GenerateSpiceItemName( const wxString& aRefName ) const
|
||||
void SIM_MODEL_TLINE::ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields )
|
||||
{
|
||||
|
||||
}*/
|
||||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataSchFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
void SIM_MODEL_TLINE::ReadDataLibFields( unsigned aSymbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields )
|
||||
{
|
||||
if( GetFieldValue( aFields, PARAMS_FIELD ) != "" )
|
||||
SIM_MODEL::ReadDataLibFields( aSymbolPinCount, aFields );
|
||||
else
|
||||
inferredReadDataFields( aSymbolPinCount, aFields );
|
||||
}
|
||||
|
||||
|
||||
void SIM_MODEL_TLINE::WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const
|
||||
{
|
||||
SIM_MODEL::WriteDataSchFields( aFields );
|
||||
|
||||
if( m_isInferred )
|
||||
inferredWriteDataFields( aFields );
|
||||
}
|
||||
|
||||
|
||||
void SIM_MODEL_TLINE::WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const
|
||||
{
|
||||
SIM_MODEL::WriteDataLibFields( aFields );
|
||||
|
||||
if( m_isInferred )
|
||||
inferredWriteDataFields( aFields );
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SIM_MODEL_TLINE::inferredReadDataFields( unsigned aSymbolPinCount,
|
||||
const std::vector<T>* aFields )
|
||||
{
|
||||
ParsePinsField( aSymbolPinCount, PINS_FIELD );
|
||||
|
||||
if( ( InferTypeFromRefAndValue( GetFieldValue( aFields, REFERENCE_FIELD ),
|
||||
GetFieldValue( aFields, VALUE_FIELD ) ) == GetType()
|
||||
&& ParseParamsField( GetFieldValue( aFields, VALUE_FIELD ) ) )
|
||||
// If Value is device type, this is an empty model
|
||||
|| GetFieldValue( aFields, VALUE_FIELD ) == DeviceTypeInfo( GetDeviceType() ).fieldValue )
|
||||
{
|
||||
m_isInferred = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SIM_MODEL_TLINE::inferredWriteDataFields( std::vector<T>& aFields ) const
|
||||
{
|
||||
wxString value = GetFieldValue( &aFields, PARAMS_FIELD );
|
||||
|
||||
if( value == "" )
|
||||
value = GetDeviceTypeInfo().fieldValue;
|
||||
|
||||
WriteInferredDataFields( aFields, value );
|
||||
}
|
||||
|
||||
|
||||
std::vector<PARAM::INFO> SIM_MODEL_TLINE::makeZ0ParamInfo()
|
||||
|
@ -33,7 +33,21 @@ class SIM_MODEL_TLINE : public SIM_MODEL
|
||||
public:
|
||||
SIM_MODEL_TLINE( TYPE aType );
|
||||
|
||||
void ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
const std::vector<SCH_FIELD>* aFields ) override;
|
||||
void ReadDataLibFields( unsigned aSymbolPinCount,
|
||||
const std::vector<LIB_FIELD>* aFields ) override;
|
||||
|
||||
void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override;
|
||||
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void inferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
||||
|
||||
template <typename T>
|
||||
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
||||
|
||||
static std::vector<PARAM::INFO> makeZ0ParamInfo();
|
||||
static std::vector<PARAM::INFO> makeRlgcParamInfo();
|
||||
|
||||
@ -41,6 +55,8 @@ private:
|
||||
|
||||
// Subcircuits require models even when they have no Spice instance parameters.
|
||||
bool requiresSpiceModel() const override;
|
||||
|
||||
bool m_isInferred;
|
||||
};
|
||||
|
||||
#endif // SIM_MODEL_TLINE_H
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user