Sim: Refactor Spice code generation to a new SPICE_GENERATOR class

This commit is contained in:
Mikolaj Wielgus 2022-09-14 09:19:25 +02:00
parent e473e71ef8
commit e4c5bc6c66
24 changed files with 783 additions and 672 deletions

View File

@ -75,7 +75,7 @@ bool DIALOG_SIGNAL_LIST::TransferDataToWindow()
for( const auto& item : m_circuitModel->GetItems() ) for( const auto& item : m_circuitModel->GetItems() )
{ {
// Add all possible currents for the primitive. // Add all possible currents for the primitive.
for( const auto& currentName : item.model->GenerateSpiceCurrentNames( item.refName ) ) for( const auto& currentName : item.model->SpiceGenerator().CurrentNames( item.refName ) )
m_signals->Append( currentName ); m_signals->Append( currentName );
} }
} }

View File

@ -338,7 +338,7 @@ void DIALOG_SIM_MODEL<T>::updateModelCodeTab()
wxTextFile file; wxTextFile file;
wxString text; wxString text;
text << curModel().GenerateSpicePreview( modelName ); text << curModel().SpiceGenerator().Preview( modelName );
text << "\n"; text << "\n";
text << "--- FILE SOURCE (" << path << ") ---\n"; text << "--- FILE SOURCE (" << path << ") ---\n";
text << "\n"; text << "\n";
@ -356,7 +356,7 @@ void DIALOG_SIM_MODEL<T>::updateModelCodeTab()
} }
} }
else else
m_codePreview->SetText( curModel().GenerateSpicePreview( modelName ) ); m_codePreview->SetText( curModel().SpiceGenerator().Preview( modelName ) );
m_codePreview->SetEditable( false ); // ??? m_codePreview->SetEditable( false ); // ???
m_wasCodePreviewUpdated = true; m_wasCodePreviewUpdated = true;

View File

@ -177,7 +177,7 @@ wxString NETLIST_EXPORTER_SPICE::GetItemName( const wxString& aRefName ) const
if( it == spiceItems.end() ) if( it == spiceItems.end() )
return ""; return "";
return it->model->GenerateSpiceItemName( aRefName ); return it->model->SpiceGenerator().ItemName( aRefName );
} }
@ -425,7 +425,7 @@ void NETLIST_EXPORTER_SPICE::writeModels( OUTPUTFORMATTER& aFormatter )
if( !item.model->IsEnabled() ) if( !item.model->IsEnabled() )
continue; continue;
aFormatter.Print( 0, "%s", TO_UTF8( item.model->GenerateSpiceModelLine( item.modelName ) ) ); aFormatter.Print( 0, "%s", TO_UTF8( item.model->SpiceGenerator().ModelLine( item.modelName ) ) );
} }
} }
@ -438,10 +438,10 @@ void NETLIST_EXPORTER_SPICE::writeItems( OUTPUTFORMATTER& aFormatter )
continue; continue;
aFormatter.Print( 0, "%s", aFormatter.Print( 0, "%s",
TO_UTF8( item.model->GenerateSpiceItemLine( item.refName, TO_UTF8( item.model->SpiceGenerator().ItemLine( item.refName,
item.modelName, item.modelName,
item.pinNumbers, item.pinNumbers,
item.pinNetNames ) ) ); item.pinNetNames ) ) );
} }
} }

View File

@ -42,6 +42,7 @@
#include <iterator> #include <iterator>
using SPICE_GENERATOR = SIM_MODEL::SPICE_GENERATOR;
using DEVICE_TYPE = SIM_MODEL::DEVICE_TYPE_; using DEVICE_TYPE = SIM_MODEL::DEVICE_TYPE_;
using TYPE = SIM_MODEL::TYPE; using TYPE = SIM_MODEL::TYPE;
@ -83,36 +84,220 @@ namespace SIM_MODEL_SPICE_PARSER
} }
wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
{
LOCALE_IO toggle;
if( !m_model.HasSpiceNonInstanceOverrides() && !m_model.requiresSpiceModelLine() )
return "";
wxString result = "";
result << wxString::Format( ".model %s ", aModelName );
size_t indentLength = result.Length();
result << wxString::Format( "%s \n", m_model.GetSpiceInfo().modelType );
for( const PARAM& param : m_model.GetParams() )
{
if( param.info.isSpiceInstanceParam )
continue;
wxString name = ( param.info.spiceModelName == "" ) ?
param.info.name : param.info.spiceModelName;
wxString value = param.value->ToSpiceString();
if( value == "" )
continue;
result << wxString::Format( "+%s%s=%s\n", wxString( ' ', indentLength - 1 ), name, value );
}
return result;
}
wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName,
const wxString& aModelName ) const
{
// Use linear symbol pin numbers enumeration. Used in model preview.
std::vector<wxString> pinNumbers;
for( int i = 0; i < m_model.GetPinCount(); ++i )
pinNumbers.push_back( wxString::FromCDouble( i + 1 ) );
return ItemLine( aRefName, aModelName, pinNumbers );
}
wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers ) const
{
std::vector<wxString> pinNetNames;
for( const PIN& pin : GetPins() )
pinNetNames.push_back( pin.name );
return ItemLine( aRefName, aModelName, aSymbolPinNumbers, pinNetNames );
}
wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString result;
result << ItemName( aRefName );
result << ItemPins( aRefName, aModelName, aSymbolPinNumbers, aPinNetNames );
result << ItemModelName( aModelName );
result << ItemParams();
result << "\n";
return result;
}
wxString SPICE_GENERATOR::ItemName( const wxString& aRefName ) const
{
if( aRefName != "" && aRefName.StartsWith( m_model.GetSpiceInfo().itemType ) )
return aRefName;
else
return m_model.GetSpiceInfo().itemType + aRefName;
}
wxString SPICE_GENERATOR::ItemPins( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString result;
int ncCounter = 0;
for( const PIN& pin : GetPins() )
{
auto it = std::find( aSymbolPinNumbers.begin(), aSymbolPinNumbers.end(),
pin.symbolPinNumber );
if( it == aSymbolPinNumbers.end() )
{
LOCALE_IO toggle;
result << wxString::Format( " NC-%s-%u", aRefName, ncCounter++ );
}
else
{
long symbolPinIndex = std::distance( aSymbolPinNumbers.begin(), it );
result << " " << aPinNetNames.at( symbolPinIndex );
}
}
return result;
}
wxString SPICE_GENERATOR::ItemModelName( const wxString& aModelName ) const
{
return " " + aModelName;
}
wxString SPICE_GENERATOR::ItemParams() const
{
wxString result;
for( const PARAM& param : GetInstanceParams() )
{
wxString name = ( param.info.spiceInstanceName == "" ) ?
param.info.name : param.info.spiceInstanceName;
wxString value = param.value->ToSpiceString();
if( value != "" )
result << " " << name << "=" << value;
}
return result;
}
wxString SPICE_GENERATOR::TuningLine( const wxString& aSymbol ) const
{
// TODO.
return "";
}
std::vector<wxString> SPICE_GENERATOR::CurrentNames( const wxString& aRefName ) const
{
LOCALE_IO toggle;
return { wxString::Format( "I(%s)", ItemName( aRefName ) ) };
}
wxString SPICE_GENERATOR::Preview( const wxString& aModelName ) const
{
wxString spiceCode = ModelLine( aModelName );
if( spiceCode == "" )
spiceCode = m_model.m_spiceCode;
if( spiceCode == "" && m_model.GetBaseModel() )
spiceCode = m_model.GetBaseModel()->m_spiceCode;
wxString itemLine = ItemLine( "", aModelName );
if( spiceCode != "" )
spiceCode << "\n";
spiceCode << itemLine;
return spiceCode.Trim();
}
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> SPICE_GENERATOR::GetInstanceParams() const
{
std::vector<std::reference_wrapper<const PARAM>> instanceParams;
for( const PARAM& param : m_model.GetParams() )
{
if( param.info.isSpiceInstanceParam )
instanceParams.emplace_back( param );
}
return instanceParams;
}
SIM_MODEL::DEVICE_INFO SIM_MODEL::DeviceTypeInfo( DEVICE_TYPE_ aDeviceType ) SIM_MODEL::DEVICE_INFO SIM_MODEL::DeviceTypeInfo( DEVICE_TYPE_ aDeviceType )
{ {
switch( aDeviceType ) switch( aDeviceType )
{ {
case DEVICE_TYPE_::NONE: return { "", "" }; case DEVICE_TYPE_::NONE: return { "", "" };
case DEVICE_TYPE_::R: return { "R", "Resistor" }; case DEVICE_TYPE_::R: return { "R", "Resistor" };
case DEVICE_TYPE_::C: return { "C", "Capacitor" }; case DEVICE_TYPE_::C: return { "C", "Capacitor" };
case DEVICE_TYPE_::L: return { "L", "Inductor" }; case DEVICE_TYPE_::L: return { "L", "Inductor" };
case DEVICE_TYPE_::TLINE: return { "TLINE", "Transmission Line" }; case DEVICE_TYPE_::TLINE: return { "TLINE", "Transmission Line" };
case DEVICE_TYPE_::SW: return { "SW", "Switch" }; case DEVICE_TYPE_::SW: return { "SW", "Switch" };
case DEVICE_TYPE_::D: return { "D", "Diode" }; case DEVICE_TYPE_::D: return { "D", "Diode" };
case DEVICE_TYPE_::NPN: return { "NPN", "NPN BJT" }; case DEVICE_TYPE_::NPN: return { "NPN", "NPN BJT" };
case DEVICE_TYPE_::PNP: return { "PNP", "PNP BJT" }; case DEVICE_TYPE_::PNP: return { "PNP", "PNP BJT" };
case DEVICE_TYPE_::NJFET: return { "NJFET", "N-channel JFET" }; case DEVICE_TYPE_::NJFET: return { "NJFET", "N-channel JFET" };
case DEVICE_TYPE_::PJFET: return { "PJFET", "P-channel JFET" }; case DEVICE_TYPE_::PJFET: return { "PJFET", "P-channel JFET" };
case DEVICE_TYPE_::NMOS: return { "NMOS", "N-channel MOSFET" }; case DEVICE_TYPE_::NMOS: return { "NMOS", "N-channel MOSFET" };
case DEVICE_TYPE_::PMOS: return { "PMOS", "P-channel MOSFET" }; case DEVICE_TYPE_::PMOS: return { "PMOS", "P-channel MOSFET" };
case DEVICE_TYPE_::NMES: return { "NMES", "N-channel MESFET" }; case DEVICE_TYPE_::NMES: return { "NMES", "N-channel MESFET" };
case DEVICE_TYPE_::PMES: return { "PMES", "P-channel MESFET" }; case DEVICE_TYPE_::PMES: return { "PMES", "P-channel MESFET" };
case DEVICE_TYPE_::V: return { "V", "Voltage Source" }; case DEVICE_TYPE_::V: return { "V", "Voltage Source" };
case DEVICE_TYPE_::I: return { "I", "Current Source" }; case DEVICE_TYPE_::I: return { "I", "Current Source" };
case DEVICE_TYPE_::SUBCKT: return { "SUBCKT", "Subcircuit" }; case DEVICE_TYPE_::SUBCKT: return { "SUBCKT", "Subcircuit" };
case DEVICE_TYPE_::XSPICE: return { "XSPICE", "XSPICE Code Model" }; case DEVICE_TYPE_::XSPICE: return { "XSPICE", "XSPICE Code Model" };
case DEVICE_TYPE_::SPICE: return { "SPICE", "Raw Spice Element" }; case DEVICE_TYPE_::SPICE: return { "SPICE", "Raw Spice Element" };
case DEVICE_TYPE_::_ENUM_END: break; case DEVICE_TYPE_::_ENUM_END: break;
} }
wxFAIL; wxFAIL;
@ -907,123 +1092,6 @@ void SIM_MODEL::ReadSpiceCode( const wxString& aSpiceCode )
} }
wxString SIM_MODEL::GenerateSpiceModelLine( const wxString& aModelName ) const
{
LOCALE_IO toggle;
if( !HasSpiceNonInstanceOverrides() && !requiresSpiceModelLine() )
return "";
wxString result = "";
result << wxString::Format( ".model %s ", aModelName );
size_t indentLength = result.Length();
result << wxString::Format( "%s \n", GetSpiceInfo().modelType );
for( const PARAM& param : GetParams() )
{
if( param.info.isSpiceInstanceParam )
continue;
wxString name = ( param.info.spiceModelName == "" ) ?
param.info.name : param.info.spiceModelName;
wxString value = param.value->ToSpiceString();
if( value == "" )
continue;
result << wxString::Format( "+%s%s=%s\n", wxString( ' ', indentLength - 1 ), name, value );
}
return result;
}
wxString SIM_MODEL::GenerateSpiceItemName( const wxString& aRefName ) const
{
if( aRefName != "" && aRefName.StartsWith( GetSpiceInfo().itemType ) )
return aRefName;
else
return GetSpiceInfo().itemType + aRefName;
}
wxString SIM_MODEL::GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName ) const
{
// Use linear symbol pin numbers enumeration. Used in model preview.
std::vector<wxString> pinNumbers;
for( int i = 0; i < GetPinCount(); ++i )
pinNumbers.push_back( wxString::FromCDouble( i + 1 ) );
return GenerateSpiceItemLine( aRefName, aModelName, pinNumbers );
}
wxString SIM_MODEL::GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers ) const
{
std::vector<wxString> pinNetNames;
for( const PIN& pin : GetPins() )
pinNetNames.push_back( pin.name );
return GenerateSpiceItemLine( aRefName, aModelName, aSymbolPinNumbers, pinNetNames );
}
wxString SIM_MODEL::GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString result;
result << GenerateSpiceItemName( aRefName );
result << GenerateSpiceItemPins( aRefName, aModelName, aSymbolPinNumbers, aPinNetNames );
result << GenerateSpiceItemModelName( aModelName );
result << GenerateSpiceItemParams();
result << "\n";
return result;
}
wxString SIM_MODEL::GenerateSpiceTuningLine( const wxString& aSymbol ) const
{
// TODO.
return "";
}
wxString SIM_MODEL::GenerateSpicePreview( const wxString& aModelName ) const
{
wxString spiceCode = GenerateSpiceModelLine( aModelName );
if( spiceCode == "" )
spiceCode = m_spiceCode;
if( spiceCode == "" && GetBaseModel() )
spiceCode = GetBaseModel()->m_spiceCode;
wxString itemLine = GenerateSpiceItemLine( "", aModelName );
if( spiceCode != "" )
spiceCode << "\n";
spiceCode << itemLine;
return spiceCode.Trim();
}
std::vector<wxString> SIM_MODEL::GenerateSpiceCurrentNames( const wxString& aRefName ) const
{
LOCALE_IO toggle;
return { wxString::Format( "I(%s)", GenerateSpiceItemName( aRefName ) ) };
}
void SIM_MODEL::AddPin( const PIN& aPin ) void SIM_MODEL::AddPin( const PIN& aPin )
{ {
m_pins.push_back( aPin ); m_pins.push_back( aPin );
@ -1096,20 +1164,6 @@ std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> SIM_MODEL::GetParams
} }
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> SIM_MODEL::GetSpiceInstanceParams() const
{
std::vector<std::reference_wrapper<const PARAM>> spiceInstanceParams;
for( const PARAM& param : GetParams() )
{
if( param.info.isSpiceInstanceParam )
spiceInstanceParams.emplace_back( param );
}
return spiceInstanceParams;
}
const SIM_MODEL::PARAM& SIM_MODEL::GetUnderlyingParam( unsigned aParamIndex ) const const SIM_MODEL::PARAM& SIM_MODEL::GetUnderlyingParam( unsigned aParamIndex ) const
{ {
return m_params.at( aParamIndex ); return m_params.at( aParamIndex );
@ -1190,8 +1244,12 @@ bool SIM_MODEL::HasSpiceNonInstanceOverrides() const
} }
SIM_MODEL::SIM_MODEL( TYPE aType ) : m_baseModel( nullptr ), m_type( aType ), SIM_MODEL::SIM_MODEL( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ) :
m_isEnabled( true ), m_isInferred( false ) m_spiceGenerator( std::move( aSpiceGenerator ) ),
m_baseModel( nullptr ),
m_type( aType ),
m_isEnabled( true ),
m_isInferred( false )
{ {
} }
@ -1238,59 +1296,6 @@ void SIM_MODEL::WriteInferredDataFields( std::vector<T>& aFields, const wxString
} }
wxString SIM_MODEL::GenerateSpiceItemPins( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString result;
int ncCounter = 0;
for( const PIN& pin : GetSpicePins() )
{
auto it = std::find( aSymbolPinNumbers.begin(), aSymbolPinNumbers.end(),
pin.symbolPinNumber );
if( it == aSymbolPinNumbers.end() )
{
LOCALE_IO toggle;
result << wxString::Format( " NC-%s-%u", aRefName, ncCounter++ );
}
else
{
long symbolPinIndex = std::distance( aSymbolPinNumbers.begin(), it );
result << " " << aPinNetNames.at( symbolPinIndex );
}
}
return result;
}
wxString SIM_MODEL::GenerateSpiceItemModelName( const wxString& aModelName ) const
{
return " " + aModelName;
}
wxString SIM_MODEL::GenerateSpiceItemParams() const
{
wxString result;
for( const PARAM& param : GetSpiceInstanceParams() )
{
wxString name = ( param.info.spiceInstanceName == "" ) ?
param.info.name : param.info.spiceInstanceName;
wxString value = param.value->ToSpiceString();
if( value != "" )
result << " " << name << "=" << value;
}
return result;
}
wxString SIM_MODEL::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const wxString SIM_MODEL::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const
{ {
wxString result; wxString result;

View File

@ -108,6 +108,50 @@ namespace SIM_MODEL_GRAMMAR
class SIM_MODEL class SIM_MODEL
{ {
public: public:
struct PIN;
struct PARAM;
class SPICE_GENERATOR
{
public:
SPICE_GENERATOR( const SIM_MODEL& aModel ) : m_model( aModel ) {}
virtual wxString ModelLine( const wxString& aModelName ) const;
wxString ItemLine( const wxString& aRefName,
const wxString& aModelName ) const;
wxString ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers ) const;
virtual wxString ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const;
virtual wxString ItemName( const wxString& aRefName ) const;
virtual wxString ItemPins( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const;
virtual wxString ItemModelName( const wxString& aModelName ) const;
virtual wxString ItemParams() const;
virtual wxString TuningLine( const wxString& aSymbol ) const;
virtual std::vector<wxString> CurrentNames( const wxString& aRefName ) const;
virtual wxString Preview( const wxString& aModelName ) const;
protected:
virtual std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> GetPins() const
{
return m_model.GetPins();
}
std::vector<std::reference_wrapper<const SIM_MODEL::PARAM>> GetInstanceParams() const;
const SIM_MODEL& m_model;
};
static constexpr auto REFERENCE_FIELD = "Reference"; static constexpr auto REFERENCE_FIELD = "Reference";
static constexpr auto VALUE_FIELD = "Value"; static constexpr auto VALUE_FIELD = "Value";
@ -463,6 +507,8 @@ public:
static void SetFieldValue( std::vector<T>& aFields, const wxString& aFieldName, static void SetFieldValue( std::vector<T>& aFields, const wxString& aFieldName,
const wxString& aValue ); const wxString& aValue );
const SPICE_GENERATOR& SpiceGenerator() const { return *m_spiceGenerator; }
// Move semantics. // Move semantics.
// Rule of five. // Rule of five.
@ -472,7 +518,6 @@ public:
SIM_MODEL( SIM_MODEL&& aOther ) = default; SIM_MODEL( SIM_MODEL&& aOther ) = default;
SIM_MODEL& operator=(SIM_MODEL&& aOther ) = delete; SIM_MODEL& operator=(SIM_MODEL&& aOther ) = delete;
virtual void ReadSpiceCode( const wxString& aSpiceCode ); virtual void ReadSpiceCode( const wxString& aSpiceCode );
template <typename T> template <typename T>
@ -493,23 +538,7 @@ public:
virtual bool HasToIncludeSpiceLibrary() const { return GetBaseModel() && !HasOverrides(); } virtual bool HasToIncludeSpiceLibrary() const { return GetBaseModel() && !HasOverrides(); }
virtual wxString GenerateSpiceModelLine( const wxString& aModelName ) const;
virtual wxString GenerateSpiceItemName( const wxString& aRefName ) const;
wxString GenerateSpiceItemLine( const wxString& aRefName, const wxString& aModelName ) const;
wxString GenerateSpiceItemLine( const wxString& aRefName, const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers ) const;
virtual wxString GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const;
virtual wxString GenerateSpiceTuningLine( const wxString& aSymbol ) const;
virtual wxString GenerateSpicePreview( const wxString& aModelName ) const;
SPICE_INFO GetSpiceInfo() const { return SpiceInfo( GetType() ); } SPICE_INFO GetSpiceInfo() const { return SpiceInfo( GetType() ); }
virtual std::vector<wxString> GenerateSpiceCurrentNames( const wxString& aRefName ) const;
void AddPin( const PIN& aPin ); void AddPin( const PIN& aPin );
int FindModelPinIndex( const wxString& aSymbolPinNumber ); int FindModelPinIndex( const wxString& aSymbolPinNumber );
@ -541,7 +570,6 @@ public:
const PARAM* FindParam( const wxString& aParamName ) const; const PARAM* FindParam( const wxString& aParamName ) const;
std::vector<std::reference_wrapper<const PARAM>> GetParams() const; std::vector<std::reference_wrapper<const PARAM>> GetParams() const;
std::vector<std::reference_wrapper<const PARAM>> GetSpiceInstanceParams() const;
const PARAM& GetUnderlyingParam( unsigned aParamIndex ) const; // Return the actual parameter. const PARAM& GetUnderlyingParam( unsigned aParamIndex ) const; // Return the actual parameter.
const PARAM& GetBaseParam( unsigned aParamIndex ) const; // Always return base parameter if it exists. const PARAM& GetBaseParam( unsigned aParamIndex ) const; // Always return base parameter if it exists.
@ -564,20 +592,14 @@ public:
bool IsEnabled() const { return m_isEnabled; } bool IsEnabled() const { return m_isEnabled; }
protected: protected:
SIM_MODEL( TYPE aType ); SIM_MODEL( TYPE aType ) : SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) ) {}
SIM_MODEL( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator );
virtual void CreatePins( unsigned aSymbolPinCount ); virtual void CreatePins( unsigned aSymbolPinCount );
template <typename T> template <typename T>
void WriteInferredDataFields( std::vector<T>& aFields, const wxString& aValue ) const; void WriteInferredDataFields( std::vector<T>& aFields, const wxString& aValue ) const;
virtual wxString GenerateSpiceItemPins( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const;
virtual wxString GenerateSpiceItemModelName( const wxString& aModelName ) const;
virtual wxString GenerateSpiceItemParams() const;
virtual wxString GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const; virtual wxString GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const;
wxString GenerateParamsField( const wxString& aPairSeparator ) const; wxString GenerateParamsField( const wxString& aPairSeparator ) const;
@ -586,11 +608,6 @@ protected:
void ParsePinsField( unsigned aSymbolPinCount, const wxString& aPinsField ); void ParsePinsField( unsigned aSymbolPinCount, const wxString& aPinsField );
void ParseDisabledField( const wxString& aDisabledField ); void ParseDisabledField( const wxString& aDisabledField );
virtual std::vector<std::reference_wrapper<const PIN>> GetSpicePins() const
{
return GetPins();
}
virtual bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, virtual bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue,
SIM_VALUE_GRAMMAR::NOTATION aNotation SIM_VALUE_GRAMMAR::NOTATION aNotation
= SIM_VALUE_GRAMMAR::NOTATION::SPICE ); = SIM_VALUE_GRAMMAR::NOTATION::SPICE );
@ -629,6 +646,7 @@ private:
virtual std::vector<wxString> getPinNames() const { return {}; } virtual std::vector<wxString> getPinNames() const { return {}; }
std::unique_ptr<SPICE_GENERATOR> m_spiceGenerator;
const SIM_MODEL* m_baseModel; const SIM_MODEL* m_baseModel;
const TYPE m_type; const TYPE m_type;

View File

@ -25,10 +25,54 @@
#include <sim/sim_model_behavioral.h> #include <sim/sim_model_behavioral.h>
#include <locale_io.h> #include <locale_io.h>
using SPICE_GENERATOR = SIM_MODEL_BEHAVIORAL::SPICE_GENERATOR;
SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType )
: SIM_MODEL( aType ), wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
m_isInferred( false ) {
return "";
}
wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
LOCALE_IO toggle;
switch( m_model.GetType() )
{
case TYPE::R_BEHAVIORAL:
case TYPE::C_BEHAVIORAL:
case TYPE::L_BEHAVIORAL:
return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName,
m_model.GetParam( 0 ).value->ToString(),
aSymbolPinNumbers,
aPinNetNames );
case TYPE::V_BEHAVIORAL:
return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName,
wxString::Format( "V=%s", m_model.GetParam( 0 ).value->ToString() ),
aSymbolPinNumbers,
aPinNetNames );
case TYPE::I_BEHAVIORAL:
return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName,
wxString::Format( "I=%s", m_model.GetParam( 0 ).value->ToString() ),
aSymbolPinNumbers,
aPinNetNames );
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_BEHAVIORAL" );
return "";
}
}
SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType ) :
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) ),
m_isInferred( false )
{ {
static PARAM::INFO resistor = makeParams( "r", "Expression for resistance", "Ω" ); static PARAM::INFO resistor = makeParams( "r", "Expression for resistance", "Ω" );
static PARAM::INFO capacitor = makeParams( "c", "Expression for capacitance", "F" ); static PARAM::INFO capacitor = makeParams( "c", "Expression for capacitance", "F" );
@ -87,46 +131,6 @@ void SIM_MODEL_BEHAVIORAL::WriteDataLibFields( std::vector<LIB_FIELD>& aFields )
} }
wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceModelLine( const wxString& aModelName ) const
{
return "";
}
wxString SIM_MODEL_BEHAVIORAL::GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
LOCALE_IO toggle;
switch( GetType() )
{
case TYPE::R_BEHAVIORAL:
case TYPE::C_BEHAVIORAL:
case TYPE::L_BEHAVIORAL:
return SIM_MODEL::GenerateSpiceItemLine( aRefName,
GetParam( 0 ).value->ToString(),
aSymbolPinNumbers,
aPinNetNames );
case TYPE::V_BEHAVIORAL:
return SIM_MODEL::GenerateSpiceItemLine( aRefName,
wxString::Format( "V=%s", GetParam( 0 ).value->ToString() ), aSymbolPinNumbers,
aPinNetNames );
case TYPE::I_BEHAVIORAL:
return SIM_MODEL::GenerateSpiceItemLine( aRefName,
wxString::Format( "I=%s", GetParam( 0 ).value->ToString() ), aSymbolPinNumbers,
aPinNetNames );
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_BEHAVIORAL" );
return "";
}
}
bool SIM_MODEL_BEHAVIORAL::parseValueField( const wxString& aValueField ) bool SIM_MODEL_BEHAVIORAL::parseValueField( const wxString& aValueField )
{ {
wxString expr = aValueField; wxString expr = aValueField;

View File

@ -31,6 +31,19 @@
class SIM_MODEL_BEHAVIORAL : public SIM_MODEL class SIM_MODEL_BEHAVIORAL : public SIM_MODEL
{ {
public: public:
class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR
{
public:
using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR;
wxString ModelLine( const wxString& aModelName ) const override;
wxString ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const override;
};
SIM_MODEL_BEHAVIORAL( TYPE aType ); SIM_MODEL_BEHAVIORAL( TYPE aType );
void ReadDataSchFields( unsigned aSymbolPinCount, void ReadDataSchFields( unsigned aSymbolPinCount,
@ -41,12 +54,6 @@ public:
void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override; void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override;
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override; void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
wxString GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const override;
private: private:
bool parseValueField( const wxString& aValueField ); bool parseValueField( const wxString& aValueField );
@ -61,6 +68,7 @@ private:
static PARAM::INFO makeParams( wxString aName, wxString aDescription, wxString aUnit ); static PARAM::INFO makeParams( wxString aName, wxString aDescription, wxString aUnit );
bool m_isInferred; bool m_isInferred;
}; };

View File

@ -26,10 +26,33 @@
#include <pegtl.hpp> #include <pegtl.hpp>
#include <pegtl/contrib/parse_tree.hpp> #include <pegtl/contrib/parse_tree.hpp>
using SPICE_GENERATOR = SIM_MODEL_IDEAL::SPICE_GENERATOR;
SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType )
: SIM_MODEL( aType ), wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
m_isInferred( false ) {
return "";
}
wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString valueStr = m_model.GetParam( 0 ).value->ToString( SIM_VALUE::NOTATION::SPICE );
if( valueStr != "" )
return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, valueStr, aSymbolPinNumbers,
aPinNetNames );
else
return "";
}
SIM_MODEL_IDEAL::SIM_MODEL_IDEAL( TYPE aType ) :
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) ),
m_isInferred( false )
{ {
static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "Ω" ); static PARAM::INFO resistor = makeParamInfo( "r", "Resistance", "Ω" );
static PARAM::INFO capacitor = makeParamInfo( "c", "Capacitance", "F" ); static PARAM::INFO capacitor = makeParamInfo( "c", "Capacitance", "F" );
@ -84,26 +107,6 @@ void SIM_MODEL_IDEAL::WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) cons
} }
wxString SIM_MODEL_IDEAL::GenerateSpiceModelLine( const wxString& aModelName ) const
{
return "";
}
wxString SIM_MODEL_IDEAL::GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString valueStr = GetParam( 0 ).value->ToString( SIM_VALUE::NOTATION::SPICE );
if( valueStr != "" )
return SIM_MODEL::GenerateSpiceItemLine( aRefName, valueStr, aSymbolPinNumbers, aPinNetNames );
else
return "";
}
template <typename T> template <typename T>
void SIM_MODEL_IDEAL::inferredWriteDataFields( std::vector<T>& aFields ) const void SIM_MODEL_IDEAL::inferredWriteDataFields( std::vector<T>& aFields ) const
{ {

View File

@ -31,6 +31,19 @@
class SIM_MODEL_IDEAL : public SIM_MODEL class SIM_MODEL_IDEAL : public SIM_MODEL
{ {
public: public:
class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR
{
public:
using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR;
wxString ModelLine( const wxString& aModelName ) const override;
wxString ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const override;
};
SIM_MODEL_IDEAL( TYPE aType ); SIM_MODEL_IDEAL( TYPE aType );
void ReadDataSchFields( unsigned aSymbolPinCount, const std::vector<SCH_FIELD>* aFields ) override; void ReadDataSchFields( unsigned aSymbolPinCount, const std::vector<SCH_FIELD>* aFields ) override;
@ -39,13 +52,6 @@ public:
void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override; void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override;
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override; void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
wxString GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const override;
private: private:
template <typename T> template <typename T>
void inferredWriteDataFields( std::vector<T>& aFields ) const; void inferredWriteDataFields( std::vector<T>& aFields ) const;

View File

@ -24,8 +24,22 @@
#include <sim/sim_model_mutual_inductor.h> #include <sim/sim_model_mutual_inductor.h>
using SPICE_GENERATOR = SIM_MODEL_MUTUAL_INDUCTOR::SPICE_GENERATOR;
SIM_MODEL_MUTUAL_INDUCTOR::SIM_MODEL_MUTUAL_INDUCTOR() : SIM_MODEL( SIM_MODEL::TYPE::L_MUTUAL )
wxString SPICE_GENERATOR::ItemParams() const
{
wxString result;
for( const PARAM& param : GetInstanceParams() )
result << " " << param.value->ToSpiceString();
return result;
}
SIM_MODEL_MUTUAL_INDUCTOR::SIM_MODEL_MUTUAL_INDUCTOR() :
SIM_MODEL( SIM_MODEL::TYPE::L_MUTUAL, std::make_unique<SPICE_GENERATOR>( *this ) )
{ {
static std::vector<PARAM::INFO> paramInfos = makeParamInfos(); static std::vector<PARAM::INFO> paramInfos = makeParamInfos();
@ -34,17 +48,6 @@ SIM_MODEL_MUTUAL_INDUCTOR::SIM_MODEL_MUTUAL_INDUCTOR() : SIM_MODEL( SIM_MODEL::T
} }
wxString SIM_MODEL_MUTUAL_INDUCTOR::GenerateSpiceItemParams() const
{
wxString result;
for( const PARAM& param : GetSpiceInstanceParams() )
result << param.value->ToSimpleString() << " ";
return result;
}
const std::vector<SIM_MODEL::PARAM::INFO> SIM_MODEL_MUTUAL_INDUCTOR::makeParamInfos() const std::vector<SIM_MODEL::PARAM::INFO> SIM_MODEL_MUTUAL_INDUCTOR::makeParamInfos()
{ {
std::vector<PARAM::INFO> paramInfos; std::vector<PARAM::INFO> paramInfos;

View File

@ -31,9 +31,15 @@
class SIM_MODEL_MUTUAL_INDUCTOR : public SIM_MODEL class SIM_MODEL_MUTUAL_INDUCTOR : public SIM_MODEL
{ {
public: public:
SIM_MODEL_MUTUAL_INDUCTOR(); class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR
{
public:
using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR;
wxString GenerateSpiceItemParams() const override; wxString ItemParams() const override;
};
SIM_MODEL_MUTUAL_INDUCTOR();
private: private:
static const std::vector<PARAM::INFO> makeParamInfos(); static const std::vector<PARAM::INFO> makeParamInfos();

View File

@ -25,34 +25,15 @@
#include <sim/sim_model_ngspice.h> #include <sim/sim_model_ngspice.h>
#include <locale_io.h> #include <locale_io.h>
using SPICE_GENERATOR = SIM_MODEL_NGSPICE::SPICE_GENERATOR;
using TYPE = SIM_MODEL::TYPE; using TYPE = SIM_MODEL::TYPE;
SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType ) std::vector<wxString> SPICE_GENERATOR::CurrentNames( const wxString& aRefName ) const
: SIM_MODEL( aType )
{
const MODEL_INFO& modelInfo = ModelInfo( getModelType() );
for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams )
{
// For now, only the geometry parameters.
if( paramInfo.category == SIM_MODEL::PARAM::CATEGORY::PRINCIPAL
|| paramInfo.category == SIM_MODEL::PARAM::CATEGORY::GEOMETRY )
{
AddParam( paramInfo, getIsOtherVariant() );
}
}
for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.modelParams )
AddParam( paramInfo, getIsOtherVariant() );
}
std::vector<wxString> SIM_MODEL_NGSPICE::GenerateSpiceCurrentNames( const wxString& aRefName ) const
{ {
LOCALE_IO toggle; LOCALE_IO toggle;
switch( TypeInfo( GetType() ).deviceType ) switch( m_model.GetTypeInfo().deviceType )
{ {
case DEVICE_TYPE_::NPN: case DEVICE_TYPE_::NPN:
case DEVICE_TYPE_::PNP: case DEVICE_TYPE_::PNP:
@ -74,7 +55,7 @@ std::vector<wxString> SIM_MODEL_NGSPICE::GenerateSpiceCurrentNames( const wxStri
case DEVICE_TYPE_::C: case DEVICE_TYPE_::C:
case DEVICE_TYPE_::L: case DEVICE_TYPE_::L:
case DEVICE_TYPE_::D: case DEVICE_TYPE_::D:
return SIM_MODEL::GenerateSpiceCurrentNames( aRefName ); return CurrentNames( aRefName );
default: default:
wxFAIL_MSG( "Unhandled model device type in SIM_MODEL_NGSPICE" ); wxFAIL_MSG( "Unhandled model device type in SIM_MODEL_NGSPICE" );
@ -83,6 +64,26 @@ std::vector<wxString> SIM_MODEL_NGSPICE::GenerateSpiceCurrentNames( const wxStri
} }
SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType )
: SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) )
{
const MODEL_INFO& modelInfo = ModelInfo( getModelType() );
for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.instanceParams )
{
// For now, only the geometry parameters.
if( paramInfo.category == SIM_MODEL::PARAM::CATEGORY::PRINCIPAL
|| paramInfo.category == SIM_MODEL::PARAM::CATEGORY::GEOMETRY )
{
AddParam( paramInfo, getIsOtherVariant() );
}
}
for( const SIM_MODEL::PARAM::INFO& paramInfo : modelInfo.modelParams )
AddParam( paramInfo, getIsOtherVariant() );
}
bool SIM_MODEL_NGSPICE::SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, bool SIM_MODEL_NGSPICE::SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue,
SIM_VALUE_GRAMMAR::NOTATION aNotation ) SIM_VALUE_GRAMMAR::NOTATION aNotation )
{ {

View File

@ -33,9 +33,16 @@ class SIM_MODEL_NGSPICE : public SIM_MODEL
public: public:
friend struct MODEL_INFO_MAP; friend struct MODEL_INFO_MAP;
SIM_MODEL_NGSPICE( TYPE aType ); class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR
{
public:
using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR;
std::vector<wxString> GenerateSpiceCurrentNames( const wxString& aRefName ) const override; std::vector<wxString> CurrentNames( const wxString& aRefName ) const override;
};
SIM_MODEL_NGSPICE( TYPE aType );
bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue,
SIM_VALUE_GRAMMAR::NOTATION aNotation ) override; SIM_VALUE_GRAMMAR::NOTATION aNotation ) override;

View File

@ -27,6 +27,8 @@
#include <pegtl/contrib/parse_tree.hpp> #include <pegtl/contrib/parse_tree.hpp>
#include <locale_io.h> #include <locale_io.h>
using SPICE_GENERATOR = SIM_MODEL_SOURCE::SPICE_GENERATOR;
namespace SIM_MODEL_SOURCE_PARSER namespace SIM_MODEL_SOURCE_PARSER
{ {
@ -38,63 +40,36 @@ namespace SIM_MODEL_SOURCE_PARSER
} }
SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType ) wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
: SIM_MODEL( aType ),
m_isInferred( false )
{
for( const SIM_MODEL::PARAM::INFO& paramInfo : makeParamInfos( aType ) )
AddParam( paramInfo );
}
void SIM_MODEL_SOURCE::WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const
{
SIM_MODEL::WriteDataSchFields( aFields );
if( m_isInferred )
inferredWriteDataFields( aFields );
}
void SIM_MODEL_SOURCE::WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const
{
SIM_MODEL::WriteDataLibFields( aFields );
if( m_isInferred )
inferredWriteDataFields( aFields );
}
wxString SIM_MODEL_SOURCE::GenerateSpiceModelLine( const wxString& aModelName ) const
{ {
return ""; return "";
} }
wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName, wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName,
const wxString& aModelName, const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers, const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const const std::vector<wxString>& aPinNetNames ) const
{ {
LOCALE_IO toggle; LOCALE_IO toggle;
wxString model; wxString model;
wxString ac = FindParam( "ac" )->value->ToSpiceString(); wxString ac = m_model.FindParam( "ac" )->value->ToSpiceString();
wxString ph = FindParam( "ph" )->value->ToSpiceString(); wxString ph = m_model.FindParam( "ph" )->value->ToSpiceString();
if( ac != "" ) if( ac != "" )
model << wxString::Format( "AC %s %s ", ac, ph ); model << wxString::Format( "AC %s %s ", ac, ph );
if( GetSpiceInfo().inlineTypeString != "" ) if( m_model.GetSpiceInfo().inlineTypeString != "" )
{ {
wxString args = ""; wxString args = "";
switch( GetType() ) switch( m_model.GetType() )
{ {
case TYPE::V_PWL: case TYPE::V_PWL:
case TYPE::I_PWL: case TYPE::I_PWL:
{ {
tao::pegtl::string_input<> in( GetParam( 0 ).value->ToString().ToUTF8(), tao::pegtl::string_input<> in( m_model.GetParam( 0 ).value->ToString().ToUTF8(),
"from_content" ); "from_content" );
std::unique_ptr<tao::pegtl::parse_tree::node> root; std::unique_ptr<tao::pegtl::parse_tree::node> root;
@ -158,8 +133,8 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName,
args << getParamValueString( "dt", "0" ) << " "; args << getParamValueString( "dt", "0" ) << " ";
args << getParamValueString( "td", "0" ) << " "; args << getParamValueString( "td", "0" ) << " ";
auto min = dynamic_cast<SIM_VALUE_FLOAT&>( *FindParam( "max" )->value ); auto min = dynamic_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "max" )->value );
auto max = dynamic_cast<SIM_VALUE_FLOAT&>( *FindParam( "min" )->value ); auto max = dynamic_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "min" )->value );
SIM_VALUE_FLOAT range = max - min; SIM_VALUE_FLOAT range = max - min;
SIM_VALUE_FLOAT offset = ( max + min ) / SIM_VALUE_FLOAT( 2 ); SIM_VALUE_FLOAT offset = ( max + min ) / SIM_VALUE_FLOAT( 2 );
@ -196,7 +171,7 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName,
break;*/ break;*/
default: default:
for( const PARAM& param : GetParams() ) for( const PARAM& param : m_model.GetParams() )
{ {
wxString argStr = param.value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE ); wxString argStr = param.value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE );
@ -206,12 +181,51 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName,
break; break;
} }
model << wxString::Format( "%s( %s)", GetSpiceInfo().inlineTypeString, args ); model << wxString::Format( "%s( %s)", m_model.GetSpiceInfo().inlineTypeString, args );
} }
else else
model << GetParam( 0 ).value->ToSpiceString(); model << m_model.GetParam( 0 ).value->ToSpiceString();
return SIM_MODEL::GenerateSpiceItemLine( aRefName, model, aSymbolPinNumbers, aPinNetNames ); return SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, model, aSymbolPinNumbers, aPinNetNames );
}
wxString SPICE_GENERATOR::getParamValueString( const wxString& aParamName,
const wxString& aDefaultValue ) const
{
wxString result = m_model.FindParam( aParamName )->value->ToSpiceString();
if( result == "" )
result = aDefaultValue;
return result;
}
SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType )
: SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) ),
m_isInferred( false )
{
for( const SIM_MODEL::PARAM::INFO& paramInfo : makeParamInfos( aType ) )
AddParam( paramInfo );
}
void SIM_MODEL_SOURCE::WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const
{
SIM_MODEL::WriteDataSchFields( aFields );
if( m_isInferred )
inferredWriteDataFields( aFields );
}
void SIM_MODEL_SOURCE::WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const
{
SIM_MODEL::WriteDataLibFields( aFields );
if( m_isInferred )
inferredWriteDataFields( aFields );
} }
@ -263,18 +277,6 @@ void SIM_MODEL_SOURCE::inferredWriteDataFields( std::vector<T>& aFields ) const
} }
wxString SIM_MODEL_SOURCE::getParamValueString( const wxString& aParamName,
const wxString& aDefaultValue ) const
{
wxString result = FindParam( aParamName )->value->ToSpiceString();
if( result == "" )
result = aDefaultValue;
return result;
}
const std::vector<SIM_MODEL::PARAM::INFO>& SIM_MODEL_SOURCE::makeParamInfos( TYPE aType ) const std::vector<SIM_MODEL::PARAM::INFO>& SIM_MODEL_SOURCE::makeParamInfos( TYPE aType )
{ {
static std::vector<SIM_MODEL::PARAM::INFO> vdc = makeDcParamInfos( "y", "V" ); static std::vector<SIM_MODEL::PARAM::INFO> vdc = makeDcParamInfos( "y", "V" );

View File

@ -46,17 +46,28 @@ namespace SIM_MODEL_SOURCE_GRAMMAR
class SIM_MODEL_SOURCE : public SIM_MODEL class SIM_MODEL_SOURCE : public SIM_MODEL
{ {
public: public:
class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR
{
public:
using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR;
wxString ModelLine( const wxString& aModelName ) const override;
wxString ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const override;
private:
wxString getParamValueString( const wxString& aParamName,
const wxString& aDefaultValue ) const;
};
SIM_MODEL_SOURCE( TYPE aType ); SIM_MODEL_SOURCE( TYPE aType );
void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override; void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override;
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override; void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
wxString GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const override;
bool SetParamValue( unsigned aParamIndex, const wxString& aValue, bool SetParamValue( unsigned aParamIndex, const wxString& aValue,
SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SI ) SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SI )
override; override;
@ -72,8 +83,6 @@ private:
std::vector<wxString> getPinNames() const override { return { "+", "-" }; } std::vector<wxString> getPinNames() const override { return { "+", "-" }; }
wxString getParamValueString( const wxString& aParamName, const wxString& aDefaultValue ) const;
static const std::vector<PARAM::INFO>& makeParamInfos( TYPE aType ); static const std::vector<PARAM::INFO>& makeParamInfos( TYPE aType );
static std::vector<PARAM::INFO> makeDcParamInfos( wxString aPrefix, wxString aUnit ); static std::vector<PARAM::INFO> makeDcParamInfos( wxString aPrefix, wxString aUnit );
@ -94,6 +103,7 @@ private:
static void appendAcParamInfos( std::vector<PARAM::INFO>& aParamInfos, wxString aUnit ); static void appendAcParamInfos( std::vector<PARAM::INFO>& aParamInfos, wxString aUnit );
bool m_isInferred; bool m_isInferred;
}; };

View File

@ -26,6 +26,8 @@
#include <pegtl.hpp> #include <pegtl.hpp>
#include <pegtl/contrib/parse_tree.hpp> #include <pegtl/contrib/parse_tree.hpp>
using SPICE_GENERATOR = SIM_MODEL_SPICE::SPICE_GENERATOR;
namespace SIM_MODEL_SPICE_PARSER namespace SIM_MODEL_SPICE_PARSER
{ {
@ -36,8 +38,85 @@ namespace SIM_MODEL_SPICE_PARSER
} }
SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType ) wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
: SIM_MODEL( aType ) {
return "";
}
wxString SPICE_GENERATOR::ItemName( const wxString& aRefName ) const
{
wxString elementType = m_model.GetParam( static_cast<int>( SPICE_PARAM::TYPE ) ).value->ToString();
if( aRefName != "" && aRefName.StartsWith( elementType ) )
return aRefName;
else
return elementType + aRefName;
}
wxString SPICE_GENERATOR::ItemPins( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString result;
for( const PIN& pin : GetPins() )
{
auto it = std::find( aSymbolPinNumbers.begin(), aSymbolPinNumbers.end(),
pin.symbolPinNumber );
if( it != aSymbolPinNumbers.end() )
{
long symbolPinIndex = std::distance( aSymbolPinNumbers.begin(), it );
result << " " << aPinNetNames.at( symbolPinIndex );
}
}
return result;
}
wxString SPICE_GENERATOR::ItemModelName( const wxString& aModelName ) const
{
return "";
}
wxString SPICE_GENERATOR::ItemParams() const
{
wxString result;
for( const PARAM& param : GetInstanceParams() )
{
if( param.info.name != "model" )
result << "";
else
result << " " << param.value->ToString();
}
return result;
}
wxString SPICE_GENERATOR::Preview( const wxString& aModelName ) const
{
std::vector<wxString> pinNumbers;
std::vector<wxString> pinNetNames;
for( int i = 0; i < m_model.GetPinCount(); ++i )
{
pinNumbers.push_back( wxString::FromCDouble( i + 1 ) );
pinNetNames.push_back( wxString::FromCDouble( i + 1 ) );
}
return ItemLine( "", aModelName, pinNumbers, pinNetNames );
}
SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType ) :
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) )
{ {
static std::vector<PARAM::INFO> paramInfos = makeParamInfos(); static std::vector<PARAM::INFO> paramInfos = makeParamInfos();
@ -81,38 +160,6 @@ void SIM_MODEL_SPICE::WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) cons
} }
wxString SIM_MODEL_SPICE::GenerateSpiceModelLine( const wxString& aModelName ) const
{
return "";
}
wxString SIM_MODEL_SPICE::GenerateSpiceItemName( const wxString& aRefName ) const
{
wxString elementType = GetParam( static_cast<int>( SPICE_PARAM::TYPE ) ).value->ToString();
if( aRefName != "" && aRefName.StartsWith( elementType ) )
return aRefName;
else
return elementType + aRefName;
}
wxString SIM_MODEL_SPICE::GenerateSpicePreview( const wxString& aModelName ) const
{
std::vector<wxString> pinNumbers;
std::vector<wxString> pinNetNames;
for( int i = 0; i < GetPinCount(); ++i )
{
pinNumbers.push_back( wxString::FromCDouble( i + 1 ) );
pinNetNames.push_back( wxString::FromCDouble( i + 1 ) );
}
return GenerateSpiceItemLine( "", aModelName, pinNumbers, pinNetNames );
}
void SIM_MODEL_SPICE::CreatePins( unsigned aSymbolPinCount ) void SIM_MODEL_SPICE::CreatePins( unsigned aSymbolPinCount )
{ {
for( unsigned symbolPinIndex = 0; symbolPinIndex < aSymbolPinCount; ++symbolPinIndex ) for( unsigned symbolPinIndex = 0; symbolPinIndex < aSymbolPinCount; ++symbolPinIndex )
@ -120,51 +167,6 @@ void SIM_MODEL_SPICE::CreatePins( unsigned aSymbolPinCount )
} }
wxString SIM_MODEL_SPICE::GenerateSpiceItemPins( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString result;
for( const PIN& pin : GetSpicePins() )
{
auto it = std::find( aSymbolPinNumbers.begin(), aSymbolPinNumbers.end(),
pin.symbolPinNumber );
if( it != aSymbolPinNumbers.end() )
{
long symbolPinIndex = std::distance( aSymbolPinNumbers.begin(), it );
result << " " << aPinNetNames.at( symbolPinIndex );
}
}
return result;
}
wxString SIM_MODEL_SPICE::GenerateSpiceItemModelName( const wxString& aModelName ) const
{
return "";
}
wxString SIM_MODEL_SPICE::GenerateSpiceItemParams() const
{
wxString result;
for( const PARAM& param : GetSpiceInstanceParams() )
{
if( param.info.name != "model" )
result << "";
else
result << " " << param.value->ToString();
}
return result;
}
bool SIM_MODEL_SPICE::SetParamFromSpiceCode( const wxString& aParamName, bool SIM_MODEL_SPICE::SetParamFromSpiceCode( const wxString& aParamName,
const wxString& aParamValue, const wxString& aParamValue,
SIM_VALUE_GRAMMAR::NOTATION aNotation ) SIM_VALUE_GRAMMAR::NOTATION aNotation )

View File

@ -31,6 +31,25 @@
class SIM_MODEL_SPICE : public SIM_MODEL class SIM_MODEL_SPICE : public SIM_MODEL
{ {
public: public:
class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR
{
public:
using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR;
wxString ModelLine( const wxString& aModelName ) const override;
wxString ItemName( const wxString& aRefName ) const override;
wxString ItemPins( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const override;
wxString ItemModelName( const wxString& aModelName ) const override;
wxString ItemParams() const override;
wxString Preview( const wxString& aModelName ) const override;
};
DEFINE_ENUM_CLASS_WITH_ITERATOR( SPICE_PARAM, DEFINE_ENUM_CLASS_WITH_ITERATOR( SPICE_PARAM,
TYPE, TYPE,
MODEL, MODEL,
@ -53,29 +72,16 @@ public:
void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override; void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override;
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override; void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
wxString GenerateSpiceItemName( const wxString& aRefName ) const override;
wxString GenerateSpicePreview( const wxString& aModelName ) const override;
protected: protected:
void CreatePins( unsigned aSymbolPinCount ) override; void CreatePins( unsigned aSymbolPinCount ) override;
wxString GenerateSpiceItemPins( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const override;
wxString GenerateSpiceItemModelName( const wxString& aModelName ) const override;
wxString GenerateSpiceItemParams() const override;
bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue, bool SetParamFromSpiceCode( const wxString& aParamName, const wxString& aParamValue,
SIM_VALUE_GRAMMAR::NOTATION aNotation SIM_VALUE_GRAMMAR::NOTATION aNotation
= SIM_VALUE_GRAMMAR::NOTATION::SPICE ) override; = SIM_VALUE_GRAMMAR::NOTATION::SPICE ) override;
private: private:
std::vector<PARAM::INFO> makeParamInfos(); static std::vector<PARAM::INFO> makeParamInfos();
template <typename T> template <typename T>
void readLegacyDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields ); void readLegacyDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
@ -84,6 +90,7 @@ private:
bool requiresSpiceModelLine() const override { return false; } bool requiresSpiceModelLine() const override { return false; }
std::vector<std::unique_ptr<PARAM::INFO>> m_paramInfos; std::vector<std::unique_ptr<PARAM::INFO>> m_paramInfos;
}; };

View File

@ -27,6 +27,8 @@
#include <pegtl.hpp> #include <pegtl.hpp>
#include <pegtl/contrib/parse_tree.hpp> #include <pegtl/contrib/parse_tree.hpp>
using SPICE_GENERATOR = SIM_MODEL_SUBCKT::SPICE_GENERATOR;
namespace SIM_MODEL_SUBCKT_SPICE_PARSER namespace SIM_MODEL_SUBCKT_SPICE_PARSER
{ {
@ -46,8 +48,29 @@ namespace SIM_MODEL_SUBCKT_SPICE_PARSER
} }
SIM_MODEL_SUBCKT::SIM_MODEL_SUBCKT( TYPE aType ) wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
: SIM_MODEL( aType ) {
return "";
}
std::vector<wxString> SPICE_GENERATOR::CurrentNames( const wxString& aRefName ) const
{
std::vector<wxString> currentNames;
for( const PIN& pin : GetPins() )
{
currentNames.push_back( wxString::Format( "I(%s:%s)",
ItemName( aRefName ),
pin.name ) );
}
return currentNames;
}
SIM_MODEL_SUBCKT::SIM_MODEL_SUBCKT( TYPE aType ) :
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) )
{ {
} }
@ -122,27 +145,6 @@ void SIM_MODEL_SUBCKT::ReadSpiceCode( const wxString& aSpiceCode )
} }
wxString SIM_MODEL_SUBCKT::GenerateSpiceModelLine( const wxString& aModelName ) const
{
return "";
}
std::vector<wxString> SIM_MODEL_SUBCKT::GenerateSpiceCurrentNames( const wxString& aRefName ) const
{
std::vector<wxString> currentNames;
for( const PIN& pin : GetPins() )
{
currentNames.push_back( wxString::Format( "I(%s:%s)",
GenerateSpiceItemName( aRefName ),
pin.name ) );
}
return currentNames;
}
void SIM_MODEL_SUBCKT::SetBaseModel( const SIM_MODEL& aBaseModel ) void SIM_MODEL_SUBCKT::SetBaseModel( const SIM_MODEL& aBaseModel )
{ {
SIM_MODEL::SetBaseModel( aBaseModel ); SIM_MODEL::SetBaseModel( aBaseModel );

View File

@ -31,11 +31,19 @@
class SIM_MODEL_SUBCKT : public SIM_MODEL class SIM_MODEL_SUBCKT : public SIM_MODEL
{ {
public: public:
class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR
{
public:
using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR;
wxString ModelLine( const wxString& aModelName ) const override;
std::vector<wxString> CurrentNames( const wxString& aRefName ) const override;
};
SIM_MODEL_SUBCKT( TYPE aType ); SIM_MODEL_SUBCKT( TYPE aType );
void ReadSpiceCode( const wxString& aSpiceCode ) override; void ReadSpiceCode( const wxString& aSpiceCode ) override;
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
std::vector<wxString> GenerateSpiceCurrentNames( const wxString& aRefName ) const override;
void SetBaseModel( const SIM_MODEL& aBaseModel ) override; void SetBaseModel( const SIM_MODEL& aBaseModel ) override;
protected: protected:
@ -44,6 +52,7 @@ protected:
private: private:
bool requiresSpiceModelLine() const override { return true; } bool requiresSpiceModelLine() const override { return true; }
std::vector<std::unique_ptr<PARAM::INFO>> m_paramInfos; std::vector<std::unique_ptr<PARAM::INFO>> m_paramInfos;
}; };

View File

@ -24,8 +24,84 @@
#include <sim/sim_model_switch.h> #include <sim/sim_model_switch.h>
using SPICE_GENERATOR = SIM_MODEL_SWITCH::SPICE_GENERATOR;
SIM_MODEL_SWITCH::SIM_MODEL_SWITCH( TYPE aType ) : SIM_MODEL( aType )
wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString result;
switch( m_model.GetType() )
{
case TYPE::SW_V:
{
result << SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, aModelName, aSymbolPinNumbers,
aPinNetNames );
break;
}
case TYPE::SW_I:
{
wxString vsourceName = "V__" + aRefName;
// Current switches measure input current through a voltage source.
result << vsourceName << " " << aPinNetNames[0] << " " << aPinNetNames[1] << " 0\n";
result << SIM_MODEL::SPICE_GENERATOR::ItemLine( aRefName, vsourceName + " " + aModelName,
aSymbolPinNumbers, aPinNetNames );
break;
}
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_SWITCH" );
break;
}
return result;
}
wxString SPICE_GENERATOR::ItemParams() const
{
wxString result;
for( const PARAM& param : GetInstanceParams() )
{
// The only instance param is "ic", which is positional.
wxString value = param.value->ToSpiceString();
if( value == "none" )
result << "";
else
result << value;
}
return result;
}
std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> SPICE_GENERATOR::GetPins() const
{
switch( m_model.GetType() )
{
case TYPE::SW_V:
return { m_model.GetPin( 2 ), m_model.GetPin( 3 ), m_model.GetPin( 0 ), m_model.GetPin( 1 ) };
case TYPE::SW_I:
return { m_model.GetPin( 2 ), m_model.GetPin( 3 ) };
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_SWITCH" );
return {};
}
}
SIM_MODEL_SWITCH::SIM_MODEL_SWITCH( TYPE aType ) :
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) )
{ {
static std::vector<PARAM::INFO> vsw = makeSwVParamInfos(); static std::vector<PARAM::INFO> vsw = makeSwVParamInfos();
static std::vector<PARAM::INFO> isw = makeSwIParamInfos(); static std::vector<PARAM::INFO> isw = makeSwIParamInfos();
@ -51,62 +127,6 @@ SIM_MODEL_SWITCH::SIM_MODEL_SWITCH( TYPE aType ) : SIM_MODEL( aType )
} }
wxString SIM_MODEL_SWITCH::GenerateSpiceItemParams() const
{
wxString result;
for( const PARAM& param : GetSpiceInstanceParams() )
{
// The only instance param is "ic", which is positional.
wxString value = param.value->ToSpiceString();
if( value == "none" )
result << "";
else
result << value;
}
return result;
}
wxString SIM_MODEL_SWITCH::GenerateSpiceItemLine( const wxString& aRefName,
const wxString& aModelName,
const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aPinNetNames ) const
{
wxString result;
switch( GetType() )
{
case TYPE::SW_V:
{
result << SIM_MODEL::GenerateSpiceItemLine( aRefName, aModelName, aSymbolPinNumbers,
aPinNetNames );
break;
}
case TYPE::SW_I:
{
wxString vsourceName = "V__" + aRefName;
// Current switches measure input current through a voltage source.
result << vsourceName << " " << aPinNetNames[0] << " " << aPinNetNames[1] << " 0\n";
result << SIM_MODEL::GenerateSpiceItemLine( aRefName, vsourceName + " " + aModelName,
aSymbolPinNumbers, aPinNetNames );
break;
}
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_SWITCH" );
break;
}
return result;
}
wxString SIM_MODEL_SWITCH::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const wxString SIM_MODEL_SWITCH::GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const
{ {
if( aParam.info.name == "ic" && aParam.value->ToString() == "none" ) if( aParam.info.name == "ic" && aParam.value->ToString() == "none" )
@ -118,23 +138,6 @@ wxString SIM_MODEL_SWITCH::GenerateParamValuePair( const PARAM& aParam, bool& aI
} }
std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> SIM_MODEL_SWITCH::GetSpicePins() const
{
switch( GetType() )
{
case TYPE::SW_V:
return { GetPin( 2 ), GetPin( 3 ), GetPin( 0 ), GetPin( 1 ) };
case TYPE::SW_I:
return { GetPin( 2 ), GetPin( 3 ) };
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_SWITCH" );
return {};
}
}
const std::vector<SIM_MODEL::PARAM::INFO> SIM_MODEL_SWITCH::makeSwVParamInfos() const std::vector<SIM_MODEL::PARAM::INFO> SIM_MODEL_SWITCH::makeSwVParamInfos()
{ {
std::vector<PARAM::INFO> paramInfos; std::vector<PARAM::INFO> paramInfos;

View File

@ -31,16 +31,23 @@
class SIM_MODEL_SWITCH : public SIM_MODEL class SIM_MODEL_SWITCH : public SIM_MODEL
{ {
public: public:
SIM_MODEL_SWITCH( TYPE aType ); class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR
{
public:
using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR;
wxString GenerateSpiceItemParams() const override; wxString ItemLine( const wxString& aRefName, const wxString& aModelName,
wxString GenerateSpiceItemLine( const wxString& aRefName, const wxString& aModelName, const std::vector<wxString>& aSymbolPinNumbers,
const std::vector<wxString>& aSymbolPinNumbers, const std::vector<wxString>& aPinNetNames ) const override;
const std::vector<wxString>& aPinNetNames ) const override; wxString ItemParams() const override;
std::vector<std::reference_wrapper<const PIN>> GetPins() const override;
};
SIM_MODEL_SWITCH( TYPE aType );
protected: protected:
wxString GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const override; wxString GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const override;
std::vector<std::reference_wrapper<const PIN>> GetSpicePins() const override;
private: private:
std::vector<wxString> getPinNames() const override std::vector<wxString> getPinNames() const override

View File

@ -25,12 +25,53 @@
#include <sim/sim_model_tline.h> #include <sim/sim_model_tline.h>
#include <locale_io.h> #include <locale_io.h>
using SPICE_GENERATOR = SIM_MODEL_TLINE::SPICE_GENERATOR;
using PARAM = SIM_MODEL::PARAM; using PARAM = SIM_MODEL::PARAM;
SIM_MODEL_TLINE::SIM_MODEL_TLINE( TYPE aType ) wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
: SIM_MODEL( aType ), {
m_isInferred( false ) wxString r, l, g, c, len;
switch( m_model.GetType() )
{
case TYPE::TLINE_Z0:
{
auto z0 = static_cast<const SIM_VALUE_FLOAT&>( *m_model.FindParam( "z0" )->value );
auto td = static_cast<const SIM_VALUE_FLOAT&>( *m_model.FindParam( "td" )->value );
if( !z0.HasValue() || !td.HasValue() )
return wxString::Format( ".model %s LTRA()\n", aModelName );
r = SIM_VALUE_FLOAT( 0 ).ToSpiceString();
l = ( td * z0 ).ToSpiceString();
g = SIM_VALUE_FLOAT( 0 ).ToSpiceString();
c = ( td / z0 ).ToSpiceString();
len = SIM_VALUE_FLOAT( 1 ).ToSpiceString();
break;
}
case TYPE::TLINE_RLGC:
r = m_model.FindParam( "r" )->value->ToSpiceString();
l = m_model.FindParam( "l" )->value->ToSpiceString();
g = m_model.FindParam( "g" )->value->ToSpiceString();
c = m_model.FindParam( "c" )->value->ToSpiceString();
len = m_model.FindParam( "len" )->value->ToSpiceString();
break;
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_TLINE" );
return "";
}
return wxString::Format( ".model %s LTRA( r=%s l=%s g=%s c=%s len=%s )\n",
aModelName, r, l, g, c, len );
}
SIM_MODEL_TLINE::SIM_MODEL_TLINE( TYPE aType ) :
SIM_MODEL( aType, std::make_unique<SPICE_GENERATOR>( *this ) ),
m_isInferred( false )
{ {
static std::vector<PARAM::INFO> z0 = makeZ0ParamInfos(); static std::vector<PARAM::INFO> z0 = makeZ0ParamInfos();
static std::vector<PARAM::INFO> rlgc = makeRlgcParamInfos(); static std::vector<PARAM::INFO> rlgc = makeRlgcParamInfos();
@ -72,46 +113,6 @@ void SIM_MODEL_TLINE::WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) cons
} }
wxString SIM_MODEL_TLINE::GenerateSpiceModelLine( const wxString& aModelName ) const
{
wxString r, l, g, c, len;
switch( GetType() )
{
case TYPE::TLINE_Z0:
{
auto z0 = static_cast<const SIM_VALUE_FLOAT&>( *FindParam( "z0" )->value );
auto td = static_cast<const SIM_VALUE_FLOAT&>( *FindParam( "td" )->value );
if( !z0.HasValue() || !td.HasValue() )
return wxString::Format( ".model %s ltra()\n", aModelName );
r = SIM_VALUE_FLOAT( 0 ).ToSpiceString();
l = ( td * z0 ).ToSpiceString();
g = SIM_VALUE_FLOAT( 0 ).ToSpiceString();
c = ( td / z0 ).ToSpiceString();
len = SIM_VALUE_FLOAT( 1 ).ToSpiceString();
break;
}
case TYPE::TLINE_RLGC:
r = FindParam( "r" )->value->ToSpiceString();
l = FindParam( "l" )->value->ToSpiceString();
g = FindParam( "g" )->value->ToSpiceString();
c = FindParam( "c" )->value->ToSpiceString();
len = FindParam( "len" )->value->ToSpiceString();
break;
default:
wxFAIL_MSG( "Unhandled SIM_MODEL type in SIM_MODEL_TLINE" );
return "";
}
return wxString::Format( ".model %s ltra( r=%s l=%s g=%s c=%s len=%s )\n",
aModelName, r, l, g, c, len );
}
template <typename T> template <typename T>
void SIM_MODEL_TLINE::inferredWriteDataFields( std::vector<T>& aFields ) const void SIM_MODEL_TLINE::inferredWriteDataFields( std::vector<T>& aFields ) const
{ {

View File

@ -31,13 +31,20 @@
class SIM_MODEL_TLINE : public SIM_MODEL class SIM_MODEL_TLINE : public SIM_MODEL
{ {
public: public:
class SPICE_GENERATOR : public SIM_MODEL::SPICE_GENERATOR
{
public:
using SIM_MODEL::SPICE_GENERATOR::SPICE_GENERATOR;
wxString ModelLine( const wxString& aModelName ) const override;
};
SIM_MODEL_TLINE( TYPE aType ); SIM_MODEL_TLINE( TYPE aType );
void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override; void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override;
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override; void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
private: private:
template <typename T> template <typename T>
void inferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields ); void inferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );

View File

@ -823,7 +823,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
symbol->GetFields() ); symbol->GetFields() );
wxString ref = symbol->GetRef( &m_frame->GetCurrentSheet() ); wxString ref = symbol->GetRef( &m_frame->GetCurrentSheet() );
std::vector<wxString> currentNames = model->GenerateSpiceCurrentNames( ref ); std::vector<wxString> currentNames = model->SpiceGenerator().CurrentNames( ref );
if( currentNames.size() == 0 ) if( currentNames.size() == 0 )
return true; return true;