ADDED support to save contributions from all noise generators.

You must first check the checkbox in the Simulation Command dialog,
after which the signals will appear in the User Defined Signals
autocomplete lists.
This commit is contained in:
Jeff Young 2023-07-04 11:04:20 +01:00
parent 37772ac29e
commit 492ef62053
14 changed files with 166 additions and 88 deletions

View File

@ -123,6 +123,41 @@ DIALOG_SIM_COMMAND::DIALOG_SIM_COMMAND( wxWindow* aParent,
SetupStandardButtons();
}
bool DIALOG_SIM_COMMAND::TransferDataToWindow()
{
/// @todo one day it could interpret the sim command and fill out appropriate fields.
if( empty( m_customTxt ) )
loadDirectives();
m_fixIncludePaths->SetValue( m_settings->GetFixIncludePaths() );
NGSPICE_SIMULATOR_SETTINGS* ngspiceSettings =
dynamic_cast<NGSPICE_SIMULATOR_SETTINGS*>( m_settings.get() );
if( ngspiceSettings )
{
switch( ngspiceSettings->GetModelMode() )
{
case NGSPICE_MODEL_MODE::USER_CONFIG: m_compatibilityModeChoice->SetSelection( 0 ); break;
case NGSPICE_MODEL_MODE::NGSPICE: m_compatibilityModeChoice->SetSelection( 1 ); break;
case NGSPICE_MODEL_MODE::PSPICE: m_compatibilityModeChoice->SetSelection( 2 ); break;
case NGSPICE_MODEL_MODE::LTSPICE: m_compatibilityModeChoice->SetSelection( 3 ); break;
case NGSPICE_MODEL_MODE::LT_PSPICE: m_compatibilityModeChoice->SetSelection( 4 ); break;
case NGSPICE_MODEL_MODE::HSPICE: m_compatibilityModeChoice->SetSelection( 5 ); break;
default:
wxFAIL_MSG( wxString::Format( "Unknown NGSPICE_MODEL_MODE %d.",
ngspiceSettings->GetModelMode() ) );
break;
}
}
if( m_simCommand.IsEmpty() && !empty( m_customTxt ) )
parseCommand( m_customTxt->GetValue() );
return true;
}
wxString DIALOG_SIM_COMMAND::evaluateDCControls( wxChoice* aDcSource, wxTextCtrl* aDcStart,
wxTextCtrl* aDcStop, wxTextCtrl* aDcIncr )
{
@ -241,14 +276,15 @@ bool DIALOG_SIM_COMMAND::TransferDataFromWindow()
if( !ref.IsEmpty() )
ref = wxS( "," ) + m_circuitModel->GetItemName( std::string( ref.ToUTF8() ) );
m_simCommand.Printf( ".noise v(%s%s) %s %s %s %s %s",
m_simCommand.Printf( ".noise v(%s%s) %s %s %s %s %s %s",
output,
ref,
noiseSource,
scaleToString( m_noiseScale->GetSelection() ),
m_noisePointsNumber->GetValue(),
SPICE_VALUE( m_noiseFreqStart->GetValue() ).ToSpiceString(),
SPICE_VALUE( m_noiseFreqStop->GetValue() ).ToSpiceString() );
SPICE_VALUE( m_noiseFreqStop->GetValue() ).ToSpiceString(),
m_saveAllNoise->GetValue() ? "1" : "" );
}
else if( page == m_pgOP ) // DC operating point analysis
{
@ -330,41 +366,6 @@ bool DIALOG_SIM_COMMAND::TransferDataFromWindow()
}
bool DIALOG_SIM_COMMAND::TransferDataToWindow()
{
/// @todo one day it could interpret the sim command and fill out appropriate fields.
if( empty( m_customTxt ) )
loadDirectives();
m_fixIncludePaths->SetValue( m_settings->GetFixIncludePaths() );
NGSPICE_SIMULATOR_SETTINGS* ngspiceSettings =
dynamic_cast<NGSPICE_SIMULATOR_SETTINGS*>( m_settings.get() );
if( ngspiceSettings )
{
switch( ngspiceSettings->GetModelMode() )
{
case NGSPICE_MODEL_MODE::USER_CONFIG: m_compatibilityModeChoice->SetSelection( 0 ); break;
case NGSPICE_MODEL_MODE::NGSPICE: m_compatibilityModeChoice->SetSelection( 1 ); break;
case NGSPICE_MODEL_MODE::PSPICE: m_compatibilityModeChoice->SetSelection( 2 ); break;
case NGSPICE_MODEL_MODE::LTSPICE: m_compatibilityModeChoice->SetSelection( 3 ); break;
case NGSPICE_MODEL_MODE::LT_PSPICE: m_compatibilityModeChoice->SetSelection( 4 ); break;
case NGSPICE_MODEL_MODE::HSPICE: m_compatibilityModeChoice->SetSelection( 5 ); break;
default:
wxFAIL_MSG( wxString::Format( "Unknown NGSPICE_MODEL_MODE %d.",
ngspiceSettings->GetModelMode() ) );
break;
}
}
if( m_simCommand.IsEmpty() && !empty( m_customTxt ) )
parseCommand( m_customTxt->GetValue() );
return true;
}
void DIALOG_SIM_COMMAND::updateDCSources( wxChar aType, wxChoice* aSource )
{
wxString prevSelection;
@ -485,9 +486,10 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand )
SPICE_VALUE pts;
SPICE_VALUE fStart;
SPICE_VALUE fStop;
bool saveAll;
m_circuitModel->ParseNoiseCommand( aCommand, &output, &ref, &source, &scale, &pts,
&fStart, &fStop );
&fStart, &fStop, &saveAll );
m_noiseMeas->SetStringSelection( output );
m_noiseRef->SetStringSelection( ref );
@ -505,6 +507,8 @@ void DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand )
m_noisePointsNumber->SetValue( pts.ToSpiceString() );
m_noiseFreqStart->SetValue( fStart.ToSpiceString() );
m_noiseFreqStop->SetValue( fStop.ToSpiceString() );
m_saveAllNoise->SetValue( saveAll );
}
else if( token == ".tran" )
{

View File

@ -312,11 +312,14 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i
fgSizer11->Add( m_noiseFreqStopUnits, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
bSizer10->Add( fgSizer11, 0, wxALIGN_BOTTOM|wxTOP|wxBOTTOM|wxLEFT, 5 );
bSizer10->Add( fgSizer11, 0, wxALIGN_BOTTOM|wxTOP|wxLEFT, 5 );
bSizer15->Add( bSizer10, 0, wxEXPAND|wxTOP, 5 );
m_saveAllNoise = new wxCheckBox( m_pgNoise, wxID_ANY, _("Save contributions from all noise generators"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer15->Add( m_saveAllNoise, 0, wxALL, 10 );
m_pgNoise->SetSizer( bSizer15 );
m_pgNoise->Layout();

View File

@ -3113,7 +3113,7 @@
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_BOTTOM|wxTOP|wxBOTTOM|wxLEFT</property>
<property name="flag">wxALIGN_BOTTOM|wxTOP|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxFlexGridSizer" expanded="1">
<property name="cols">3</property>
@ -3638,6 +3638,70 @@
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Save contributions from all noise generators</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_saveAllNoise</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
</object>
</object>
</object>

View File

@ -97,6 +97,7 @@ class DIALOG_SIM_COMMAND_BASE : public DIALOG_SHIM
wxStaticText* m_staticText31;
wxTextCtrl* m_noiseFreqStop;
wxStaticText* m_noiseFreqStopUnits;
wxCheckBox* m_saveAllNoise;
wxPanel* m_pgOP;
wxStaticText* m_staticText13;
wxPanel* m_pgPoleZero;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2008-2021 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2008-2023 KiCad Developers, see change_log.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
@ -28,14 +28,6 @@
#include <id.h>
/**
* The maximum number of items in the clarify selection context menu. While in
* most cases it is highly unlikely that there would ever be more than 10 items
* at the current cursor, there are some exceptions (a bunch of pins created at
* once, for instance). The current setting of 200 is arbitrary.
*/
#define MAX_SELECT_ITEM_IDS 200
/**
* The maximum number of units per package.
* While counts approaching 100 start to make the unit-selection popup menu
@ -75,11 +67,6 @@ enum id_eeschema_frm
ID_LIBVIEW_SYM_FILTER,
ID_LIBVIEW_SYM_LIST,
ID_SIM_RUN,
ID_SIM_TUNE,
ID_SIM_PROBE,
ID_SIM_ADD_SIGNALS,
ID_END_EESCHEMA_ID_LIST, // End of IDs specific to Eeschema
// These ID are used in context menus,

View File

@ -84,25 +84,25 @@ void NGSPICE::Init( const SPICE_SIMULATOR_SETTINGS* aSettings )
}
std::vector<std::string> NGSPICE::AllPlots() const
std::vector<std::string> NGSPICE::AllVectors() const
{
LOCALE_IO c_locale; // ngspice works correctly only with C locale
char* currentPlot = m_ngSpice_CurPlot();
char** allPlots = m_ngSpice_AllVecs( currentPlot );
int noOfPlots = 0;
char** allVectors = m_ngSpice_AllVecs( currentPlot );
int noOfVectors = 0;
std::vector<std::string> retVal;
if( allPlots != nullptr )
if( allVectors != nullptr )
{
for( char** plot = allPlots; *plot != nullptr; plot++ )
noOfPlots++;
for( char** plot = allVectors; *plot != nullptr; plot++ )
noOfVectors++;
retVal.reserve( noOfPlots );
retVal.reserve( noOfVectors );
for( int i = 0; i < noOfPlots; i++, allPlots++ )
for( int i = 0; i < noOfVectors; i++, allVectors++ )
{
std::string vec = *allPlots;
std::string vec = *allVectors;
retVal.push_back( vec );
}
}
@ -336,10 +336,10 @@ wxString NGSPICE::GetXAxis( SIM_TYPE aType ) const
case ST_DC:
// find plot, which ends with "-sweep"
for( wxString plot : AllPlots() )
for( wxString vector : AllVectors() )
{
if( plot.Lower().EndsWith( wxS( "-sweep" ) ) )
return plot;
if( vector.Lower().EndsWith( wxS( "-sweep" ) ) )
return vector;
}
return wxS( "sweep" );

View File

@ -80,8 +80,8 @@ public:
///< @copydoc SPICE_SIMULATOR::GetXAxis()
wxString GetXAxis( SIM_TYPE aType ) const override final;
///< @copydoc SPICE_SIMULATOR::AllPlots()
std::vector<std::string> AllPlots() const override final;
///< @copydoc SPICE_SIMULATOR::AllVectors()
std::vector<std::string> AllVectors() const override final;
///< @copydoc SPICE_SIMULATOR::GetPlot()
std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) override final;

View File

@ -147,7 +147,7 @@ bool NGSPICE_CIRCUIT_MODEL::ParseDCCommand( const wxString& aCmd, SPICE_DC_PARAM
bool NGSPICE_CIRCUIT_MODEL::ParseNoiseCommand( const wxString& aCmd, wxString* aOutput,
wxString* aRef, wxString* aSource, wxString* aScale,
SPICE_VALUE* aPts, SPICE_VALUE* aFStart,
SPICE_VALUE* aFStop )
SPICE_VALUE* aFStop, bool* aSaveAll )
{
if( !aCmd.Lower().StartsWith( wxS( ".noise" ) ) )
return false;
@ -197,7 +197,13 @@ bool NGSPICE_CIRCUIT_MODEL::ParseNoiseCommand( const wxString& aCmd, wxString* a
}
if( !token.IsEmpty() )
{
*aFStop = SPICE_VALUE( token );
token = tokens.GetNextToken();
}
if( !token.IsEmpty() )
*aSaveAll = true;
return true;
}

View File

@ -129,7 +129,7 @@ public:
bool ParseNoiseCommand( const wxString& aCmd, wxString* aOutput, wxString* aRef,
wxString* aSource, wxString* aScale, SPICE_VALUE* aPts,
SPICE_VALUE* aFStart, SPICE_VALUE* aFStop );
SPICE_VALUE* aFStart, SPICE_VALUE* aFStop, bool* aSaveAll );
/**
* Determine if a directive is a simulation command.

View File

@ -427,7 +427,7 @@ void SIMULATOR_FRAME::NewPlotPanel( const wxString& aSimCommand, int aOptions )
}
const std::vector<wxString>& SIMULATOR_FRAME::Signals()
const std::vector<wxString> SIMULATOR_FRAME::Signals()
{
return m_panel->Signals();
}

View File

@ -95,7 +95,10 @@ public:
*/
bool EditSimCommand();
const std::vector<wxString>& Signals();
/**
* @return the list of signals in the current simulation results.
*/
const std::vector<wxString> Signals();
const std::map<int, wxString>& UserDefinedSignals();

View File

@ -741,8 +741,8 @@ void SIMULATOR_PANEL::rebuildSignalsList()
if( simType == ST_NOISE )
{
addSignal( wxS( "inoise" ) );
addSignal( wxS( "onoise" ) );
addSignal( wxS( "inoise_spectrum" ) );
addSignal( wxS( "onoise_spectrum" ) );
}
// Add .PROBE directives
@ -847,18 +847,16 @@ wxString SIMULATOR_PANEL::vectorNameFromSignalName( const wxString& aSignalName,
if( aTraceType )
{
wxString name = aSignalName.Upper();
if( name == wxS( "INOISE" ) || name == wxS( "ONOISE" ) )
if( circuitModel()->GetSimType() == ST_NOISE )
{
if( getNoiseSource().Upper().StartsWith( 'I' ) )
*aTraceType = SPT_CURRENT;
else
*aTraceType = SPT_VOLTAGE;
}
else if( !name.IsEmpty() )
else
{
wxUniChar firstChar = name[0];
wxUniChar firstChar = aSignalName.Upper()[0];
if( firstChar == 'V' )
*aTraceType = SPT_VOLTAGE;
@ -1451,10 +1449,6 @@ void SIMULATOR_PANEL::updateTrace( const wxString& aVectorName, int aTraceType,
break;
case ST_NOISE:
simVectorName = wxString::Format( wxS( "noise1.%s_spectrum" ), simVectorName );
data_y = simulator()->GetMagPlot( (const char*) simVectorName.c_str() );
break;
case ST_DC:
case ST_TRANSIENT:
data_y = simulator()->GetMagPlot( (const char*) simVectorName.c_str() );
@ -2137,9 +2131,10 @@ wxString SIMULATOR_PANEL::getNoiseSource() const
SPICE_VALUE pts;
SPICE_VALUE fStart;
SPICE_VALUE fStop;
bool saveAll;
circuitModel()->ParseNoiseCommand( circuitModel()->GetSimCommand(), &output, &ref, &source,
&scale, &pts, &fStart, &fStop );
&scale, &pts, &fStart, &fStop, &saveAll );
return source;
}
@ -2388,6 +2383,17 @@ void SIMULATOR_PANEL::OnSimReport( const wxString& aMsg )
}
std::vector<wxString> SIMULATOR_PANEL::Signals()
{
std::vector<wxString> signals;
for( const std::string& vec : simulator()->AllVectors() )
signals.emplace_back( vec );
return signals;
}
void SIMULATOR_PANEL::OnSimRefresh( bool aFinal )
{
SIM_TYPE simType = circuitModel()->GetSimType();
@ -2413,7 +2419,9 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal )
m_simConsole->AppendText( _( "\n\nSimulation results:\n\n" ) );
m_simConsole->SetInsertionPointEnd();
for( const std::string& vec : simulator()->AllPlots() )
simulator()->Command( "setplot noise2" );
for( const std::string& vec : simulator()->AllVectors() )
{
std::vector<double> val_list = simulator()->GetRealPlot( vec, 1 );
wxString value = SPICE_VALUE( val_list[ 0 ] ).ToSpiceString();
@ -2423,6 +2431,8 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal )
m_simConsole->AppendText( msg );
m_simConsole->SetInsertionPointEnd();
}
simulator()->Command( "setplot noise1" );
}
SIM_PLOT_PANEL* plotPanel = dynamic_cast<SIM_PLOT_PANEL*>( plotPanelWindow );
@ -2483,7 +2493,7 @@ void SIMULATOR_PANEL::OnSimRefresh( bool aFinal )
m_simConsole->AppendText( _( "\n\nSimulation results:\n\n" ) );
m_simConsole->SetInsertionPointEnd();
for( const std::string& vec : simulator()->AllPlots() )
for( const std::string& vec : simulator()->AllVectors() )
{
std::vector<double> val_list = simulator()->GetRealPlot( vec, 1 );
wxString value = SPICE_VALUE( val_list[ 0 ] ).ToSpiceString();

View File

@ -91,7 +91,7 @@ public:
*/
SIM_PLOT_PANEL_BASE* NewPlotPanel( const wxString& aSimCommand, int aSimOptions );
const std::vector<wxString>& Signals() { return m_signals; }
std::vector<wxString> Signals();
const std::map<int, wxString>& UserDefinedSignals() { return m_userDefinedSignals; }
void SetUserDefinedSignals( const std::map<int, wxString>& aSignals );

View File

@ -91,7 +91,7 @@ public:
*
* @return List of vector names. ?May not match to the net name elements.
*/
virtual std::vector<std::string> AllPlots() const = 0;
virtual std::vector<std::string> AllVectors() const = 0;
/**
* Return a requested vector with complex values. If the vector is real, then