SPICE_SIMULATOR: Code formatting & clean up

This commit is contained in:
Maciej Suminski 2016-08-11 14:41:07 +02:00
parent 9748b65a6d
commit 9e2485ea97
8 changed files with 349 additions and 280 deletions

View File

@ -180,6 +180,7 @@ set( EESCHEMA_SRCS
sim/sim_plot_frame_base.cpp sim/sim_plot_frame_base.cpp
sim/sim_plot_frame.cpp sim/sim_plot_frame.cpp
sim/sim_plot_panel.cpp sim/sim_plot_panel.cpp
sim/spice_simulator.cpp
sim/ngspice.cpp sim/ngspice.cpp
netlist_exporters/netlist_exporter.cpp netlist_exporters/netlist_exporter.cpp

View File

@ -1,150 +1,99 @@
#include "sharedspice.h" /*
#include <cstdio> * This program source code file is part of KiCad, a free EDA CAD application.
#include <sstream> *
* Copyright (C) 2016 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "ngspice.h"
#include <wx/dynlib.h> #include <wx/dynlib.h>
#include <string>
#include <vector>
#include "spice_simulator.h"
#include <reporter.h> #include <reporter.h>
#include <sstream>
// TODO cmake modules to add include directory for ngspice
using namespace std; using namespace std;
class NGSPICE : public SPICE_SIMULATOR {
public:
NGSPICE();
virtual ~NGSPICE();
void Init();
bool LoadNetlist(const string& netlist);
bool Command(const string& cmd);
string GetConsole() const;
const vector<double> GetPlot( std::string name, int max_len = -1);
void dump();
private:
typedef void (*ngSpice_Init)(SendChar*, SendStat*, ControlledExit*,
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_AllVecs)(char* plotname);
typedef char** (*ngSpice_AllPlots)(void);
ngSpice_Init m_ngSpice_Init;
ngSpice_Circ m_ngSpice_Circ;
ngSpice_Command m_ngSpice_Command;
ngGet_Vec_Info m_ngGet_Vec_Info;
ngSpice_AllPlots m_ngSpice_AllPlots;
ngSpice_AllVecs m_ngSpice_AllVecs;
wxDynamicLibrary *m_dll;
static int cbSendChar( char* what, int id, void* user)
{
NGSPICE *sim = reinterpret_cast<NGSPICE*>(user);
printf("sim %p cr %p\n",sim, sim->m_consoleReporter );
if(sim->m_consoleReporter)
sim->m_consoleReporter->Report(what);
return 0;
}
static int cbSendStat( char* what, int id, void* user)
{
/* NGSPICE *sim = reinterpret_cast<NGSPICE*>(user);
if(sim->m_consoleReporter)
sim->m_consoleReporter->Report(what);*/
return 0;
}
};
NGSPICE::NGSPICE() NGSPICE::NGSPICE()
{ {
m_dll = new wxDynamicLibrary("/home/twl/projects_sw/ngspice-26/src/.libs/libngspice.so.0.0.0"); //, wxDL_LAZY); m_dll = new wxDynamicLibrary( "libngspice.so" );
printf("DLL at %p\n", m_dll);
assert( m_dll ); assert( m_dll );
// Obtain function pointers
m_ngSpice_Init = (ngSpice_Init) m_dll->GetSymbol( "ngSpice_Init" ); m_ngSpice_Init = (ngSpice_Init) m_dll->GetSymbol( "ngSpice_Init" );
printf("Init @ %p\n", m_ngSpice_Init);
m_ngSpice_Circ = (ngSpice_Circ) m_dll->GetSymbol( "ngSpice_Circ" ); m_ngSpice_Circ = (ngSpice_Circ) m_dll->GetSymbol( "ngSpice_Circ" );
m_ngSpice_Command = (ngSpice_Command) m_dll->GetSymbol( "ngSpice_Command" ); m_ngSpice_Command = (ngSpice_Command) m_dll->GetSymbol( "ngSpice_Command" );
m_ngGet_Vec_Info = (ngGet_Vec_Info) m_dll->GetSymbol( "ngGet_Vec_Info" ); m_ngGet_Vec_Info = (ngGet_Vec_Info) m_dll->GetSymbol( "ngGet_Vec_Info" );
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" );
} }
NGSPICE::~NGSPICE()
{
delete m_dll;
}
void NGSPICE::Init() void NGSPICE::Init()
{ {
m_ngSpice_Init( &cbSendChar, &cbSendStat, NULL, NULL, NULL, NULL, this); m_ngSpice_Init( &cbSendChar, &cbSendStat, NULL, NULL, NULL, NULL, this);
} }
const vector<double> NGSPICE::GetPlot( std::string name, int max_len )
const vector<double> NGSPICE::GetPlot( const string& aName, int aMaxLen )
{ {
vector<double> data; vector<double> data;
vector_info *vi = m_ngGet_Vec_Info((char*)name.c_str()); vector_info* vi = m_ngGet_Vec_Info( (char*) aName.c_str() );
if( vi->v_realdata ) if( vi->v_realdata )
{
for( int i = 0; i < vi->v_length; i++ ) for( int i = 0; i < vi->v_length; i++ )
data.push_back( vi->v_realdata[i] ); data.push_back( vi->v_realdata[i] );
}
return data; return data;
} }
static string loadFile(const string& filename) bool NGSPICE::LoadNetlist(const string& aNetlist)
{
FILE *f=fopen(filename.c_str(),"rb");
char buf[10000];
int n = fread(buf, 1, 10000, f);
fclose(f);
buf[n] = 0;
return buf;
}
bool NGSPICE::LoadNetlist(const string& netlist)
{ {
// TODO remove the hard limit
char* lines[16384]; char* lines[16384];
stringstream ss(netlist); stringstream ss( aNetlist );
int n = 0; int n = 0;
while(!ss.eof()) while( !ss.eof() && n < 16384 )
{ {
char line[1024]; char line[1024];
ss.getline(line, 1024); ss.getline( line, sizeof(line) );
lines[n++] = strdup(line); lines[n++] = strdup(line);
printf("l '%s'\n", line); printf("l '%s'\n", line);
} }
lines[n]= NULL;
printf("netlist contains %d lines\n", n); lines[n] = NULL;
m_ngSpice_Circ( lines ); m_ngSpice_Circ( lines );
for(int i = 0; i < n; i++) for(int i = 0; i < n; i++)
@ -154,10 +103,11 @@ bool NGSPICE::LoadNetlist(const string& netlist)
} }
bool NGSPICE::Command(const string& cmd ) bool NGSPICE::Command( const string& aCmd )
{ {
m_ngSpice_Command( (char*)(cmd + string("\n")).c_str()); m_ngSpice_Command( (char*)( aCmd + string( "\n" ) ).c_str() );
dump(); dump();
return true; return true;
} }
@ -167,7 +117,7 @@ void NGSPICE::dump()
// m_ngSpice_Command("run\n"); // m_ngSpice_Command("run\n");
char** plots = m_ngSpice_AllPlots(); char** plots = m_ngSpice_AllPlots();
for(int i = 0; plots[i]; i++) for( int i = 0; plots[i]; ++i )
{ {
printf( "-> plot : %s\n", plots[i] ); printf( "-> plot : %s\n", plots[i] );
char** vecs = m_ngSpice_AllVecs( plots[i] ); char** vecs = m_ngSpice_AllVecs( plots[i] );
@ -181,24 +131,24 @@ void NGSPICE::dump()
printf( " - v_type %x\n", vi->v_type ); printf( " - v_type %x\n", vi->v_type );
printf( " - v_flags %x\n", vi->v_flags ); printf( " - v_flags %x\n", vi->v_flags );
printf( " - v_length %d\n", vi->v_length ); printf( " - v_length %d\n", vi->v_length );
}
}
} }
}
}
NGSPICE::~NGSPICE()
{
printf("Killing ngspice\n");
delete m_dll;
}
#if 0 #if 0
static string loadFile(const string& filename)
{
FILE *f=fopen(filename.c_str(),"rb");
char buf[10000];
int n = fread(buf, 1, 10000, f);
fclose(f);
buf[n] = 0;
return buf;
}
main() main()
{ {
NGSPICE spice; NGSPICE spice;
@ -238,16 +188,28 @@ main()
std::string NGSPICE::GetConsole() const { string NGSPICE::GetConsole() const {
return ""; return "";
} }
SPICE_SIMULATOR::~SPICE_SIMULATOR()
{
int NGSPICE::cbSendChar( char* what, int id, void* user)
{
NGSPICE* sim = reinterpret_cast<NGSPICE*>( user );
printf("sim %p cr %p\n",sim, sim->m_consoleReporter );
if( sim->m_consoleReporter )
sim->m_consoleReporter->Report( what );
return 0;
} }
SPICE_SIMULATOR *SPICE_SIMULATOR::CreateInstance( const std::string name )
int NGSPICE::cbSendStat( char* what, int id, void* user)
{ {
return new NGSPICE; /* NGSPICE *sim = reinterpret_cast<NGSPICE*>(user);
if(sim->m_consoleReporter)
sim->m_consoleReporter->Report(what);*/
return 0;
} }

View File

@ -1,20 +1,73 @@
#ifndef __NGSPICE_H /*
#define __NGSPICE_H * This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <string> #ifndef NGSPICE_H
#include <vector> #define NGSPICE_H
class SPICE_SIMULATOR { #include "sharedspice.h"
#include "spice_simulator.h"
class wxDynamicLibrary;
class NGSPICE : public SPICE_SIMULATOR {
public: public:
SPICE_SIMULATOR(); NGSPICE();
~SPICE_SIMULATOR(); virtual ~NGSPICE();
virtual void Init(); void Init();
virtual bool LoadNetlist(const std::string& netlist); bool LoadNetlist( const std::string& aNetlist );
virtual bool Command(const std::string& cmd); bool Command( const std::string& aCmd );
const std::vector<double> GetPlot( std::string name, int max_len = -1); std::string GetConsole() const;
const std::vector<double> GetPlot( const std::string& aName, int aMaxLen = -1 );
void dump();
private:
typedef void (*ngSpice_Init)( SendChar*, SendStat*, ControlledExit*,
SendData*, SendInitData*, BGThreadRunning*, void* );
// ngspice library functions
typedef int (*ngSpice_Circ)(char** circarray);
typedef int (*ngSpice_Command)(char* command);
typedef pvector_info (*ngGet_Vec_Info)(char* vecname);
typedef char** (*ngSpice_AllVecs)(char* plotname);
typedef char** (*ngSpice_AllPlots)(void);
ngSpice_Init m_ngSpice_Init;
ngSpice_Circ m_ngSpice_Circ;
ngSpice_Command m_ngSpice_Command;
ngGet_Vec_Info m_ngGet_Vec_Info;
ngSpice_AllPlots m_ngSpice_AllPlots;
ngSpice_AllVecs m_ngSpice_AllVecs;
wxDynamicLibrary* m_dll;
static int cbSendChar( char* what, int id, void* user );
static int cbSendStat( char* what, int id, void* user );
}; };
#endif #endif /* NGSPICE_H */

View File

@ -44,6 +44,10 @@
#include "sim_plot_panel.h" #include "sim_plot_panel.h"
#include "spice_simulator.h" #include "spice_simulator.h"
#ifdef KICAD_SCRIPTING
#include <python_scripting.h>
#endif
class SIM_REPORTER : public REPORTER class SIM_REPORTER : public REPORTER
{ {
@ -51,11 +55,11 @@ public:
SIM_REPORTER( wxRichTextCtrl* console ) SIM_REPORTER( wxRichTextCtrl* console )
{ {
m_console = console; m_console = console;
} }
~SIM_REPORTER() ~SIM_REPORTER()
{ {
} }
virtual REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_UNDEFINED ) virtual REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_UNDEFINED )
@ -67,25 +71,27 @@ public:
private: private:
wxRichTextCtrl* m_console; wxRichTextCtrl* m_console;
}; };
SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY *aKiway, wxWindow* parent ) SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
: SIM_PLOT_FRAME_BASE( aKiway, parent ) : SIM_PLOT_FRAME_BASE( aKiway, aParent )
{ {
m_exporter = NULL; m_exporter = NULL;
m_simulator = NULL; m_simulator = NULL;
m_currentPlot = NULL; m_currentPlot = NULL;
m_pyConsole = NULL;
NewPlot(); NewPlot();
TogglePythonConsole();
} }
SIM_PLOT_FRAME::~SIM_PLOT_FRAME() SIM_PLOT_FRAME::~SIM_PLOT_FRAME()
{ {
} }
void SIM_PLOT_FRAME::StartSimulation() void SIM_PLOT_FRAME::StartSimulation()
{ {
if( m_exporter ) if( m_exporter )
@ -131,6 +137,7 @@ void SIM_PLOT_FRAME::StartSimulation()
//m_simulator->Command("quit\n"); //m_simulator->Command("quit\n");
} }
void SIM_PLOT_FRAME::NewPlot() void SIM_PLOT_FRAME::NewPlot()
{ {
SIM_PLOT_PANEL* plot = new SIM_PLOT_PANEL( this, wxID_ANY ); SIM_PLOT_PANEL* plot = new SIM_PLOT_PANEL( this, wxID_ANY );

View File

@ -22,11 +22,9 @@ class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE
{ {
public: public:
/** Constructor */ /** Constructor */
SIM_PLOT_FRAME(KIWAY *aKiway, wxWindow* parent ); SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent );
~SIM_PLOT_FRAME(); ~SIM_PLOT_FRAME();
void SetSchFrame( SCH_EDIT_FRAME* schFrame ) void SetSchFrame( SCH_EDIT_FRAME* schFrame )
{ {
m_schematicFrame = schFrame; m_schematicFrame = schFrame;
@ -36,16 +34,16 @@ class SIM_PLOT_FRAME : public SIM_PLOT_FRAME_BASE
void NewPlot(); void NewPlot();
void TogglePythonConsole();
private: private:
virtual void onNewPlot( wxCommandEvent& event ) { NewPlot(); } virtual void onNewPlot( wxCommandEvent& event ) { NewPlot(); }
SIM_PLOT_PANEL* m_currentPlot; SIM_PLOT_PANEL* m_currentPlot;
SCH_EDIT_FRAME* m_schematicFrame; SCH_EDIT_FRAME* m_schematicFrame;
NETLIST_EXPORTER_PSPICE* m_exporter; NETLIST_EXPORTER_PSPICE* m_exporter;
SPICE_SIMULATOR* m_simulator; SPICE_SIMULATOR* m_simulator;
wxWindow* m_pyConsole;
//// end generated class members //// end generated class members
}; };

View File

@ -4,7 +4,6 @@ static SIM_PLOT_PANEL *panel = NULL;
static int drawPlotFunc( mglGraph *graph ) static int drawPlotFunc( mglGraph *graph )
{ {
printf("DrawPlot [%d traces]!\n", panel->m_traces.size()); printf("DrawPlot [%d traces]!\n", panel->m_traces.size());
graph->Clf(); graph->Clf();
@ -17,7 +16,6 @@ static int drawPlotFunc( mglGraph *graph )
graph->Label('y',"Voltage",0); graph->Label('y',"Voltage",0);
graph->SetRange('y', -1.5, 1.5); graph->SetRange('y', -1.5, 1.5);
for( auto t : panel->m_traces ) for( auto t : panel->m_traces )
{ {
graph->AddLegend( (const char*) t.name.c_str(), "" ); graph->AddLegend( (const char*) t.name.c_str(), "" );
@ -34,12 +32,8 @@ static int drawPlotFunc( mglGraph *graph )
} }
SIM_PLOT_PANEL::SIM_PLOT_PANEL( wxWindow * parent, SIM_PLOT_PANEL::SIM_PLOT_PANEL( wxWindow* parent, wxWindowID id, const wxPoint& pos,
wxWindowID id, const wxSize& size, long style, const wxString& name )
const wxPoint & pos,
const wxSize & size,
long style,
const wxString & name )
: wxMathGL( parent, id, pos, size, style, name ) : wxMathGL( parent, id, pos, size, style, name )
{ {
panel = this; panel = this;
@ -52,9 +46,9 @@ SIM_PLOT_PANEL::SIM_PLOT_PANEL( wxWindow * parent,
SIM_PLOT_PANEL::~SIM_PLOT_PANEL() SIM_PLOT_PANEL::~SIM_PLOT_PANEL()
{ {
} }
void SIM_PLOT_PANEL::AddTrace(const wxString& name, int n_points, double *t, double *x, int flags ) void SIM_PLOT_PANEL::AddTrace(const wxString& name, int n_points, double *t, double *x, int flags )
{ {
Trace trace; Trace trace;

View File

@ -0,0 +1,31 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "ngspice.h"
SPICE_SIMULATOR* SPICE_SIMULATOR::CreateInstance( const std::string& )
{
return new NGSPICE;
}

View File

@ -1,10 +1,36 @@
#ifndef __NGSPICE_H /*
#define __NGSPICE_H * This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef SPICE_SIMULATOR_H
#define SPICE_SIMULATOR_H
#include <string> #include <string>
#include <vector> #include <vector>
enum SimTraceType class REPORTER;
enum SIM_TRACE_TYPE
{ {
SIM_AC_MAG = 0x1, SIM_AC_MAG = 0x1,
SIM_AC_PHASE = 0x2, SIM_AC_PHASE = 0x2,
@ -13,32 +39,29 @@ SIM_TR_CURRENT = 0x8,
SIM_TR_FFT = 0x10 SIM_TR_FFT = 0x10
}; };
class REPORTER;
class SPICE_SIMULATOR { class SPICE_SIMULATOR {
public: public:
typedef void (*ConsoleCallback)( bool isError, const wxString& message, void *userData );
static SPICE_SIMULATOR *CreateInstance( const std::string name );
SPICE_SIMULATOR() {} SPICE_SIMULATOR() {}
virtual ~SPICE_SIMULATOR() = 0; virtual ~SPICE_SIMULATOR() {}
static SPICE_SIMULATOR* CreateInstance( const std::string& aName );
typedef void (*ConsoleCallback)( bool isError, const std::string& message, void* userData );
virtual void Init() = 0; virtual void Init() = 0;
virtual bool LoadNetlist(const std::string& netlist) = 0; virtual bool LoadNetlist( const std::string& aNetlist ) = 0;
virtual bool Command(const std::string& cmd) = 0; virtual bool Command( const std::string& aCmd ) = 0;
virtual void SetConsoleReporter ( REPORTER *rep )
virtual void SetConsoleReporter( REPORTER* aReporter )
{ {
m_consoleReporter = rep; m_consoleReporter = aReporter;
} }
virtual const std::vector<double> GetPlot( std::string name, int max_len = -1) = 0; virtual const std::vector<double> GetPlot( const std::string& aName, int aMaxLen = -1) = 0;
protected: protected:
REPORTER* m_consoleReporter; REPORTER* m_consoleReporter;
}; };
#endif /* SPICE_SIMULATOR_H */
#endif