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.

353 lines
11 KiB

2 years ago
  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 The 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->SetCoordX( x );
  43. aTrace->SetCursor( aCursorId, cursor );
  44. aPlotTab->GetPlotWin()->AddLayer( cursor );
  45. };
  46. wxArrayString items = wxSplit( aParams, '|' );
  47. for( const wxString& item : items )
  48. {
  49. if( item.StartsWith( wxS( "rgb" ) ) )
  50. {
  51. wxColour color;
  52. color.Set( item );
  53. aTrace->SetTraceColour( color );
  54. aPlotTab->UpdateTraceStyle( aTrace );
  55. }
  56. else if( item.StartsWith( wxS( "cursor1" ) ) )
  57. {
  58. wxArrayString parts = wxSplit( item, ':' );
  59. double val;
  60. if( parts.size() == 3 )
  61. {
  62. parts[0].AfterFirst( '=' ).ToDouble( &val );
  63. m_cursorFormats[0][0].FromString( parts[1] );
  64. m_cursorFormats[0][1].FromString( parts[2] );
  65. addCursor( 1, val );
  66. }
  67. }
  68. else if( item.StartsWith( wxS( "cursor2" ) ) )
  69. {
  70. wxArrayString parts = wxSplit( item, ':' );
  71. double val;
  72. if( parts.size() == 3 )
  73. {
  74. parts[0].AfterFirst( '=' ).ToDouble( &val );
  75. m_cursorFormats[1][0].FromString( parts[1] );
  76. m_cursorFormats[1][1].FromString( parts[2] );
  77. addCursor( 2, val );
  78. }
  79. }
  80. else if( item.StartsWith( wxS( "cursorD" ) ) )
  81. {
  82. wxArrayString parts = wxSplit( item, ':' );
  83. if( parts.size() == 3 )
  84. {
  85. m_cursorFormats[2][0].FromString( parts[1] );
  86. m_cursorFormats[2][1].FromString( parts[2] );
  87. }
  88. }
  89. else if( item == wxS( "dottedSecondary" ) )
  90. {
  91. aPlotTab->SetDottedSecondary( true );
  92. }
  93. else if( item == wxS( "hideGrid" ) )
  94. {
  95. aPlotTab->ShowGrid( false );
  96. }
  97. }
  98. }
  99. bool SIMULATOR_FRAME_UI::loadLegacyWorkbook( const wxString& aPath )
  100. {
  101. wxTextFile file( aPath );
  102. #define EXPECTING( msg ) \
  103. DisplayErrorMessage( this, wxString::Format( _( "Error loading workbook: line %d: %s." ), \
  104. file.GetCurrentLine()+1, \
  105. msg ) )
  106. if( !file.Open() )
  107. return false;
  108. long version = 1;
  109. wxString firstLine = file.GetFirstLine();
  110. wxString pageCountLine;
  111. if( firstLine.StartsWith( wxT( "version " ) ) )
  112. {
  113. if( !firstLine.substr( 8 ).ToLong( &version ) )
  114. {
  115. EXPECTING( _( "expecting version" ) );
  116. file.Close();
  117. return false;
  118. }
  119. pageCountLine = file.GetNextLine();
  120. }
  121. else
  122. {
  123. pageCountLine = firstLine;
  124. }
  125. long tabCount;
  126. if( !pageCountLine.ToLong( &tabCount ) )
  127. {
  128. EXPECTING( _( "expecting simulation tab count" ) );
  129. file.Close();
  130. return false;
  131. }
  132. std::map<SIM_PLOT_TAB*, std::vector<std::tuple<long, wxString, wxString>>> traceInfo;
  133. for( long i = 0; i < tabCount; ++i )
  134. {
  135. long simType, tracesCount;
  136. if( !file.GetNextLine().ToLong( &simType ) )
  137. {
  138. EXPECTING( _( "expecting simulation tab type" ) );
  139. file.Close();
  140. return false;
  141. }
  142. wxString command = UnescapeString( file.GetNextLine() );
  143. wxString simCommand;
  144. int simOptions = NETLIST_EXPORTER_SPICE::OPTION_DEFAULT_FLAGS;
  145. wxStringTokenizer tokenizer( command, "\r\n", wxTOKEN_STRTOK );
  146. if( version >= 2 )
  147. {
  148. simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS;
  149. simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES;
  150. simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS;
  151. }
  152. if( version >= 3 )
  153. {
  154. simOptions &= ~NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_DISSIPATIONS;
  155. }
  156. while( tokenizer.HasMoreTokens() )
  157. {
  158. wxString line = tokenizer.GetNextToken();
  159. if( line.StartsWith( wxT( ".kicad adjustpaths" ) ) )
  160. simOptions |= NETLIST_EXPORTER_SPICE::OPTION_ADJUST_INCLUDE_PATHS;
  161. else if( line.StartsWith( wxT( ".save all" ) ) )
  162. simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_VOLTAGES;
  163. else if( line.StartsWith( wxT( ".probe alli" ) ) )
  164. simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_CURRENTS;
  165. else if( line.StartsWith( wxT( ".probe allp" ) ) )
  166. simOptions |= NETLIST_EXPORTER_SPICE::OPTION_SAVE_ALL_DISSIPATIONS;
  167. else
  168. simCommand += line + wxT( "\n" );
  169. }
  170. SIM_TAB* simTab = NewSimTab( simCommand );
  171. SIM_PLOT_TAB* plotTab = dynamic_cast<SIM_PLOT_TAB*>( simTab );
  172. simTab->SetSimOptions( simOptions );
  173. if( !file.GetNextLine().ToLong( &tracesCount ) )
  174. {
  175. EXPECTING( _( "expecting trace count" ) );
  176. file.Close();
  177. return false;
  178. }
  179. if( plotTab )
  180. traceInfo[plotTab] = {};
  181. for( long j = 0; j < tracesCount; ++j )
  182. {
  183. long traceType;
  184. wxString name, param;
  185. if( !file.GetNextLine().ToLong( &traceType ) )
  186. {
  187. EXPECTING( _( "expecting trace type" ) );
  188. file.Close();
  189. return false;
  190. }
  191. name = file.GetNextLine();
  192. if( name.IsEmpty() )
  193. {
  194. EXPECTING( _( "expecting trace name" ) );
  195. file.Close();
  196. return false;
  197. }
  198. param = file.GetNextLine();
  199. if( param.IsEmpty() )
  200. {
  201. EXPECTING( _( "expecting trace color" ) );
  202. file.Close();
  203. return false;
  204. }
  205. if( plotTab )
  206. traceInfo[plotTab].emplace_back( std::make_tuple( traceType, name, param ) );
  207. }
  208. if( version > 4 )
  209. {
  210. long measurementCount;
  211. if( !file.GetNextLine().ToLong( &measurementCount ) )
  212. {
  213. EXPECTING( _( "expecting measurement count" ) );
  214. file.Close();
  215. return false;
  216. }
  217. for( int ii = 0; ii < (int) measurementCount; ++ ii )
  218. {
  219. wxString measurement = file.GetNextLine();
  220. if( measurement.IsEmpty() )
  221. {
  222. EXPECTING( _( "expecting measurement definition" ) );
  223. file.Close();
  224. return false;
  225. }
  226. wxString format = file.GetNextLine();
  227. if( format.IsEmpty() )
  228. {
  229. EXPECTING( _( "expecting measurement format definition" ) );
  230. file.Close();
  231. return false;
  232. }
  233. if( plotTab )
  234. plotTab->Measurements().emplace_back( measurement, format );
  235. }
  236. }
  237. }
  238. long userDefinedSignalCount;
  239. if( file.GetNextLine().ToLong( &userDefinedSignalCount ) )
  240. {
  241. for( int ii = 0; ii < (int) userDefinedSignalCount; ++ii )
  242. m_userDefinedSignals[ ii ] = file.GetNextLine();
  243. }
  244. for( const auto& [ plotTab, traceInfoVector ] : traceInfo )
  245. {
  246. for( const auto& [ traceType, signalName, param ] : traceInfoVector )
  247. {
  248. if( traceType == SPT_UNKNOWN && signalName == wxS( "$LEGEND" ) )
  249. {
  250. wxArrayString coords = wxSplit( param, ' ' );
  251. if( coords.size() >= 2 )
  252. {
  253. long x = 0;
  254. long y = 0;
  255. coords[0].ToLong( &x );
  256. coords[1].ToLong( &y );
  257. plotTab->SetLegendPosition( wxPoint( (int) x, (int) y ) );
  258. }
  259. plotTab->ShowLegend( true );
  260. }
  261. else
  262. {
  263. wxString vectorName = vectorNameFromSignalName( plotTab, signalName, nullptr );
  264. TRACE* trace = plotTab->GetOrAddTrace( vectorName, (int) traceType );
  265. if( version >= 4 && trace )
  266. parseTraceParams( plotTab, trace, signalName, param );
  267. }
  268. }
  269. plotTab->UpdatePlotColors();
  270. }
  271. if( SIM_TAB* simTab = GetCurrentSimTab() )
  272. {
  273. m_simulatorFrame->LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() );
  274. if( version >= 5 )
  275. {
  276. simTab = dynamic_cast<SIM_TAB*>( m_plotNotebook->GetPage( 0 ) );
  277. if( simTab )
  278. simTab->SetLastSchTextSimCommand( file.GetNextLine() );
  279. }
  280. }
  281. file.Close();
  282. return true;
  283. }