kicad/eeschema/sim/legacy_workbook.cpp

354 lines
11 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016-2023 CERN
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
* @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 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 <memory>
#include <wx/debug.h>
#include <project/project_file.h>
#include <confirm.h>
#include <string_utils.h>
#include <sim/simulator_frame_ui.h>
#include <sim/simulator_frame.h>
#include <sim/sim_plot_tab.h>
void SIMULATOR_FRAME_UI::parseTraceParams( SIM_PLOT_TAB* aPlotTab, TRACE* aTrace,
const wxString& aSignalName, const wxString& aParams )
{
auto addCursor =
[&]( int aCursorId, double x )
{
CURSOR* cursor = new CURSOR( aTrace, aPlotTab );
cursor->SetName( aSignalName );
cursor->SetCoordX( x );
aTrace->SetCursor( aCursorId, cursor );
aPlotTab->GetPlotWin()->AddLayer( cursor );
};
wxArrayString items = wxSplit( aParams, '|' );
for( const wxString& item : items )
{
if( item.StartsWith( wxS( "rgb" ) ) )
{
wxColour color;
color.Set( item );
aTrace->SetTraceColour( color );
aPlotTab->UpdateTraceStyle( aTrace );
}
else if( item.StartsWith( wxS( "cursor1" ) ) )
{
wxArrayString parts = wxSplit( item, ':' );
double val;
if( parts.size() == 3 )
{
parts[0].AfterFirst( '=' ).ToDouble( &val );
m_cursorFormats[0][0].FromString( parts[1] );
m_cursorFormats[0][1].FromString( parts[2] );
addCursor( 1, val );
}
}
else if( item.StartsWith( wxS( "cursor2" ) ) )
{
wxArrayString parts = wxSplit( item, ':' );
double val;
if( parts.size() == 3 )
{
parts[0].AfterFirst( '=' ).ToDouble( &val );
m_cursorFormats[1][0].FromString( parts[1] );
m_cursorFormats[1][1].FromString( parts[2] );
addCursor( 2, val );
}
}
else if( item.StartsWith( wxS( "cursorD" ) ) )
{
wxArrayString parts = wxSplit( item, ':' );
if( parts.size() == 3 )
{
m_cursorFormats[2][0].FromString( parts[1] );
m_cursorFormats[2][1].FromString( parts[2] );
}
}
else if( item == wxS( "dottedSecondary" ) )
{
aPlotTab->SetDottedSecondary( true );
}
else if( item == wxS( "hideGrid" ) )
{
aPlotTab->ShowGrid( false );
}
}
}
bool SIMULATOR_FRAME_UI::loadLegacyWorkbook( const wxString& aPath )
{
wxTextFile file( aPath );
#define EXPECTING( msg ) \
DisplayErrorMessage( this, wxString::Format( _( "Error loading workbook: line %d: %s." ), \
file.GetCurrentLine()+1, \
msg ) )
if( !file.Open() )
return false;
long version = 1;
wxString firstLine = file.GetFirstLine();
wxString pageCountLine;
if( firstLine.StartsWith( wxT( "version " ) ) )
{
if( !firstLine.substr( 8 ).ToLong( &version ) )
{
EXPECTING( _( "expecting version" ) );
file.Close();
return false;
}
pageCountLine = file.GetNextLine();
}
else
{
pageCountLine = firstLine;
}
long tabCount;
if( !pageCountLine.ToLong( &tabCount ) )
{
EXPECTING( _( "expecting simulation tab count" ) );
file.Close();
return false;
}
std::map<SIM_PLOT_TAB*, std::vector<std::tuple<long, wxString, wxString>>> traceInfo;
for( long i = 0; i < tabCount; ++i )
{
long simType, tracesCount;
if( !file.GetNextLine().ToLong( &simType ) )
{
EXPECTING( _( "expecting simulation tab type" ) );
file.Close();
return false;
}
wxString command = UnescapeString( file.GetNextLine() );
wxString simCommand;
int simOptions = NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS;
wxStringTokenizer tokenizer( command, wxT( "\r\n" ), wxTOKEN_STRTOK );
if( version >= 2 )
{
simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS;
simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES;
simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS;
}
if( version >= 3 )
{
simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_DISSIPATIONS;
}
while( tokenizer.HasMoreTokens() )
{
wxString line = tokenizer.GetNextToken();
if( line.StartsWith( wxT( ".kicad adjustpaths" ) ) )
simOptions |= NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS;
else if( line.StartsWith( wxT( ".save all" ) ) )
simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES;
else if( line.StartsWith( wxT( ".probe alli" ) ) )
simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS;
else if( line.StartsWith( wxT( ".probe allp" ) ) )
simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_DISSIPATIONS;
else
simCommand += line + wxT( "\n" );
}
SIM_TAB* simTab = NewSimTab( simCommand );
SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( simTab );
simTab->SetSimOptions( simOptions );
if( !file.GetNextLine().ToLong( &tracesCount ) )
{
EXPECTING( _( "expecting trace count" ) );
file.Close();
return false;
}
if( plotTab )
traceInfo[plotTab] = {};
for( long j = 0; j < tracesCount; ++j )
{
long traceType;
wxString name, param;
if( !file.GetNextLine().ToLong( &traceType ) )
{
EXPECTING( _( "expecting trace type" ) );
file.Close();
return false;
}
name = file.GetNextLine();
if( name.IsEmpty() )
{
EXPECTING( _( "expecting trace name" ) );
file.Close();
return false;
}
param = file.GetNextLine();
if( param.IsEmpty() )
{
EXPECTING( _( "expecting trace color" ) );
file.Close();
return false;
}
if( plotTab )
traceInfo[plotTab].emplace_back( std::make_tuple( traceType, name, param ) );
}
if( version > 4 )
{
long measurementCount;
if( !file.GetNextLine().ToLong( &measurementCount ) )
{
EXPECTING( _( "expecting measurement count" ) );
file.Close();
return false;
}
for( int ii = 0; ii < (int) measurementCount; ++ ii )
{
wxString measurement = file.GetNextLine();
if( measurement.IsEmpty() )
{
EXPECTING( _( "expecting measurement definition" ) );
file.Close();
return false;
}
wxString format = file.GetNextLine();
if( format.IsEmpty() )
{
EXPECTING( _( "expecting measurement format definition" ) );
file.Close();
return false;
}
if( plotTab )
plotTab->Measurements().emplace_back( measurement, format );
}
}
}
long userDefinedSignalCount;
if( file.GetNextLine().ToLong( &userDefinedSignalCount ) )
{
for( int ii = 0; ii < (int) userDefinedSignalCount; ++ii )
m_userDefinedSignals[ ii ] = file.GetNextLine();
}
for( const auto& [ plotTab, traceInfoVector ] : traceInfo )
{
for( const auto& [ traceType, signalName, param ] : traceInfoVector )
{
if( traceType == SPT_UNKNOWN && signalName == wxS( "$LEGEND" ) )
{
wxArrayString coords = wxSplit( param, ' ' );
if( coords.size() >= 2 )
{
long x = 0;
long y = 0;
coords[0].ToLong( &x );
coords[1].ToLong( &y );
plotTab->SetLegendPosition( wxPoint( (int) x, (int) y ) );
}
plotTab->ShowLegend( true );
}
else
{
wxString vectorName = vectorNameFromSignalName( plotTab, signalName, nullptr );
TRACE* trace = plotTab->GetOrAddTrace( vectorName, (int) traceType );
if( version >= 4 && trace )
parseTraceParams( plotTab, trace, signalName, param );
}
}
plotTab->UpdatePlotColors();
}
if( SIM_TAB* simTab = GetCurrentSimTab() )
{
m_simulatorFrame->LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() );
if( version >= 5 )
{
simTab = dynamic_cast<SIM_TAB*>( m_plotNotebook->GetPage( 0 ) );
if( simTab )
simTab->SetLastSchTextSimCommand( file.GetNextLine() );
}
}
file.Close();
return true;
}