You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

354 lines
11 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2016-2023 CERN
  5. * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
  6. * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  7. * @author Maciej Suminski <maciej.suminski@cern.ch>
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 3
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, you may find one here:
  21. * https://www.gnu.org/licenses/gpl-3.0.html
  22. * or you may search the http://www.gnu.org website for the version 3 license,
  23. * or you may write to the Free Software Foundation, Inc.,
  24. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  25. */
  26. #include <memory>
  27. #include <wx/debug.h>
  28. #include <project/project_file.h>
  29. #include <confirm.h>
  30. #include <string_utils.h>
  31. #include <sim/simulator_frame_ui.h>
  32. #include <sim/simulator_frame.h>
  33. #include <sim/sim_plot_tab.h>
  34. void SIMULATOR_FRAME_UI::parseTraceParams( SIM_PLOT_TAB* aPlotTab, TRACE* aTrace,
  35. const wxString& aSignalName, const wxString& aParams )
  36. {
  37. auto addCursor =
  38. [&]( int aCursorId, double x )
  39. {
  40. CURSOR* cursor = new CURSOR( aTrace, aPlotTab );
  41. cursor->SetName( aSignalName );
  42. cursor->SetPen( wxPen( aTrace->GetTraceColour() ) );
  43. cursor->SetCoordX( x );
  44. aTrace->SetCursor( aCursorId, cursor );
  45. aPlotTab->GetPlotWin()->AddLayer( cursor );
  46. };
  47. wxArrayString items = wxSplit( aParams, '|' );
  48. for( const wxString& item : items )
  49. {
  50. if( item.StartsWith( wxS( "rgb" ) ) )
  51. {
  52. wxColour color;
  53. color.Set( item );
  54. aTrace->SetTraceColour( color );
  55. aPlotTab->UpdateTraceStyle( aTrace );
  56. }
  57. else if( item.StartsWith( wxS( "cursor1" ) ) )
  58. {
  59. wxArrayString parts = wxSplit( item, ':' );
  60. double val;
  61. if( parts.size() == 3 )
  62. {
  63. parts[0].AfterFirst( '=' ).ToDouble( &val );
  64. m_cursorFormats[0][0].FromString( parts[1] );
  65. m_cursorFormats[0][1].FromString( parts[2] );
  66. addCursor( 1, val );
  67. }
  68. }
  69. else if( item.StartsWith( wxS( "cursor2" ) ) )
  70. {
  71. wxArrayString parts = wxSplit( item, ':' );
  72. double val;
  73. if( parts.size() == 3 )
  74. {
  75. parts[0].AfterFirst( '=' ).ToDouble( &val );
  76. m_cursorFormats[1][0].FromString( parts[1] );
  77. m_cursorFormats[1][1].FromString( parts[2] );
  78. addCursor( 2, val );
  79. }
  80. }
  81. else if( item.StartsWith( wxS( "cursorD" ) ) )
  82. {
  83. wxArrayString parts = wxSplit( item, ':' );
  84. if( parts.size() == 3 )
  85. {
  86. m_cursorFormats[2][0].FromString( parts[1] );
  87. m_cursorFormats[2][1].FromString( parts[2] );
  88. }
  89. }
  90. else if( item == wxS( "dottedSecondary" ) )
  91. {
  92. aPlotTab->SetDottedSecondary( true );
  93. }
  94. else if( item == wxS( "hideGrid" ) )
  95. {
  96. aPlotTab->ShowGrid( false );
  97. }
  98. }
  99. }
  100. bool SIMULATOR_FRAME_UI::loadLegacyWorkbook( const wxString& aPath )
  101. {
  102. wxTextFile file( aPath );
  103. #define EXPECTING( msg ) \
  104. DisplayErrorMessage( this, wxString::Format( _( "Error loading workbook: line %d: %s." ), \
  105. file.GetCurrentLine()+1, \
  106. msg ) )
  107. if( !file.Open() )
  108. return false;
  109. long version = 1;
  110. wxString firstLine = file.GetFirstLine();
  111. wxString pageCountLine;
  112. if( firstLine.StartsWith( wxT( "version " ) ) )
  113. {
  114. if( !firstLine.substr( 8 ).ToLong( &version ) )
  115. {
  116. EXPECTING( _( "expecting version" ) );
  117. file.Close();
  118. return false;
  119. }
  120. pageCountLine = file.GetNextLine();
  121. }
  122. else
  123. {
  124. pageCountLine = firstLine;
  125. }
  126. long tabCount;
  127. if( !pageCountLine.ToLong( &tabCount ) )
  128. {
  129. EXPECTING( _( "expecting simulation tab count" ) );
  130. file.Close();
  131. return false;
  132. }
  133. std::map<SIM_PLOT_TAB*, std::vector<std::tuple<long, wxString, wxString>>> traceInfo;
  134. for( long i = 0; i < tabCount; ++i )
  135. {
  136. long simType, tracesCount;
  137. if( !file.GetNextLine().ToLong( &simType ) )
  138. {
  139. EXPECTING( _( "expecting simulation tab type" ) );
  140. file.Close();
  141. return false;
  142. }
  143. wxString command = UnescapeString( file.GetNextLine() );
  144. wxString simCommand;
  145. int simOptions = NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS;
  146. wxStringTokenizer tokenizer( command, wxT( "\r\n" ), wxTOKEN_STRTOK );
  147. if( version >= 2 )
  148. {
  149. simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS;
  150. simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES;
  151. simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS;
  152. }
  153. if( version >= 3 )
  154. {
  155. simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_DISSIPATIONS;
  156. }
  157. while( tokenizer.HasMoreTokens() )
  158. {
  159. wxString line = tokenizer.GetNextToken();
  160. if( line.StartsWith( wxT( ".kicad adjustpaths" ) ) )
  161. simOptions |= NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS;
  162. else if( line.StartsWith( wxT( ".save all" ) ) )
  163. simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES;
  164. else if( line.StartsWith( wxT( ".probe alli" ) ) )
  165. simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS;
  166. else if( line.StartsWith( wxT( ".probe allp" ) ) )
  167. simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_DISSIPATIONS;
  168. else
  169. simCommand += line + wxT( "\n" );
  170. }
  171. SIM_TAB* simTab = NewSimTab( simCommand );
  172. SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( simTab );
  173. simTab->SetSimOptions( simOptions );
  174. if( !file.GetNextLine().ToLong( &tracesCount ) )
  175. {
  176. EXPECTING( _( "expecting trace count" ) );
  177. file.Close();
  178. return false;
  179. }
  180. if( plotTab )
  181. traceInfo[plotTab] = {};
  182. for( long j = 0; j < tracesCount; ++j )
  183. {
  184. long traceType;
  185. wxString name, param;
  186. if( !file.GetNextLine().ToLong( &traceType ) )
  187. {
  188. EXPECTING( _( "expecting trace type" ) );
  189. file.Close();
  190. return false;
  191. }
  192. name = file.GetNextLine();
  193. if( name.IsEmpty() )
  194. {
  195. EXPECTING( _( "expecting trace name" ) );
  196. file.Close();
  197. return false;
  198. }
  199. param = file.GetNextLine();
  200. if( param.IsEmpty() )
  201. {
  202. EXPECTING( _( "expecting trace color" ) );
  203. file.Close();
  204. return false;
  205. }
  206. if( plotTab )
  207. traceInfo[plotTab].emplace_back( std::make_tuple( traceType, name, param ) );
  208. }
  209. if( version > 4 )
  210. {
  211. long measurementCount;
  212. if( !file.GetNextLine().ToLong( &measurementCount ) )
  213. {
  214. EXPECTING( _( "expecting measurement count" ) );
  215. file.Close();
  216. return false;
  217. }
  218. for( int ii = 0; ii < (int) measurementCount; ++ ii )
  219. {
  220. wxString measurement = file.GetNextLine();
  221. if( measurement.IsEmpty() )
  222. {
  223. EXPECTING( _( "expecting measurement definition" ) );
  224. file.Close();
  225. return false;
  226. }
  227. wxString format = file.GetNextLine();
  228. if( format.IsEmpty() )
  229. {
  230. EXPECTING( _( "expecting measurement format definition" ) );
  231. file.Close();
  232. return false;
  233. }
  234. if( plotTab )
  235. plotTab->Measurements().emplace_back( measurement, format );
  236. }
  237. }
  238. }
  239. long userDefinedSignalCount;
  240. if( file.GetNextLine().ToLong( &userDefinedSignalCount ) )
  241. {
  242. for( int ii = 0; ii < (int) userDefinedSignalCount; ++ii )
  243. m_userDefinedSignals[ ii ] = file.GetNextLine();
  244. }
  245. for( const auto& [ plotTab, traceInfoVector ] : traceInfo )
  246. {
  247. for( const auto& [ traceType, signalName, param ] : traceInfoVector )
  248. {
  249. if( traceType == SPT_UNKNOWN && signalName == wxS( "$LEGEND" ) )
  250. {
  251. wxArrayString coords = wxSplit( param, ' ' );
  252. if( coords.size() >= 2 )
  253. {
  254. long x = 0;
  255. long y = 0;
  256. coords[0].ToLong( &x );
  257. coords[1].ToLong( &y );
  258. plotTab->SetLegendPosition( wxPoint( (int) x, (int) y ) );
  259. }
  260. plotTab->ShowLegend( true );
  261. }
  262. else
  263. {
  264. wxString vectorName = vectorNameFromSignalName( plotTab, signalName, nullptr );
  265. TRACE* trace = plotTab->AddTrace( vectorName, (int) traceType );
  266. if( version >= 4 && trace )
  267. parseTraceParams( plotTab, trace, signalName, param );
  268. }
  269. }
  270. plotTab->UpdatePlotColors();
  271. }
  272. if( SIM_TAB* simTab = GetCurrentSimTab() )
  273. {
  274. m_simulatorFrame->LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() );
  275. if( version >= 5 )
  276. {
  277. simTab = dynamic_cast<SIM_TAB*>( m_plotNotebook->GetPage( 0 ) );
  278. if( simTab )
  279. simTab->SetLastSchTextSimCommand( file.GetNextLine() );
  280. }
  281. }
  282. file.Close();
  283. return true;
  284. }