prcngspice.cpp

来自「gspiceui电子CAD仿真程序.用于电路参数模拟仿真」· C++ 代码 · 共 989 行 · 第 1/2 页

CPP
989
字号
//*****************************************************************************//                               PrcNgSpice.cpp                               *//                              ----------------                              *//  Started     : 07/05/2004                                                  *//  Last Update : 09/06/2005                                                  *//  Copyright   : (C) 2004 by M.S.Waters                                      *//  Email       : M.Waters@bom.gov.au                                         *//*****************************************************************************//*****************************************************************************//                                                                            *//    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.                                     *//                                                                            *//*****************************************************************************#include "PrcNgSpice.hpp"//*****************************************************************************// Constructor.PrcNgSpice::PrcNgSpice( void ) : PrcSimrBase( ){  // Set the simulator binary file name if it can be found  bSetBinary( wxT("ngspice") );}//*****************************************************************************// Destructor.PrcNgSpice::~PrcNgSpice( ){}//*****************************************************************************// Parse a OPTIONS command and put the data in a simulation object.// eg.s .OPTIONS TEMP=27.00 TNOM=27.00//// Argument List://   rosCmd - The command line to be parsed//   roSim  - The simulation object//// Return Values://   TRUE  - Success//   FALSE - Failurebool  PrcNgSpice::bParseCmdOPT( wxString & rosCmd, Simulation & roSim ){  wxStringTokenizer  ostk1( rosCmd, wxT(" =\t\n\r") );  wxString  os1;  bool      bRtn=TRUE;  double    df1;  // Basic argument checks  if( ostk1.CountTokens( ) < 3 )              return( FALSE );  // Check command type  os1 = ostk1.GetNextToken( );  if( os1.Upper( ) != wxT(".OPTIONS") )       return( FALSE );  // Extract the analysis temperature  os1 = ostk1.GetNextToken( );  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToFlt( os1, &df1 ) ) bRtn = FALSE;  if( ! roSim.bSetTempC( (float) df1 ) )      bRtn = FALSE;  return( bRtn );}//*****************************************************************************// Parse a FOURIER command and put the data in a simulation object.//// Argument List://   rosCmd - The command line to be parsed//   roSim  - The simulation object//// Return Values://   TRUE  - Success//   FALSE - Failurebool  PrcNgSpice::bParseCmdOP( wxString & rosCmd, Simulation & roSim ){  return( FALSE );}//*****************************************************************************// Parse a FOURIER command and put the data in a simulation object.//// Argument List://   rosCmd - The command line to be parsed//   roSim  - The simulation object//// Return Values://   TRUE  - Success//   FALSE - Failurebool  PrcNgSpice::bParseCmdIC( wxString & rosCmd, Simulation & roSim ){  return( FALSE );}//*****************************************************************************// Parse a DC command and put the data in a simulation object.// Eg.s: .DC Vin 0.00 200.00m 25.00m//       .DC TEMP 0.00 200.00 25.00//// Argument List://   rosCmd - The command line to be parsed//   roSim  - The simulation object//// Return Values://   TRUE  - Success//   FALSE - Failurebool  PrcNgSpice::bParseCmdDC( wxString & rosCmd, Simulation & roSim ){  wxStringTokenizer  ostk1;  wxString  os1;  bool      bRtn=TRUE;  double    df1;  // Basic argument checks  ostk1.SetString( rosCmd );  if( ostk1.CountTokens( ) != 5 )             return( FALSE );  // Check command type  os1 = ostk1.GetNextToken( );  if( os1.Upper( ) != wxT(".DC") )            return( FALSE );  // Extract the sweep type: linear or log  os1 = ostk1.GetNextToken( );  if( os1.Upper( ) == wxT("TEMP") )    roSim.bSetSwpScale( 1 );  else  {    os1 = roSim.rosGetCpnt( os1 );    if( ! os1.IsEmpty( ) && roSim.bSetSrcCpnt( os1 ) )         roSim.bSetSwpScale( 0 );    else                                      bRtn = FALSE;  }  // Extract the start value  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToFlt( os1, &df1 ) ) bRtn = FALSE;  if( ! roSim.bSetSwpStart( (float) df1 ) )   bRtn = FALSE;  // Extract the stop value  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToFlt( os1, &df1 ) ) bRtn = FALSE;  if( ! roSim.bSetSwpStop( (float) df1 ) )    bRtn = FALSE;  // Extract the step increment  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToFlt( os1, &df1 ) ) bRtn = FALSE;  if( ! roSim.bSetSwpStep( (float) df1 ) )    bRtn = FALSE;  return( bRtn );}//*****************************************************************************// Parse a AC command and put the data in a simulation object.// Eg.s: .AC LIN 30 1.00K 300.00K//       .AC DEC 30 1.00K 300.00K//       .AC OCT 30 1.00K 300.00K//// Argument List://   rosCmd - The command line to be parsed//   roSim  - The simulation object//// Return Values://   TRUE  - Success//   FALSE - Failurebool  PrcNgSpice::bParseCmdAC( wxString & rosCmd, Simulation & roSim ){  wxStringTokenizer  ostk1;  wxString  os1;  bool      bRtn=TRUE;  double    df1;  long      li1;  // Basic argument checks  ostk1.SetString( rosCmd );  if( ostk1.CountTokens( ) != 5 )             return( FALSE );  // Check command type  os1 = ostk1.GetNextToken( );  if( os1.Upper( ) != wxT(".AC") )            return( FALSE );  // Extract the sweep type: linear or log  os1 = ostk1.GetNextToken( );  os1.MakeUpper( );  if(      os1 == wxT("LIN") ) roSim.bSetSwpScale( 0 );  else if( os1 == wxT("DEC") ) roSim.bSetSwpScale( 2 );  else if( os1 == wxT("OCT") ) roSim.bSetSwpScale( 3 );  else                                        bRtn = FALSE;  // Extract the step count  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToInt( os1, &li1 ) ) bRtn = FALSE;  if( ! roSim.bSetSwpStep( (float) li1 ) )    bRtn = FALSE;  // Extract the start frequency  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToFlt( os1, &df1 ) ) bRtn = FALSE;  if( ! roSim.bSetSwpStart( (float) df1 ) )   bRtn = FALSE;  // Extract the stop frequency  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToFlt( os1, &df1 ) ) bRtn = FALSE;  if( ! roSim.bSetSwpStop( (float) df1 ) )    bRtn = FALSE;  return( bRtn );}//*****************************************************************************// Parse a TRANSIENT command and put the data in a simulation object.// Eg.s: .TRAN 10.00m 100.00m 0.00 10.00m//// Argument List://   rosCmd - The command line to be parsed//   roSim  - The simulation object//// Return Values://   TRUE  - Success//   FALSE - Failurebool  PrcNgSpice::bParseCmdTR( wxString & rosCmd, Simulation & roSim ){  wxStringTokenizer  ostk1;  wxString  os1;  bool      bRtn=TRUE;  double    df1;  // Basic argument checks  ostk1.SetString( rosCmd );  if( ostk1.CountTokens( ) != 5 )               return( FALSE );  // Check command type  os1 = ostk1.GetNextToken( );  if( os1.Upper( ) != wxT(".TRAN") )            return( FALSE );  // Extract the step size  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToFlt( os1, &df1 ) )   bRtn = FALSE;  if( ! roSim.bSetSwpStep( (float) df1 ) )      bRtn = FALSE;  // Extract the stop time  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToFlt( os1, &df1 ) )   bRtn = FALSE;  if( ! roSim.bSetSwpStop( (float) df1 ) )      bRtn = FALSE;  // Extract the start time  os1 = ostk1.GetNextToken( );  if( ! ConvertType::bStrToFlt( os1, &df1 ) )   bRtn = FALSE;  if( ! roSim.bSetSwpStart( (float) df1 ) )     bRtn = FALSE;  return( bRtn );}//*****************************************************************************// Parse a PRINT command and put the data in a simulation object.//// Argument List://   rosCmd - The command line to be parsed//   roSim  - The simulation object//// Return Values://   TRUE  - Success//   FALSE - Failurebool  PrcNgSpice::bParseCmdPR( wxString & rosCmd, Simulation & roSim ){  wxStringTokenizer  ostk1;  wxString  os1;  bool      bRtn=TRUE;  size_t    szt1, szt2;  // Basic argument checks  ostk1.SetString( rosCmd );  if( ostk1.CountTokens( ) < 3 )      return( FALSE );  // Check command type  os1 = ostk1.GetNextToken( ).Left( 6 );  if( os1.Upper( ) != wxT(".PRINT") ) return( FALSE );  // Extract the start temperature  os1 = ostk1.GetNextToken( );  os1.MakeUpper( );  if(      os1 == wxT("DC")   ) roSim.bSetAnaType( Simulation::eANA_DC );  else if( os1 == wxT("AC")   ) roSim.bSetAnaType( Simulation::eANA_AC );  else if( os1 == wxT("TRAN") ) roSim.bSetAnaType( Simulation::eANA_TR );  else return( FALSE );  // Extract the parameters to derive, any complex parts and the test component  // and/or test node labels  while( ostk1.HasMoreTokens( ) )  {    // Extract the next field    os1 = ostk1.GetNextToken( );    if( os1.Length( ) < 4 ) { bRtn = FALSE; continue; }    // Extract the parameter specifier    switch( wxToupper( os1.GetChar( 0 ) ) )    {      case wxT('V'): roSim.bSetOutPar( Simulation::ePAR_VLT, TRUE ); break;      case wxT('I'): roSim.bSetOutPar( Simulation::ePAR_CUR, TRUE ); break;      case wxT('P'): roSim.bSetOutPar( Simulation::ePAR_PWR, TRUE ); break;      case wxT('R'): roSim.bSetOutPar( Simulation::ePAR_RES, TRUE ); break;      default: bRtn = FALSE; break;    }    // Extract the complex part    if( roSim.eGetAnaType( ) == Simulation::eANA_AC )    {      switch( wxToupper( os1.GetChar( 1 ) ) )      {        case wxT('M'): roSim.bSetOutCpx( Simulation::eCPX_MAG,   TRUE ); break;        case wxT('P'): roSim.bSetOutCpx( Simulation::eCPX_PHASE, TRUE ); break;        case wxT('R'): roSim.bSetOutCpx( Simulation::eCPX_REAL,  TRUE ); break;        case wxT('I'): roSim.bSetOutCpx( Simulation::eCPX_IMAG,  TRUE ); break;        case wxT('D'):          if( os1.Mid( 1, 2 ).Upper( ) == wxT("DB") )          {            roSim.bSetOutCpx( Simulation::eCPX_MAG,   TRUE );            roSim.bSetOutCpx( Simulation::eCPX_MAGDB, TRUE );            break;          }        default: bRtn = FALSE; break;      }    }    // Extract the component or node label    szt1 = os1.Index( wxT('(') );    szt2 = os1.Index( wxT(')') );    if( (int)szt1==wxNOT_FOUND || (int)szt2==wxNOT_FOUND || (szt1+1)>=szt2 )       { bRtn = FALSE; continue; }    os1 = os1.Mid( szt1+1, szt2-szt1-1 );    if( roSim.roasGetNodeLbls( ).Index( os1 ) != wxNOT_FOUND )      roSim.bAddTstNode( os1 );    else if( bMatchCpnt( roSim, os1 ) )      roSim.bAddTstCpnt( os1 );    else bRtn = FALSE;  }  return( bRtn );}//*****************************************************************************// Match a component to a set of node labels. Component voltages cannot be// specified using the component label in the Ng-Spice print statement. The two// node labels connected to the component must be specified. When parsing the// print statement the component label must be derived from the node labels.// This may not work where components are connected in parallel. The nodes are// specified in the form "<Node1>,<Node2>" eg. "1,2".//// Argument List://   rosToNodes - The nodes to match, also used to return the component label//// Return Values://   TRUE  - Success (A component with the specified nodes was found)//   FALSE - Failurebool  PrcNgSpice::bMatchCpnt( Simulation & roSim, wxString & rosToNodes ){  const wxArrayString & roasCpnts=roSim.roasGetCpnts( );  wxArrayString  oasNodes;  Component  oCpnt;  wxString   os1;  size_t     szt1;  // Argument validity checks  if( rosToNodes.IsEmpty( ) )            return( FALSE );  if( roasCpnts.GetCount( ) <= 0 )       return( FALSE );  if( rosToNodes.Freq( wxT(',') ) != 1 ) return( FALSE );  // Extract the node labels  oasNodes.Add( rosToNodes.BeforeFirst( wxT(',') ) );  oasNodes.Add( rosToNodes.AfterLast( wxT(',') ) );  // Attempt to match the nodes with a component  for( szt1=0; szt1<roasCpnts.GetCount( ); szt1++ )  {    os1 = roasCpnts.Item( szt1 );    oCpnt.bSetLine( os1 );    if( oCpnt.roasGetNodes( ) == oasNodes ) break;    oCpnt.Clear( );  }  // Was a match found?  if( ! oCpnt.bIsOk( ) )                 return( FALSE );  // A match was found  rosToNodes = oCpnt.rosGetName( );  return( TRUE );}//*****************************************************************************// Create the simulator command sequence for a DC analysis.//// Argument List://   roSim - Simulation objectvoid  PrcNgSpice::MakeCmdDC( Simulation & roSim ){  wxString  osCmdOPT;  wxString  osCmdPR;  wxString  osCmdDC;  wxString  osPar, os1;  uint      uiPar;  // Clear the field list  m_osFieldLst.Empty( );  // Create the OPTIONS command  if( roSim.iGetSwpScale( ) == PnlNgSpiceDC::eSWEEP_SRC )  {    os1 = roSim.rosGetTempC( );    osCmdOPT << wxT(".OPTIONS TEMP=") << os1 << wxT(" TNOM=") << os1;    os1 = roSim.rosGetSrcCpnt( );  }  else os1.Empty( );  // Create the DC command  osCmdDC = wxT(".DC ");  if( ! os1.IsEmpty( ) ) osCmdDC << os1 << wxT(' ');  else                   osCmdDC << wxT("TEMP ");   osCmdDC << roSim.rosGetSwpStart( ) << wxT(' ')          << roSim.rosGetSwpStop ( ) << wxT(' ')          << roSim.rosGetSwpStep ( );  roSim.bSetSrcCpnt( wxT("") );  // Create the PRINT command  osCmdPR = wxT(".PRINT DC");  for( uiPar=Simulation::ePAR_FST; uiPar<=Simulation::ePAR_LST; uiPar++ )  {    if( ! roSim.bGetOutPar( (Simulation::eParType) uiPar ) ) continue;    switch( uiPar )    {      case Simulation::ePAR_VLT: osPar = wxT("V("); break;      case Simulation::ePAR_CUR: osPar = wxT("I("); break;      case Simulation::ePAR_PWR: osPar = wxT("P("); break;      case Simulation::ePAR_RES: osPar = wxT("R("); break;      default: continue;    }    // Add any components and/or nodes to derivation list for this parameter    os1 = rosMakeArgsPR( roSim, osPar );    if( ! os1.IsEmpty( ) ) osCmdPR << os1;  }  // Add simulation commands to Simulation object  roSim.bAddSimCmd( osCmdOPT );  roSim.bAddSimCmd( osCmdPR );  roSim.bAddSimCmd( osCmdDC );}//*****************************************************************************// Create the simulator command sequence for a AC analysis.//// Argument List://   roSim - Simulation objectvoid  PrcNgSpice::MakeCmdAC( Simulation & roSim ){  wxString  osCmdOPT;  wxString  osCmdPR;  wxString  osCmdOP;  wxString  osCmdAC;  wxString  osPar, osCpx, os1;  uint      uiPar, uiCpx;  // Clear the field list  m_osFieldLst.Empty( );  // Create the OPTIONS command  os1 = roSim.rosGetTempC( );  osCmdOPT << wxT(".OPTIONS TEMP=") << os1 << wxT(" TNOM=") << os1;  // Create the AC command  osCmdAC = wxT(".AC ");  switch( roSim.iGetSwpScale( ) )  {    case 0:      osCmdAC << wxT("LIN ");      break;    case 2:      osCmdAC << wxT("DEC ");      break;    case 3:      osCmdAC << wxT("OCT ");      break;  }  osCmdAC << ( (int) roSim.fGetSwpStep( ) ) << wxT(' ')          << roSim.rosGetSwpStart( ) << wxT(' ')

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?