//************************************************************************************************** // SimnNgSpice.cpp * // ----------------- * // Started : 2008-05-07 * // Last Update : 2015-04-09 * // Copyright : (C) 2008-2016 MSWaters * //************************************************************************************************** //************************************************************************************************** // * // 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. * // * //************************************************************************************************** #include "SimnNgSpice.hpp" //************************************************************************************************** // Constructor. SimnNgSpice::SimnNgSpice( void ) : SimnBase( ) { m_eSimEng = eSIMR_NGSPICE; // Initialize all object attributes bClear( ); } //************************************************************************************************** // Destructor. SimnNgSpice::~SimnNgSpice( ) { } //************************************************************************************************** // Extract the simulator engine and return true if it's NG-Spice. // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bLoadSimEng( void ) { wxString os1; size_t sz1; // Scan the circuit description for simulator type for( sz1=0; sz1<NetList::m_osaNetLst.GetCount( ); sz1++ ) { os1 = NetList::m_osaNetLst.Item( sz1 ); if( os1.IsEmpty( ) ) continue; if( os1.Upper( ).Contains( wxT("NG-SPICE") ) ) return( true ); } return( false ); } //************************************************************************************************** // Extract all the simulator command lines from the circuit description. // // The following commands are currently detected and extracted : // // .OPTIONS // .IC // .DC // .AC // .TRANSIENT // .PRINT // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bLoadSimCmds( void ) { bool bRtn=false; wxString os1; size_t sz1; // Scan the circuit description for simulation commands for( sz1=0; sz1<NetList::m_osaNetLst.GetCount( ); sz1++ ) { os1 = NetList::m_osaNetLst.Item( sz1 ); if( os1.IsEmpty( ) ) continue; if( ! os1.StartsWith( wxT(".") ) ) continue; os1.MakeUpper( ); if( os1.StartsWith( wxT(".OPT") ) ) // OPTIONS command m_oCmdOPT.bSetString( NetList::m_osaNetLst.Item( sz1 ) ); else if( os1.StartsWith( wxT(".DC") ) ) // DC command m_oCmdDC .bSetString( NetList::m_osaNetLst.Item( sz1 ) ); else if( os1.StartsWith( wxT(".AC") ) ) // AC command m_oCmdAC .bSetString( NetList::m_osaNetLst.Item( sz1 ) ); else if( os1.StartsWith( wxT(".TR") ) ) // TRANSIENT command m_oCmdTR .bSetString( NetList::m_osaNetLst.Item( sz1 ) ); else if( os1.StartsWith( wxT(".PR") ) ) // PRINT command m_oCmdPR .bSetString( NetList::m_osaNetLst.Item( sz1 ) ); else continue; bRtn = true; } // There is no operating point command in NG-Spice, the DC command performs this function if( m_oCmdDC.m_osSource.Upper( ) == wxT("TEMP") ) m_oCmdPR.bSetAnaType( eCMD_OP ); return( bRtn ); } //************************************************************************************************** // Extract the source component. // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bLoadSigSrc( void ) { // Search for and extract a signal source component if( SimnBase::bLoadSigSrc( ) ) { // Set the NG-Spice Independent Source object (Component &) m_oCpntIndSrc = m_oCpntSwpSrc; return( true ); } // Special treatment for a DC Signal Source if( eGetAnaType( )==eCMD_DC && m_oCmdDC.m_osSource!=wxT("TEMP") ) { m_oCpntSwpSrc.bClear( ); m_oCpntSwpSrc.bSetName( m_oCmdDC.m_osSource ); return( true ); } return( false ); } //************************************************************************************************** // Clear all object attributes. // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bClear( void ) { // Clear the command object pointer attributes bClrCmds( ); // Clear the base class return( SimnBase::bClear( ) ); } //************************************************************************************************** // Clear all simulator command objects. // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bClrCmds( void ) { m_oCmdOPT.bSetDefaults( ); m_oCmdDC .bSetDefaults( ); m_oCmdAC .bSetDefaults( ); m_oCmdTR .bSetDefaults( ); m_oCmdPR .bSetDefaults( ); return( true ); } //************************************************************************************************** // Clear all test points ie. nodes and components. // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bClrTstPts( void ) { m_oCmdPR.m_osaNodes.Empty( ); m_oCmdPR.m_osaCpnts.Empty( ); return( true ); } //************************************************************************************************** // Do the current simulation settings constitute a valid simulation? // // Return Values : // true - Valid // false - Not valid bool SimnNgSpice::bValidate( void ) { // Validate the base class SimnBase::bValidate( ); if( ! m_oCmdOPT.bIsValid( ) ) SetErrMsg( m_oCmdOPT.rosGetErrMsg( ) ); if( ! m_oCmdPR .bIsValid( ) ) SetErrMsg( m_oCmdPR .rosGetErrMsg( ) ); switch( eGetAnaType( ) ) { case eCMD_OP : case eCMD_DC : if( ! m_oCmdDC.bIsValid( ) ) SetErrMsg( m_oCmdDC .rosGetErrMsg( ) ); break; case eCMD_AC : if( ! m_oCmdAC.bIsValid( ) ) SetErrMsg( m_oCmdAC .rosGetErrMsg( ) ); break; case eCMD_TR : if( ! m_oCmdTR.bIsValid( ) ) SetErrMsg( m_oCmdTR .rosGetErrMsg( ) ); break; default : SetErrMsg( wxT("No valid analysis command exists.") ); } return( bIsValid( ) ); } //************************************************************************************************** // Load the simulation information from the netlist string array into the object attributes. // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bLoad( void ) { // Envoke the base class load operations if( ! SimnBase::bLoad( ) ) return( false ); // Load the independent signal source m_oCpntIndSrc = m_oCpntSwpSrc; return( true ); } //************************************************************************************************** // Save the simulation information to the netlist string array from the object attributes. // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bSave( void ) { // Envoke the base class save operations if( ! SimnBase::bSave( ) ) return( false ); // Append the simulation command lines to the end of the file NetList::m_osaNetLst.Last( ) = wxT("********** NG-Spice Simulation Commands **********"); NetList::m_osaNetLst.Add( wxT("") ); NetList::m_osaNetLst.Add( m_oCmdOPT ); NetList::m_osaNetLst.Add( m_oCmdPR ); if( m_oCmdDC.bIsValid( ) ) NetList::m_osaNetLst.Add( m_oCmdDC ); if( m_oCmdAC.bIsValid( ) ) NetList::m_osaNetLst.Add( m_oCmdAC ); if( m_oCmdTR.bIsValid( ) ) NetList::m_osaNetLst.Add( m_oCmdTR ); NetList::m_osaNetLst.Add( wxT("") ); // Add the circuit description terminator NetList::m_osaNetLst.Add( wxT(".END") ); return( true ); } //************************************************************************************************** // Add a node to the list of test points. // // Argument List : // rosNode - The name of the node to be added to the list of test points // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bAddTstNode( const wxString & rosName ) { // Is the node name valid? if( rosName.IsEmpty( ) ) return( false ); // Is the node name already in the test node list? if( rosaGetTstNodes( ).Index( rosName ) != wxNOT_FOUND ) return( true ); // Add the node name to the list of test points m_oCmdPR.m_osaNodes.Add( rosName ); m_oCmdPR.m_osaNodes.Sort( &iStrCmpNode ); return( true ); } //************************************************************************************************** // Add a component to the list of test points. // // Argument List : // rosName - The name of the component to be added to the list of test points // // Return Values : // true - Success // false - Failure bool SimnNgSpice::bAddTstCpnt( const wxString & rosName ) { // Is the component name valid? if( rosName.IsEmpty( ) ) return( false ); // Is the component name already in the test component list? if( rosaGetTstCpnts( ).Index( rosName ) != wxNOT_FOUND ) return( true ); // Add the component name to the list of test points m_oCmdPR.m_osaCpnts.Add( rosName ); m_oCmdPR.m_osaCpnts.Sort( &iStrCmpCpnt ); return( true ); } //************************************************************************************************** // Copy the contents of a SimnGnuCap object. // // Argument List : // roSimn - A reference to a SimnGnuCap object // // Return Values : // A reference to this object SimnNgSpice & SimnNgSpice::operator = ( const SimnGnuCap & roSimn ) { (SimnBase &) *this = (SimnBase &) roSimn; m_oCmdOPT = roSimn.m_oCmdOPT; m_oCmdPR = roSimn.m_oCmdPR; m_oCpntIndSrc = roSimn.m_oCmdGEN; switch( roSimn.eGetAnaType( ) ) { case eCMD_OP : m_oCmdDC = roSimn.m_oCmdOP; break; case eCMD_DC : m_oCmdDC = roSimn.m_oCmdDC; break; case eCMD_AC : m_oCmdAC = roSimn.m_oCmdAC; break; case eCMD_TR : m_oCmdTR = roSimn.m_oCmdTR; break; default : break; } return( *this ); } //************************************************************************************************** // Print the object attributes. // // Argument List : // rosPrefix - A prefix to every line displayed (usually just spaces) void SimnNgSpice::Print( const wxString & rosPrefix ) { SimnBase::Print( rosPrefix + wxT("SimnBase::") ); m_oCmdOPT.Print( rosPrefix + wxT("m_oCmdOPT.") ); m_oCmdDC .Print( rosPrefix + wxT("m_oCmdDC.") ); m_oCmdAC .Print( rosPrefix + wxT("m_oCmdAC.") ); m_oCmdTR .Print( rosPrefix + wxT("m_oCmdTR.") ); m_oCmdPR .Print( rosPrefix + wxT("m_oCmdPR.") ); } //**************************************************************************************************