Simulator code formatting and clean up

This commit is contained in:
Maciej Suminski 2016-08-11 14:42:17 +02:00
parent 957c6ec417
commit eeeb3e0a9a
13 changed files with 443 additions and 299 deletions

View File

@ -44,8 +44,6 @@ wxString NETLIST_EXPORTER_PSPICE_SIM::GetSpiceVector( const wxString& aName, SIM
return wxString::Format( "V(%d)", it->second ); return wxString::Format( "V(%d)", it->second );
} }
/// @todo check is Lower() is required
else if( aType & SPT_CURRENT ) else if( aType & SPT_CURRENT )
{ {
return wxString::Format( "@%s[%s]", GetSpiceDevice( aName ).Lower(), return wxString::Format( "@%s[%s]", GetSpiceDevice( aName ).Lower(),
@ -183,5 +181,4 @@ void NETLIST_EXPORTER_PSPICE_SIM::writeDirectives( OUTPUTFORMATTER* aFormatter,
// Finish with our custom simulation command // Finish with our custom simulation command
aFormatter->Print( 0, "%s\n", (const char*) m_simCommand.c_str() ); aFormatter->Print( 0, "%s\n", (const char*) m_simCommand.c_str() );
} }
} }

View File

@ -64,30 +64,53 @@ public:
*/ */
static const std::vector<wxString>& GetCurrents( SPICE_PRIMITIVE aPrimitive ); static const std::vector<wxString>& GetCurrents( SPICE_PRIMITIVE aPrimitive );
/**
* @brief Overrides the simulation command directive.
*/
void SetSimCommand( const wxString& aCmd ) void SetSimCommand( const wxString& aCmd )
{ {
m_simCommand = aCmd; m_simCommand = aCmd;
} }
/**
* @brief Returns the simulation command directive.
*/
const wxString& GetSimCommand() const const wxString& GetSimCommand() const
{ {
return m_simCommand; return m_simCommand;
} }
/**
* @brief Clears the simulation command directive.
*/
void ClearSimCommand() void ClearSimCommand()
{ {
m_simCommand.Clear(); m_simCommand.Clear();
} }
/**
* @brief Returns simulation type basing on the simulation command directives.
* Simulation directives set using SetSimCommand() have priority over the ones placed in
* schematic sheets.
*/
SIM_TYPE GetSimType(); SIM_TYPE GetSimType();
/**
* @brief Returns simulation command directives placed in schematic sheets (if any).
*/
wxString GetSheetSimCommand(); wxString GetSheetSimCommand();
/**
* @brief Determines if a directive is a simulation command.
*/
static bool IsSimCommand( const wxString& aCmd ) static bool IsSimCommand( const wxString& aCmd )
{ {
return CommandToSimType( aCmd ) != ST_UNKNOWN; return CommandToSimType( aCmd ) != ST_UNKNOWN;
} }
/**
* @brief Returns simulation type basing on a simulation command directive.
*/
static SIM_TYPE CommandToSimType( const wxString& aCmd ); static SIM_TYPE CommandToSimType( const wxString& aCmd );
protected: protected:
@ -95,7 +118,7 @@ protected:
private: private:
///> Overridden simulation command ///> Custom simulation command (has priority over the schematic sheet simulation commands)
wxString m_simCommand; wxString m_simCommand;
}; };

View File

@ -52,7 +52,6 @@ NGSPICE::NGSPICE()
m_ngSpice_AllPlots = (ngSpice_AllPlots) m_dll->GetSymbol( "ngSpice_AllPlots" ); m_ngSpice_AllPlots = (ngSpice_AllPlots) m_dll->GetSymbol( "ngSpice_AllPlots" );
m_ngSpice_AllVecs = (ngSpice_AllVecs) m_dll->GetSymbol( "ngSpice_AllVecs" ); m_ngSpice_AllVecs = (ngSpice_AllVecs) m_dll->GetSymbol( "ngSpice_AllVecs" );
m_ngSpice_Running = (ngSpice_Running) m_dll->GetSymbol( "ngSpice_running" ); m_ngSpice_Running = (ngSpice_Running) m_dll->GetSymbol( "ngSpice_running" );
} }
@ -243,7 +242,7 @@ bool NGSPICE::LoadNetlist( const string& aNetlist )
bool NGSPICE::Run() bool NGSPICE::Run()
{ {
setlocale( LC_ALL, "C" ); setlocale( LC_ALL, "C" );
bool rv = Command( "bg_run" ); bool rv = Command( "bg_run" ); // bg_* commands execute in a separate thread
setlocale( LC_ALL, "" ); setlocale( LC_ALL, "" );
return rv; return rv;
} }
@ -252,7 +251,7 @@ bool NGSPICE::Run()
bool NGSPICE::Stop() bool NGSPICE::Stop()
{ {
setlocale( LC_ALL, "C" ); setlocale( LC_ALL, "C" );
bool rv = Command( "bg_halt" ); bool rv = Command( "bg_halt" ); // bg_* commands execute in a separate thread
setlocale( LC_ALL, "" ); setlocale( LC_ALL, "" );
return rv; return rv;
} }
@ -301,10 +300,11 @@ string NGSPICE::GetXAxis( SIM_TYPE aType ) const
return string( "" ); return string( "" );
} }
int NGSPICE::cbControlledExit ( int status, bool immediate, bool exit_upon_quit, int id, void *user )
int NGSPICE::cbControlledExit( int status, bool immediate, bool exit_upon_quit, int id, void* user )
{ {
printf("stat %d immed %d quit %d\n", status, !!immediate, !!exit_upon_quit); //printf("stat %d immed %d quit %d\n", status, !!immediate, !!exit_upon_quit);
return 0; return 0;
} }

View File

@ -36,32 +36,54 @@ public:
NGSPICE(); NGSPICE();
virtual ~NGSPICE(); virtual ~NGSPICE();
///> @copydoc SPICE_SIMULATOR::Init()
void Init() override; void Init() override;
///> @copydoc SPICE_SIMULATOR::LoadNetlist()
bool LoadNetlist( const std::string& aNetlist ) override; bool LoadNetlist( const std::string& aNetlist ) override;
///> @copydoc SPICE_SIMULATOR::Run()
bool Run() override; bool Run() override;
///> @copydoc SPICE_SIMULATOR::Stop()
bool Stop() override; bool Stop() override;
///> @copydoc SPICE_SIMULATOR::IsRunning()
bool IsRunning() override; bool IsRunning() override;
///> @copydoc SPICE_SIMULATOR::Command()
bool Command( const std::string& aCmd ) override; bool Command( const std::string& aCmd ) override;
///> @copydoc SPICE_SIMULATOR::GetXAxis()
std::string GetXAxis( SIM_TYPE aType ) const override; std::string GetXAxis( SIM_TYPE aType ) const override;
///> @copydoc SPICE_SIMULATOR::GetPlot()
std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) override;
///> @copydoc SPICE_SIMULATOR::GetRealPlot()
std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) override;
///> @copydoc SPICE_SIMULATOR::GetImagPlot()
std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) override;
///> @copydoc SPICE_SIMULATOR::GetMagPlot()
std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) override;
///> @copydoc SPICE_SIMULATOR::GetPhasePlot()
std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) override; std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) override;
private: private:
// ngspice library functions
typedef void (*ngSpice_Init)( SendChar*, SendStat*, ControlledExit*, typedef void (*ngSpice_Init)( SendChar*, SendStat*, ControlledExit*,
SendData*, SendInitData*, BGThreadRunning*, void* ); SendData*, SendInitData*, BGThreadRunning*, void* );
typedef int (*ngSpice_Circ)( char** circarray );
typedef int (*ngSpice_Command)( char* command );
typedef pvector_info (*ngGet_Vec_Info)( char* vecname );
typedef char** (*ngSpice_AllPlots)( void );
typedef char** (*ngSpice_AllVecs)( char* plotname );
typedef bool (*ngSpice_Running)( void );
// ngspice library functions ///> Handles to DLL functions
typedef int (*ngSpice_Circ)(char** circarray);
typedef int (*ngSpice_Command)(char* command);
typedef pvector_info (*ngGet_Vec_Info)(char* vecname);
typedef char** (*ngSpice_AllPlots)(void);
typedef char** (*ngSpice_AllVecs)(char* plotname);
typedef bool (*ngSpice_Running)(void);
ngSpice_Init m_ngSpice_Init; ngSpice_Init m_ngSpice_Init;
ngSpice_Circ m_ngSpice_Circ; ngSpice_Circ m_ngSpice_Circ;
ngSpice_Command m_ngSpice_Command; ngSpice_Command m_ngSpice_Command;
@ -72,10 +94,11 @@ private:
wxDynamicLibrary* m_dll; wxDynamicLibrary* m_dll;
// Callback functions
static int cbSendChar( char* what, int id, void* user ); static int cbSendChar( char* what, int id, void* user );
static int cbSendStat( char* what, int id, void* user ); static int cbSendStat( char* what, int id, void* user );
static int cbBGThreadRunning( bool is_running, int id, void* user ); static int cbBGThreadRunning( bool is_running, int id, void* user );
static int cbControlledExit ( int status, bool immediate, bool exit_upon_quit, int id, void *user ); static int cbControlledExit( int status, bool immediate, bool exit_upon_quit, int id, void* user );
void dump(); void dump();
}; };

View File

@ -45,6 +45,7 @@ SIM_PLOT_TYPE operator|( SIM_PLOT_TYPE aFirst, SIM_PLOT_TYPE aSecond )
return (SIM_PLOT_TYPE) res; return (SIM_PLOT_TYPE) res;
} }
class SIM_THREAD_REPORTER : public SPICE_REPORTER class SIM_THREAD_REPORTER : public SPICE_REPORTER
{ {
public: public:
@ -117,11 +118,17 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
Connect( EVT_SIM_FINISHED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimFinished ), NULL, this ); Connect( EVT_SIM_FINISHED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimFinished ), NULL, this );
Connect( EVT_SIM_CURSOR_UPDATE, wxCommandEventHandler( SIM_PLOT_FRAME::onCursorUpdate ), NULL, this ); Connect( EVT_SIM_CURSOR_UPDATE, wxCommandEventHandler( SIM_PLOT_FRAME::onCursorUpdate ), NULL, this );
m_toolSimulate = m_toolBar->AddTool( ID_SIM_RUN, _("Run/Stop Simulation"), KiBitmap( sim_run_xpm ), _("Run Simulation"), wxITEM_NORMAL ); // Toolbar buttons
m_toolAddSignals = m_toolBar->AddTool( ID_SIM_ADD_SIGNALS, _("Add Signals"), KiBitmap( sim_add_signal_xpm ), _("Add signals to plot"), wxITEM_NORMAL ); m_toolSimulate = m_toolBar->AddTool( ID_SIM_RUN, _( "Run/Stop Simulation" ),
m_toolProbe = m_toolBar->AddTool( ID_SIM_PROBE, _("Probe"), KiBitmap( sim_probe_xpm ),_("Probe signals on the schematic"), wxITEM_NORMAL ); KiBitmap( sim_run_xpm ), _( "Run Simulation" ), wxITEM_NORMAL );
m_toolTune = m_toolBar->AddTool( ID_SIM_TUNE, _("Tune"), KiBitmap( sim_tune_xpm ), _("Tune component values"), wxITEM_NORMAL ); m_toolAddSignals = m_toolBar->AddTool( ID_SIM_ADD_SIGNALS, _( "Add Signals" ),
m_toolSettings = m_toolBar->AddTool( wxID_ANY, _("Settings"), KiBitmap( sim_settings_xpm ), _("Simulation settings"), wxITEM_NORMAL ); KiBitmap( sim_add_signal_xpm ), _( "Add signals to plot" ), wxITEM_NORMAL );
m_toolProbe = m_toolBar->AddTool( ID_SIM_PROBE, _( "Probe" ),
KiBitmap( sim_probe_xpm ), _( "Probe signals on the schematic" ), wxITEM_NORMAL );
m_toolTune = m_toolBar->AddTool( ID_SIM_TUNE, _( "Tune" ),
KiBitmap( sim_tune_xpm ), _( "Tune component values" ), wxITEM_NORMAL );
m_toolSettings = m_toolBar->AddTool( wxID_ANY, _( "Settings" ),
KiBitmap( sim_settings_xpm ), _( "Simulation settings" ), wxITEM_NORMAL );
Connect( m_toolSimulate->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimulate ), NULL, this ); Connect( m_toolSimulate->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onSimulate ), NULL, this );
Connect( m_toolAddSignals->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onAddSignal ), NULL, this ); Connect( m_toolAddSignals->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onAddSignal ), NULL, this );
@ -129,6 +136,7 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
Connect( m_toolTune->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onTune ), NULL, this ); Connect( m_toolTune->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onTune ), NULL, this );
Connect( m_toolSettings->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onSettings ), NULL, this ); Connect( m_toolSettings->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( SIM_PLOT_FRAME::onSettings ), NULL, this );
// Bind toolbar buttons event to existing menu event handlers, so they behave the same
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSimulate, this, m_runSimulation->GetId() ); Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSimulate, this, m_runSimulation->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onAddSignal, this, m_addSignals->GetId() ); Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onAddSignal, this, m_addSignals->GetId() );
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onProbe, this, m_probeSignals->GetId() ); Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onProbe, this, m_probeSignals->GetId() );
@ -136,7 +144,7 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSettings, this, m_settings->GetId() ); Bind( wxEVT_COMMAND_MENU_SELECTED, &SIM_PLOT_FRAME::onSettings, this, m_settings->GetId() );
m_toolBar->Realize(); m_toolBar->Realize();
m_plotNotebook->SetPageText(0, _("Welcome!") ); m_plotNotebook->SetPageText( 0, _( "Welcome!" ) );
} }
@ -180,8 +188,6 @@ void SIM_PLOT_FRAME::StartSimulation()
updateTuners(); updateTuners();
applyTuners(); applyTuners();
m_simulator->Run(); m_simulator->Run();
Layout();
} }
@ -746,21 +752,6 @@ void SIM_PLOT_FRAME::menuShowLegendUpdate( wxUpdateUIEvent& event )
event.Check( plot ? plot->IsLegendShown() : false ); event.Check( plot ? plot->IsLegendShown() : false );
} }
#if 0
void SIM_PLOT_FRAME::menuShowCoords( wxCommandEvent& event )
{
SIM_PLOT_PANEL* plot = CurrentPlot();
plot->ShowCoords( !plot->IsCoordsShown() );
}
void SIM_PLOT_FRAME::menuShowCoordsUpdate( wxUpdateUIEvent& event )
{
SIM_PLOT_PANEL* plot = CurrentPlot();
event.Check( plot ? plot->IsCoordsShown() : false );
}
#endif
void SIM_PLOT_FRAME::onPlotClose( wxAuiNotebookEvent& event ) void SIM_PLOT_FRAME::onPlotClose( wxAuiNotebookEvent& event )
{ {

View File

@ -27,7 +27,8 @@
#define __sim_plot_frame__ #define __sim_plot_frame__
/** /**
@file Subclass of SIM_PLOT_FRAME_BASE, which is generated by wxFormBuilder. */ * @file Subclass of SIM_PLOT_FRAME_BASE, which is generated by wxFormBuilder.
*/
#include "sim_plot_frame_base.h" #include "sim_plot_frame_base.h"
#include "sim_types.h" #include "sim_types.h"
@ -49,7 +50,7 @@ class NETLIST_EXPORTER_PSPICE_SIM;
class SIM_PLOT_PANEL; class SIM_PLOT_PANEL;
class TUNER_SLIDER; class TUNER_SLIDER;
/// @todo description ///> Trace descriptor class
class TRACE_DESC class TRACE_DESC
{ {
public: public:
@ -102,191 +103,218 @@ private:
/** Implementing SIM_PLOT_FRAME_BASE */ /** Implementing SIM_PLOT_FRAME_BASE */
class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE
{ {
public: public:
/** Constructor */ /** Constructor */
SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent ); SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent );
~SIM_PLOT_FRAME(); ~SIM_PLOT_FRAME();
void StartSimulation(); void StartSimulation();
void StopSimulation(); void StopSimulation();
bool IsSimulationRunning(); bool IsSimulationRunning();
/** /**
* @brief Creates a new plot panel for a given simulation type and adds it to the main * @brief Creates a new plot panel for a given simulation type and adds it to the main
* notebook. * notebook.
* @param aSimType is requested simulation type. * @param aSimType is requested simulation type.
* @return The new plot panel. * @return The new plot panel.
*/ */
SIM_PLOT_PANEL* NewPlotPanel( SIM_TYPE aSimType ); SIM_PLOT_PANEL* NewPlotPanel( SIM_TYPE aSimType );
void AddVoltagePlot( const wxString& aNetName ); /**
void AddCurrentPlot( const wxString& aDeviceName, const wxString& aParam ); * @brief Adds a voltage plot for a given net name.
* @param aNetName is the net name for which a voltage plot should be created.
*/
void AddVoltagePlot( const wxString& aNetName );
void AddTuner( SCH_COMPONENT* aComponent ); /**
void RemoveTuner( TUNER_SLIDER* aTuner, bool aErase = true ); * @brief Adds a current plot for a particular device.
* @param aDeviceName is the device name (e.g. R1, C1).
* @param aParam is the current type (e.g. I, Ic, Id).
*/
void AddCurrentPlot( const wxString& aDeviceName, const wxString& aParam );
SIM_PLOT_PANEL* CurrentPlot() const; /**
* @brief Adds a tuner for a component.
*/
void AddTuner( SCH_COMPONENT* aComponent );
private: /**
void relayout(); * @brief Removes an existing tuner.
/** * @param aTuner is the tuner to be removed.
* @brief Adds a new plot to the current panel. * @param aErase decides whether the tuner should be also removed from the tuners list.
* @param aName is the device/net name. * Otherwise it is removed only from the SIM_PLOT_FRAME pane.
* @param aType describes the type of plot. */
* @param aParam is the parameter for the device/net (e.g. I, Id, V). void RemoveTuner( TUNER_SLIDER* aTuner, bool aErase = true );
*/
void addPlot( const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam );
/** /**
* @brief Removes a plot with a specific title. * @brief Returns the currently opened plot panel (or NULL if there is none).
* @param aPlotName is the full plot title (e.g. I(Net-C1-Pad1)). */
* @param aErase decides if plot should be removed from corresponding TRACE_MAP (see m_plots). SIM_PLOT_PANEL* CurrentPlot() const;
*/
void removePlot( const wxString& aPlotName, bool aErase = true );
void updateNetlistExporter(); private:
/**
* @brief Adds a new plot to the current panel.
* @param aName is the device/net name.
* @param aType describes the type of plot.
* @param aParam is the parameter for the device/net (e.g. I, Id, V).
*/
void addPlot( const wxString& aName, SIM_PLOT_TYPE aType, const wxString& aParam );
/** /**
* @brief Updates plot in a particular SIM_PLOT_PANEL. If the panel does not contain * @brief Removes a plot with a specific title.
* the plot, it will be added. * @param aPlotName is the full plot title (e.g. I(Net-C1-Pad1)).
* @param aDescriptor contains the plot description. * @param aErase decides if plot should be removed from corresponding TRACE_MAP (see m_plots).
* @param aPanel is the panel that should receive the update. */
* @return True if a plot was successfully added/updated. void removePlot( const wxString& aPlotName, bool aErase = true );
*/
bool updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL* aPanel );
/** /**
* @brief Updates the list of currently plotted signals. * @brief Reloads the current schematic for the netlist exporter.
*/ */
void updateSignalList(); void updateNetlistExporter();
/** /**
* @brief Updates the cursor values list. * @brief Updates plot in a particular SIM_PLOT_PANEL. If the panel does not contain
*/ * the plot, it will be added.
void updateCursors(); * @param aDescriptor contains the plot description.
* @param aPanel is the panel that should receive the update.
* @return True if a plot was successfully added/updated.
*/
bool updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL* aPanel );
/** /**
* @brief Filters out tuners for components that do not exist anymore. * @brief Updates the list of currently plotted signals.
* Decisions are based on the current NETLIST_EXPORTER data. */
*/ void updateSignalList();
void updateTuners();
/** /**
* @brief Applies component values specified using tunder sliders to the current netlist. * @brief Updates the cursor values list.
*/ */
void applyTuners(); void updateCursors();
/** /**
* @brief Loads plot settings from a file. * @brief Filters out tuners for components that do not exist anymore.
* @param aPath is the file name. * Decisions are based on the current NETLIST_EXPORTER data.
* @return True if successful. */
*/ void updateTuners();
bool loadWorkbook( const wxString& aPath );
/** /**
* @brief Saves plot settings to a file. * @brief Applies component values specified using tunder sliders to the current netlist.
* @param aPath is the file name. */
* @return True if successful. void applyTuners();
*/
bool saveWorkbook( const wxString& aPath );
SIM_PLOT_TYPE GetXAxisType( SIM_TYPE aType ) const; /**
* @brief Loads plot settings from a file.
* @param aPath is the file name.
* @return True if successful.
*/
bool loadWorkbook( const wxString& aPath );
// Menu handlers /**
void menuNewPlot( wxCommandEvent& aEvent ) override; * @brief Saves plot settings to a file.
void menuOpenWorkbook( wxCommandEvent& event ) override; * @param aPath is the file name.
void menuSaveWorkbook( wxCommandEvent& event ) override; * @return True if successful.
*/
bool saveWorkbook( const wxString& aPath );
void menuExit( wxCommandEvent& event ) override /**
{ * @brief Returns X axis for a given simulation type.
Close(); */
} SIM_PLOT_TYPE GetXAxisType( SIM_TYPE aType ) const;
void menuSaveImage( wxCommandEvent& event ) override; // Menu handlers
void menuSaveCsv( wxCommandEvent& event ) override; void menuNewPlot( wxCommandEvent& aEvent ) override;
void menuZoomIn( wxCommandEvent& event ) override; void menuOpenWorkbook( wxCommandEvent& event ) override;
void menuZoomOut( wxCommandEvent& event ) override; void menuSaveWorkbook( wxCommandEvent& event ) override;
void menuZoomFit( wxCommandEvent& event ) override;
void menuShowGrid( wxCommandEvent& event ) override;
void menuShowGridUpdate( wxUpdateUIEvent& event ) override;
void menuShowLegend( wxCommandEvent& event ) override;
void menuShowLegendUpdate( wxUpdateUIEvent& event ) override;
//void menuShowCoords( wxCommandEvent& event ) override;
//void menuShowCoordsUpdate( wxUpdateUIEvent& event ) override;
// Event handlers void menuExit( wxCommandEvent& event ) override
void onPlotChanged( wxAuiNotebookEvent& event ) override; {
void onPlotClose( wxAuiNotebookEvent& event ) override; Close();
}
void onSignalDblClick( wxCommandEvent& event ) override; void menuSaveImage( wxCommandEvent& event ) override;
void onSignalRClick( wxMouseEvent& event ) override; void menuSaveCsv( wxCommandEvent& event ) override;
void menuZoomIn( wxCommandEvent& event ) override;
void menuZoomOut( wxCommandEvent& event ) override;
void menuZoomFit( wxCommandEvent& event ) override;
void menuShowGrid( wxCommandEvent& event ) override;
void menuShowGridUpdate( wxUpdateUIEvent& event ) override;
void menuShowLegend( wxCommandEvent& event ) override;
void menuShowLegendUpdate( wxUpdateUIEvent& event ) override;
void onSimulate( wxCommandEvent& event ); // Event handlers
void onSettings( wxCommandEvent& event ); void onPlotChanged( wxAuiNotebookEvent& event ) override;
void onAddSignal( wxCommandEvent& event ); void onPlotClose( wxAuiNotebookEvent& event ) override;
void onProbe( wxCommandEvent& event );
void onTune( wxCommandEvent& event );
void onClose( wxCloseEvent& aEvent ); void onSignalDblClick( wxCommandEvent& event ) override;
void onSignalRClick( wxMouseEvent& event ) override;
void onCursorUpdate( wxCommandEvent& aEvent ); void onSimulate( wxCommandEvent& event );
void onSimUpdate( wxCommandEvent& aEvent ); void onSettings( wxCommandEvent& event );
void onSimReport( wxCommandEvent& aEvent ); void onAddSignal( wxCommandEvent& event );
void onSimStarted( wxCommandEvent& aEvent ); void onProbe( wxCommandEvent& event );
void onSimFinished( wxCommandEvent& aEvent ); void onTune( wxCommandEvent& event );
wxToolBarToolBase* m_toolSimulate; void onClose( wxCloseEvent& aEvent );
wxToolBarToolBase* m_toolAddSignals;
wxToolBarToolBase* m_toolProbe;
wxToolBarToolBase* m_toolTune;
wxToolBarToolBase* m_toolSettings;
SCH_EDIT_FRAME* m_schematicFrame; void onCursorUpdate( wxCommandEvent& aEvent );
std::unique_ptr<NETLIST_EXPORTER_PSPICE_SIM> m_exporter; void onSimUpdate( wxCommandEvent& aEvent );
std::unique_ptr<SPICE_SIMULATOR> m_simulator; void onSimReport( wxCommandEvent& aEvent );
void onSimStarted( wxCommandEvent& aEvent );
void onSimFinished( wxCommandEvent& aEvent );
typedef std::map<wxString, TRACE_DESC> TRACE_MAP; // Toolbar buttons
wxToolBarToolBase* m_toolSimulate;
wxToolBarToolBase* m_toolAddSignals;
wxToolBarToolBase* m_toolProbe;
wxToolBarToolBase* m_toolTune;
wxToolBarToolBase* m_toolSettings;
struct PLOT_INFO SCH_EDIT_FRAME* m_schematicFrame;
{ std::unique_ptr<NETLIST_EXPORTER_PSPICE_SIM> m_exporter;
///> Map of the traces displayed on the plot std::unique_ptr<SPICE_SIMULATOR> m_simulator;
TRACE_MAP m_traces;
///> Spice directive used to execute the simulation typedef std::map<wxString, TRACE_DESC> TRACE_MAP;
wxString m_simCommand;
};
///> Map of plot panels and associated data struct PLOT_INFO
std::map<SIM_PLOT_PANEL*, PLOT_INFO> m_plots; {
///> Map of the traces displayed on the plot
TRACE_MAP m_traces;
///> List of currently displayed tuners ///> Spice directive used to execute the simulation
std::list<TUNER_SLIDER*> m_tuners; wxString m_simCommand;
};
// Trick to preserve settings between runs ///> Map of plot panels and associated data
DIALOG_SIM_SETTINGS m_settingsDlg; std::map<SIM_PLOT_PANEL*, PLOT_INFO> m_plots;
// Right click context menu for signals in the listbox ///> List of currently displayed tuners
class SIGNAL_CONTEXT_MENU : public wxMenu std::list<TUNER_SLIDER*> m_tuners;
{
public:
SIGNAL_CONTEXT_MENU( const wxString& aSignal, SIM_PLOT_FRAME* aPlotFrame );
private: // Trick to preserve settings between runs
void onMenuEvent( wxMenuEvent& aEvent ); DIALOG_SIM_SETTINGS m_settingsDlg;
const wxString& m_signal; // Right click context menu for signals in the listbox
SIM_PLOT_FRAME* m_plotFrame; class SIGNAL_CONTEXT_MENU : public wxMenu
{
public:
SIGNAL_CONTEXT_MENU( const wxString& aSignal, SIM_PLOT_FRAME* aPlotFrame );
enum SIGNAL_CONTEXT_MENU_EVENTS private:
{ void onMenuEvent( wxMenuEvent& aEvent );
HIDE_SIGNAL,
SHOW_CURSOR,
HIDE_CURSOR
};
};
///> Panel that was used as the most recent one for simulations const wxString& m_signal;
SIM_PLOT_PANEL* m_lastSimPlot; SIM_PLOT_FRAME* m_plotFrame;
enum SIGNAL_CONTEXT_MENU_EVENTS
{
HIDE_SIGNAL,
SHOW_CURSOR,
HIDE_CURSOR
};
};
///> Panel that was used as the most recent one for simulations
SIM_PLOT_PANEL* m_lastSimPlot;
}; };
// Commands // Commands

View File

@ -28,80 +28,88 @@
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
static wxString formatFloat (double x, int nDigits) static wxString formatFloat( double x, int nDigits )
{ {
wxString rv, fmt; wxString rv, fmt;
if(nDigits) if( nDigits )
{ {
fmt = wxT("%.0Nf"); fmt = wxT( "%.0Nf" );
fmt[3] = '0' + nDigits; fmt[3] = '0' + nDigits;
} else { }
fmt = wxT("%.0f"); else
{
fmt = wxT( "%.0f" );
} }
rv.Printf(fmt, x); rv.Printf( fmt, x );
return rv; return rv;
} }
static void getSISuffix ( double x, const wxString& unit, int& power, wxString& suffix )
static void getSISuffix( double x, const wxString& unit, int& power, wxString& suffix )
{ {
const int n_powers = 11; const int n_powers = 11;
const struct {
const struct
{
double exponent; double exponent;
char suffix; char suffix;
} powers[] = { } powers[] =
{-18,'a'}, {
{-15,'f'}, { -18, 'a' },
{-12,'p'}, { -15, 'f' },
{-9,'n'}, { -12, 'p' },
{-6,'u'}, { -9, 'n' },
{-3,'m'}, { -6, 'u' },
{0, 0}, { -3, 'm' },
{3, 'k'}, { 0, 0 },
{6, 'M'}, { 3, 'k' },
{9, 'G'}, { 6, 'M' },
{12, 'T'}, { 9, 'G' },
{15, 'P'} { 12, 'T' },
{ 14, 'P' }
}; };
power = 0; power = 0;
suffix = unit; suffix = unit;
if (x == 0.0) if( x == 0.0 )
return; return;
for ( int i = 0; i <n_powers - 1;i++) for( int i = 0; i < n_powers - 1; i++ )
{ {
double r_cur = pow(10, powers[i].exponent); double r_cur = pow( 10, powers[i].exponent );
if( fabs(x) >= r_cur && fabs(x) < r_cur * 1000.0 ) if( fabs( x ) >= r_cur && fabs( x ) < r_cur * 1000.0 )
{ {
power = powers[i].exponent; power = powers[i].exponent;
if ( powers[i].suffix )
suffix = wxString(powers[i].suffix) + unit; if( powers[i].suffix )
suffix = wxString( powers[i].suffix ) + unit;
else else
suffix = unit; suffix = unit;
return; return;
} }
} }
} }
static int countDecimalDigits ( double x, int maxDigits )
static int countDecimalDigits( double x, int maxDigits )
{ {
int64_t k = (int) ( ( x - floor(x)) * pow ( 10.0, (double) maxDigits )); int64_t k = (int)( ( x - floor( x ) ) * pow( 10.0, (double) maxDigits ) );
int n = 0; int n = 0;
while(k && ((k % 10LL) == 0LL || (k % 10LL) == 9LL)) while( k && ( ( k % 10LL ) == 0LL || ( k % 10LL ) == 9LL ) )
{ {
k /= 10LL; k /= 10LL;
} }
n = 0; n = 0;
while (k != 0LL) while( k != 0LL )
{ {
n++; n++;
k /= 10LL; k /= 10LL;
@ -111,64 +119,66 @@ static int countDecimalDigits ( double x, int maxDigits )
} }
static void formatSILabels( mpScaleBase *scale, const wxString& aUnit, int nDigits ) static void formatSILabels( mpScaleBase* scale, const wxString& aUnit, int nDigits )
{ {
double maxVis = scale->AbsVisibleMaxValue(); double maxVis = scale->AbsVisibleMaxValue();
wxString suffix; wxString suffix;
int power, digits = 0; int power, digits = 0;
getSISuffix( maxVis, aUnit, power, suffix); getSISuffix( maxVis, aUnit, power, suffix );
double sf = pow(10.0, power); double sf = pow( 10.0, power );
for ( auto &l : scale->TickLabels() ) for( auto &l : scale->TickLabels() )
{ {
int k = countDecimalDigits( l.pos / sf, nDigits ); int k = countDecimalDigits( l.pos / sf, nDigits );
digits = std::max(digits, k); digits = std::max( digits, k );
} }
for ( auto &l : scale->TickLabels() ) for( auto &l : scale->TickLabels() )
{ {
l.label = formatFloat ( l.pos / sf, digits ) + suffix; l.label = formatFloat ( l.pos / sf, digits ) + suffix;
l.visible = true; l.visible = true;
} }
} }
class FREQUENCY_LOG_SCALE : public mpScaleXLog class FREQUENCY_LOG_SCALE : public mpScaleXLog
{ {
public: public:
FREQUENCY_LOG_SCALE(wxString name, int flags) : FREQUENCY_LOG_SCALE( wxString name, int flags ) :
mpScaleXLog( name, flags ) {}; mpScaleXLog( name, flags ) {};
void formatLabels() void formatLabels()
{ {
const wxString unit = wxT("Hz"); const wxString unit = wxT( "Hz" );
wxString suffix; wxString suffix;
int power; int power;
for ( auto &l : TickLabels() ) for( auto &l : TickLabels() )
{ {
getSISuffix( l.pos, unit, power, suffix); getSISuffix( l.pos, unit, power, suffix );
double sf = pow(10.0, power); double sf = pow( 10.0, power );
int k = countDecimalDigits( l.pos / sf, 3 ); int k = countDecimalDigits( l.pos / sf, 3 );
l.label = formatFloat ( l.pos / sf, k ) + suffix; l.label = formatFloat( l.pos / sf, k ) + suffix;
l.visible = true; l.visible = true;
} }
} }
}; };
class FREQUENCY_LIN_SCALE : public mpScaleX class FREQUENCY_LIN_SCALE : public mpScaleX
{ {
public: public:
FREQUENCY_LIN_SCALE(wxString name, int flags) : FREQUENCY_LIN_SCALE( wxString name, int flags ) :
mpScaleX( name, flags, false , 0 ) {}; mpScaleX( name, flags, false , 0 ) {};
void formatLabels() void formatLabels()
{ {
formatSILabels( this, wxT("Hz"), 3 ); formatSILabels( this, wxT( "Hz" ), 3 );
} }
}; };
@ -176,74 +186,78 @@ public:
class TIME_SCALE : public mpScaleX class TIME_SCALE : public mpScaleX
{ {
public: public:
TIME_SCALE(wxString name, int flags) : TIME_SCALE( wxString name, int flags ) :
mpScaleX ( name, flags, false, 0) {}; mpScaleX( name, flags, false, 0 ) {};
void formatLabels() void formatLabels()
{ {
formatSILabels( this, wxT("s"), 3 ); formatSILabels( this, wxT( "s" ), 3 );
} }
}; };
class VOLTAGE_SCALE_X : public mpScaleX class VOLTAGE_SCALE_X : public mpScaleX
{ {
public: public:
VOLTAGE_SCALE_X(wxString name, int flags) : VOLTAGE_SCALE_X( wxString name, int flags ) :
mpScaleX ( name, flags, false, 0 ) {}; mpScaleX( name, flags, false, 0 ) {};
void formatLabels() void formatLabels()
{ {
formatSILabels( this, wxT("V"), 3 ); formatSILabels( this, wxT( "V" ), 3 );
} }
}; };
class GAIN_SCALE : public mpScaleY class GAIN_SCALE : public mpScaleY
{ {
public: public:
GAIN_SCALE( wxString name, int flags ) : GAIN_SCALE( wxString name, int flags ) :
mpScaleY ( name, flags, false) {}; mpScaleY( name, flags, false ) {};
void formatLabels() void formatLabels()
{ {
formatSILabels( this, wxT("dB"), 3 ); formatSILabels( this, wxT( "dB" ), 3 );
} }
}; };
class PHASE_SCALE : public mpScaleY class PHASE_SCALE : public mpScaleY
{ {
public: public:
PHASE_SCALE(wxString name, int flags) : PHASE_SCALE( wxString name, int flags ) :
mpScaleY ( name, flags, false ) {}; mpScaleY( name, flags, false ) {};
void formatLabels() void formatLabels()
{ {
formatSILabels( this, wxT("\u00B0"), 3 ); formatSILabels( this, wxT( "\u00B0" ), 3 ); // degree sign
} }
}; };
class VOLTAGE_SCALE_Y : public mpScaleY class VOLTAGE_SCALE_Y : public mpScaleY
{ {
public: public:
VOLTAGE_SCALE_Y(wxString name, int flags) : VOLTAGE_SCALE_Y( wxString name, int flags ) :
mpScaleY ( name, flags, false ) {}; mpScaleY( name, flags, false ) {};
void formatLabels() void formatLabels()
{ {
formatSILabels( this, wxT("V"), 3 ); formatSILabels( this, wxT( "V" ), 3 );
} }
}; };
class CURRENT_SCALE : public mpScaleY class CURRENT_SCALE : public mpScaleY
{ {
public: public:
CURRENT_SCALE(wxString name, int flags ) : CURRENT_SCALE( wxString name, int flags ) :
mpScaleY ( name, flags, false ) {}; mpScaleY( name, flags, false ) {};
void formatLabels() void formatLabels()
{ {
formatSILabels( this, wxT("A"), 3 ); formatSILabels( this, wxT( "A" ), 3 );
} }
}; };
@ -366,7 +380,7 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( SIM_TYPE aType, wxWindow* parent, wxWindowID id,
m_axis_x = new FREQUENCY_LOG_SCALE( wxT( "Frequency" ), mpALIGN_BOTTOM ); m_axis_x = new FREQUENCY_LOG_SCALE( wxT( "Frequency" ), mpALIGN_BOTTOM );
m_axis_y1 = new GAIN_SCALE( wxT( "Gain" ), mpALIGN_LEFT ); m_axis_y1 = new GAIN_SCALE( wxT( "Gain" ), mpALIGN_LEFT );
m_axis_y2 = new PHASE_SCALE( wxT( "Phase" ), mpALIGN_RIGHT ); m_axis_y2 = new PHASE_SCALE( wxT( "Phase" ), mpALIGN_RIGHT );
m_axis_y2->SetMasterScale(m_axis_y1); m_axis_y2->SetMasterScale( m_axis_y1 );
break; break;
case ST_DC: case ST_DC:
@ -383,7 +397,7 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( SIM_TYPE aType, wxWindow* parent, wxWindowID id,
m_axis_x = new TIME_SCALE( wxT( "Time" ), mpALIGN_BOTTOM ); m_axis_x = new TIME_SCALE( wxT( "Time" ), mpALIGN_BOTTOM );
m_axis_y1 = new VOLTAGE_SCALE_Y( wxT( "Voltage" ), mpALIGN_LEFT ); m_axis_y1 = new VOLTAGE_SCALE_Y( wxT( "Voltage" ), mpALIGN_LEFT );
m_axis_y2 = new CURRENT_SCALE( wxT( "Current" ), mpALIGN_RIGHT ); m_axis_y2 = new CURRENT_SCALE( wxT( "Current" ), mpALIGN_RIGHT );
m_axis_y2->SetMasterScale(m_axis_y1); m_axis_y2->SetMasterScale( m_axis_y1 );
break; break;
default: default:
@ -416,9 +430,9 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( SIM_TYPE aType, wxWindow* parent, wxWindowID id,
m_legend = new mpInfoLegend( wxRect( 0, 40, 200, 40 ), wxTRANSPARENT_BRUSH ); m_legend = new mpInfoLegend( wxRect( 0, 40, 200, 40 ), wxTRANSPARENT_BRUSH );
AddLayer( m_legend ); AddLayer( m_legend );
m_topLevel.push_back( m_legend ); m_topLevel.push_back( m_legend );
SetColourTheme(*wxBLACK, *wxWHITE, grey); SetColourTheme( *wxBLACK, *wxWHITE, grey );
EnableDoubleBuffer(true); EnableDoubleBuffer( true );
UpdateAll(); UpdateAll();
} }
@ -455,20 +469,20 @@ bool SIM_PLOT_PANEL::AddTrace( const wxString& aName, int aPoints,
if( addedNewEntry ) if( addedNewEntry )
{ {
if ( m_type == ST_TRANSIENT ) if( m_type == ST_TRANSIENT )
{ {
bool hasVoltageTraces = false; bool hasVoltageTraces = false;
for( auto t : m_traces ) for( auto t : m_traces )
{ {
if ( ! (t.second->GetFlags() & SPT_CURRENT ) ) if( !( t.second->GetFlags() & SPT_CURRENT ) )
{ {
hasVoltageTraces = true; hasVoltageTraces = true;
break; break;
} }
} }
if ( !hasVoltageTraces ) if( !hasVoltageTraces )
m_axis_y2->SetMasterScale( nullptr ); m_axis_y2->SetMasterScale( nullptr );
else else
m_axis_y2->SetMasterScale( m_axis_y1 ); m_axis_y2->SetMasterScale( m_axis_y1 );
@ -499,12 +513,12 @@ bool SIM_PLOT_PANEL::AddTrace( const wxString& aName, int aPoints,
{ {
if( aFlags & SPT_AC_PHASE ) if( aFlags & SPT_AC_PHASE )
{ {
for(int i = 0; i < aPoints; i++ ) for( int i = 0; i < aPoints; i++ )
tmp[i] = tmp[i] * 180.0 / M_PI; // convert to degrees tmp[i] = tmp[i] * 180.0 / M_PI; // convert to degrees
} }
else else
{ {
for(int i = 0; i < aPoints; i++ ) for( int i = 0; i < aPoints; i++ )
tmp[i] = 20 * log( tmp[i] ) / log( 10.0 ); // convert to dB tmp[i] = 20 * log( tmp[i] ) / log( 10.0 ); // convert to dB
} }
} }
@ -553,6 +567,7 @@ void SIM_PLOT_PANEL::DeleteAllTraces()
DeleteTrace( t.first ); DeleteTrace( t.first );
} }
m_colorIdx = 0;
m_traces.clear(); m_traces.clear();
} }

View File

@ -32,6 +32,7 @@
class TRACE; class TRACE;
///> Cursor attached to a trace to follow its values:
class CURSOR : public mpInfoLayer class CURSOR : public mpInfoLayer
{ {
public: public:
@ -86,14 +87,18 @@ class TRACE : public mpFXYVector
{ {
public: public:
TRACE( const wxString& aName ) : TRACE( const wxString& aName ) :
mpFXYVector( aName ), m_cursor( nullptr ), m_flags(0) mpFXYVector( aName ), m_cursor( nullptr ), m_flags( 0 )
{ {
SetContinuity( true ); SetContinuity( true );
SetDrawOutsideMargins( false ); SetDrawOutsideMargins( false );
ShowName( false ); ShowName( false );
}
}
/**
* @brief Assigns new data set for the trace. aX and aY need to have the same length.
* @param aX are the X axis values.
* @param aY are the Y axis values.
*/
void SetData( const std::vector<double>& aX, const std::vector<double>& aY ) override void SetData( const std::vector<double>& aX, const std::vector<double>& aY ) override
{ {
if( m_cursor ) if( m_cursor )
@ -127,7 +132,7 @@ public:
return m_cursor; return m_cursor;
} }
void SetFlags ( int aFlags ) void SetFlags( int aFlags )
{ {
m_flags = aFlags; m_flags = aFlags;
} }
@ -222,26 +227,20 @@ public:
return m_legend->IsVisible(); return m_legend->IsVisible();
} }
void ShowCoords( bool aEnable ) ///> Returns true if the trace has cursor shown.
{
m_coords->SetVisible( aEnable );
UpdateAll();
}
bool IsCoordsShown() const
{
return m_coords->IsVisible();
}
bool HasCursorEnabled( const wxString& aName ) const; bool HasCursorEnabled( const wxString& aName ) const;
///> Toggles cursor for a particular trace.
void EnableCursor( const wxString& aName, bool aEnable ); void EnableCursor( const wxString& aName, bool aEnable );
///> Resets scale ranges to fit the current traces
void ResetScales(); void ResetScales();
private: private:
///> Returns a new color from the palette
wxColour generateColor(); wxColour generateColor();
// Color index to get a new color from the palette
unsigned int m_colorIdx; unsigned int m_colorIdx;
// Traces to be plotted // Traces to be plotted
@ -251,7 +250,6 @@ private:
mpScaleY* m_axis_y1; mpScaleY* m_axis_y1;
mpScaleY* m_axis_y2; mpScaleY* m_axis_y2;
mpInfoLegend* m_legend; mpInfoLegend* m_legend;
mpInfoCoords* m_coords;
std::vector<mpLayer*> m_topLevel; std::vector<mpLayer*> m_topLevel;

View File

@ -39,6 +39,7 @@ enum SIM_PLOT_TYPE {
SPT_AC_PHASE = 0x04, SPT_AC_PHASE = 0x04,
SPT_AC_MAG = 0x08, SPT_AC_MAG = 0x08,
// X axis
SPT_TIME = 0x10, SPT_TIME = 0x10,
SPT_LIN_FREQUENCY = 0x20, SPT_LIN_FREQUENCY = 0x20,
SPT_LOG_FREQUENCY = 0x20, SPT_LOG_FREQUENCY = 0x20,

View File

@ -1,11 +0,0 @@
#include <schframe.h>
void SCH_EDIT_FRAME::OnSimulationRun( wxCommandEvent& event )
{}
void SCH_EDIT_FRAME::OnSimulationStop( wxCommandEvent& event )
{}
void SCH_EDIT_FRAME::OnSimulationAddProbe( wxCommandEvent& event )
{}

View File

@ -41,31 +41,91 @@ public:
SPICE_SIMULATOR() : m_reporter( NULL ) {} SPICE_SIMULATOR() : m_reporter( NULL ) {}
virtual ~SPICE_SIMULATOR() {} virtual ~SPICE_SIMULATOR() {}
///> Creates a simulator instance of particular type (currently only ngspice is handled)
static SPICE_SIMULATOR* CreateInstance( const std::string& aName ); static SPICE_SIMULATOR* CreateInstance( const std::string& aName );
///> Intializes the simulator
virtual void Init() = 0; virtual void Init() = 0;
/*
* @brief Loads a netlist for the simulation.
* @return True in case of success, false otherwise.
*/
virtual bool LoadNetlist( const std::string& aNetlist ) = 0; virtual bool LoadNetlist( const std::string& aNetlist ) = 0;
/**
* @brief Executes the simulation with currently loaded netlist.
* @return True in case of success, false otherwise.
*/
virtual bool Run() = 0; virtual bool Run() = 0;
/**
* @brief Halts the simulation.
* @return True in case of success, false otherwise.
*/
virtual bool Stop() = 0; virtual bool Stop() = 0;
/**
* @brief Checks if simulation is running at the moment.
* @return True if simulation is currently executed.
*/
virtual bool IsRunning() = 0; virtual bool IsRunning() = 0;
/**
* @brief Executes a Spice command as if it was typed into console.
* @param aCmd is the command to be issued.
*/
virtual bool Command( const std::string& aCmd ) = 0; virtual bool Command( const std::string& aCmd ) = 0;
///> Returns X axis name for a given simulation type ///> Returns X axis name for a given simulation type
virtual std::string GetXAxis( SIM_TYPE aType ) const = 0; virtual std::string GetXAxis( SIM_TYPE aType ) const = 0;
///> Sets a SPICE_REPORTER object to receive the simulation log.
virtual void SetReporter( SPICE_REPORTER* aReporter ) virtual void SetReporter( SPICE_REPORTER* aReporter )
{ {
m_reporter = aReporter; m_reporter = aReporter;
} }
/**
* @brief Returns a requested vector with complex values. If the vector is real, then
* the imaginary part is set to 0 in all values.
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
* @return Requested vector. It might be empty if there is no vector with requested name.
*/
virtual std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) = 0; virtual std::vector<COMPLEX> GetPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
/**
* @brief Returns a requested vector with real values. If the vector is complex, then
* the real part is returned.
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
* @return Requested vector. It might be empty if there is no vector with requested name.
*/
virtual std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) = 0; virtual std::vector<double> GetRealPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
/**
* @brief Returns a requested vector with imaginary values. If the vector is complex, then
* the imaginary part is returned. If the vector is reql, then only zeroes are returned.
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
* @return Requested vector. It might be empty if there is no vector with requested name.
*/
virtual std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) = 0; virtual std::vector<double> GetImagPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
/**
* @brief Returns a requested vector with magnitude values.
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
* @return Requested vector. It might be empty if there is no vector with requested name.
*/
virtual std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) = 0; virtual std::vector<double> GetMagPlot( const std::string& aName, int aMaxLen = -1 ) = 0;
/**
* @brief Returns a requested vector with phase values.
* @param aName is the vector named in Spice convention (e.g. V(3), I(R1)).
* @return Requested vector. It might be empty if there is no vector with requested name.
*/
virtual std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) = 0; virtual std::vector<double> GetPhasePlot( const std::string& aName, int aMaxLen = -1 ) = 0;
protected: protected:
///> Reporter object to receive simulation log
SPICE_REPORTER* m_reporter; SPICE_REPORTER* m_reporter;
}; };

View File

@ -221,13 +221,13 @@ SPICE_VALUE SPICE_VALUE::operator/( const SPICE_VALUE& aOther ) const
void SPICE_VALUE::stripZeros( wxString& aString ) void SPICE_VALUE::stripZeros( wxString& aString )
{ {
if ( aString.Find(',') >= 0 || aString.Find('.') >= 0 ) if ( aString.Find( ',' ) >= 0 || aString.Find( '.' ) >= 0 )
{ {
while( aString.EndsWith( '0' ) ) while( aString.EndsWith( '0' ) )
aString.RemoveLast(); aString.RemoveLast();
if( aString.EndsWith( '.' ) || aString.EndsWith( ',' ) ) if( aString.EndsWith( '.' ) || aString.EndsWith( ',' ) )
aString.RemoveLast(); aString.RemoveLast();
} }
} }

View File

@ -51,6 +51,7 @@ public:
{ {
} }
///> Parses the string to create a Spice value (e.g. 100n)
SPICE_VALUE( const wxString& aString ); SPICE_VALUE( const wxString& aString );
SPICE_VALUE( int aInt, UNIT_PREFIX aPrefix = PFX_NONE ) SPICE_VALUE( int aInt, UNIT_PREFIX aPrefix = PFX_NONE )
@ -65,19 +66,35 @@ public:
Normalize(); Normalize();
} }
/**
* @brief Normalizes the value. The unit prefix is picked so the base is (0.001 <= base < 1000).
*/
void Normalize(); void Normalize();
double ToDouble() const; double ToDouble() const;
/**
* @brief Returns string value as when converting double to string (e.g. 123456.789).
*/
wxString ToString() const; wxString ToString() const;
/**
* @brief Returns string value in Spice format (e.g. 123.3456789k).
*/
wxString ToSpiceString() const; wxString ToSpiceString() const;
/**
* @brief Returns either a normal string or Spice format string, depending on the original
* value format.
*/
wxString ToOrigString() const wxString ToOrigString() const
{ {
return m_spiceStr ? ToSpiceString() : ToString(); return m_spiceStr ? ToSpiceString() : ToString();
} }
/**
* Returns true if the object was initiated with a Spice formatted string value.
*/
bool IsSpiceString() const bool IsSpiceString() const
{ {
return m_spiceStr; return m_spiceStr;
@ -120,6 +137,7 @@ private:
///> Was the value defined using the Spice notation? ///> Was the value defined using the Spice notation?
bool m_spiceStr; bool m_spiceStr;
///> Removes redundant zeros from the end of a string.
static void stripZeros( wxString& aString ); static void stripZeros( wxString& aString );
}; };
@ -141,6 +159,7 @@ public:
bool Validate( wxWindow* aParent ) override; bool Validate( wxWindow* aParent ) override;
private: private:
///> Is it valid to get an empty value?
bool m_emptyAllowed; bool m_emptyAllowed;
}; };