Sim: Refactor Spice code generation to a new SPICE_GENERATOR class
This commit is contained in:
parent
e473e71ef8
commit
e4c5bc6c66
|
@ -75,7 +75,7 @@ bool DIALOG_SIGNAL_LIST::TransferDataToWindow()
|
|||
for( const auto& item : m_circuitModel->GetItems() )
|
||||
{
|
||||
// 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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -338,7 +338,7 @@ void DIALOG_SIM_MODEL<T>::updateModelCodeTab()
|
|||
wxTextFile file;
|
||||
wxString text;
|
||||
|
||||
text << curModel().GenerateSpicePreview( modelName );
|
||||
text << curModel().SpiceGenerator().Preview( modelName );
|
||||
text << "\n";
|
||||
text << "--- FILE SOURCE (" << path << ") ---\n";
|
||||
text << "\n";
|
||||
|
@ -356,7 +356,7 @@ void DIALOG_SIM_MODEL<T>::updateModelCodeTab()
|
|||
}
|
||||
}
|
||||
else
|
||||
m_codePreview->SetText( curModel().GenerateSpicePreview( modelName ) );
|
||||
m_codePreview->SetText( curModel().SpiceGenerator().Preview( modelName ) );
|
||||
|
||||
m_codePreview->SetEditable( false ); // ???
|
||||
m_wasCodePreviewUpdated = true;
|
||||
|
|
|
@ -177,7 +177,7 @@ wxString NETLIST_EXPORTER_SPICE::GetItemName( const wxString& aRefName ) const
|
|||
if( it == spiceItems.end() )
|
||||
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() )
|
||||
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;
|
||||
|
||||
aFormatter.Print( 0, "%s",
|
||||
TO_UTF8( item.model->GenerateSpiceItemLine( item.refName,
|
||||
item.modelName,
|
||||
item.pinNumbers,
|
||||
item.pinNetNames ) ) );
|
||||
TO_UTF8( item.model->SpiceGenerator().ItemLine( item.refName,
|
||||
item.modelName,
|
||||
item.pinNumbers,
|
||||
item.pinNetNames ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include <iterator>
|
||||
|
||||
using SPICE_GENERATOR = SIM_MODEL::SPICE_GENERATOR;
|
||||
using DEVICE_TYPE = SIM_MODEL::DEVICE_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 )
|
||||
{
|
||||
switch( aDeviceType )
|
||||
{
|
||||
case DEVICE_TYPE_::NONE: return { "", "" };
|
||||
case DEVICE_TYPE_::R: return { "R", "Resistor" };
|
||||
case DEVICE_TYPE_::C: return { "C", "Capacitor" };
|
||||
case DEVICE_TYPE_::L: return { "L", "Inductor" };
|
||||
case DEVICE_TYPE_::TLINE: return { "TLINE", "Transmission Line" };
|
||||
case DEVICE_TYPE_::SW: return { "SW", "Switch" };
|
||||
case DEVICE_TYPE_::NONE: return { "", "" };
|
||||
case DEVICE_TYPE_::R: return { "R", "Resistor" };
|
||||
case DEVICE_TYPE_::C: return { "C", "Capacitor" };
|
||||
case DEVICE_TYPE_::L: return { "L", "Inductor" };
|
||||
case DEVICE_TYPE_::TLINE: return { "TLINE", "Transmission Line" };
|
||||
case DEVICE_TYPE_::SW: return { "SW", "Switch" };
|
||||
|
||||
case DEVICE_TYPE_::D: return { "D", "Diode" };
|
||||
case DEVICE_TYPE_::NPN: return { "NPN", "NPN BJT" };
|
||||
case DEVICE_TYPE_::PNP: return { "PNP", "PNP BJT" };
|
||||
case DEVICE_TYPE_::D: return { "D", "Diode" };
|
||||
case DEVICE_TYPE_::NPN: return { "NPN", "NPN BJT" };
|
||||
case DEVICE_TYPE_::PNP: return { "PNP", "PNP BJT" };
|
||||
|
||||
case DEVICE_TYPE_::NJFET: return { "NJFET", "N-channel JFET" };
|
||||
case DEVICE_TYPE_::PJFET: return { "PJFET", "P-channel JFET" };
|
||||
case DEVICE_TYPE_::NJFET: return { "NJFET", "N-channel JFET" };
|
||||
case DEVICE_TYPE_::PJFET: return { "PJFET", "P-channel JFET" };
|
||||
|
||||
case DEVICE_TYPE_::NMOS: return { "NMOS", "N-channel MOSFET" };
|
||||
case DEVICE_TYPE_::PMOS: return { "PMOS", "P-channel MOSFET" };
|
||||
case DEVICE_TYPE_::NMES: return { "NMES", "N-channel MESFET" };
|
||||
case DEVICE_TYPE_::PMES: return { "PMES", "P-channel MESFET" };
|
||||
case DEVICE_TYPE_::NMOS: return { "NMOS", "N-channel MOSFET" };
|
||||
case DEVICE_TYPE_::PMOS: return { "PMOS", "P-channel MOSFET" };
|
||||
case DEVICE_TYPE_::NMES: return { "NMES", "N-channel MESFET" };
|
||||
case DEVICE_TYPE_::PMES: return { "PMES", "P-channel MESFET" };
|
||||
|
||||
case DEVICE_TYPE_::V: return { "V", "Voltage Source" };
|
||||
case DEVICE_TYPE_::I: return { "I", "Current Source" };
|
||||
case DEVICE_TYPE_::V: return { "V", "Voltage Source" };
|
||||
case DEVICE_TYPE_::I: return { "I", "Current Source" };
|
||||
|
||||
case DEVICE_TYPE_::SUBCKT: return { "SUBCKT", "Subcircuit" };
|
||||
case DEVICE_TYPE_::XSPICE: return { "XSPICE", "XSPICE Code Model" };
|
||||
case DEVICE_TYPE_::SPICE: return { "SPICE", "Raw Spice Element" };
|
||||
case DEVICE_TYPE_::_ENUM_END: break;
|
||||
case DEVICE_TYPE_::SUBCKT: return { "SUBCKT", "Subcircuit" };
|
||||
case DEVICE_TYPE_::XSPICE: return { "XSPICE", "XSPICE Code Model" };
|
||||
case DEVICE_TYPE_::SPICE: return { "SPICE", "Raw Spice Element" };
|
||||
case DEVICE_TYPE_::_ENUM_END: break;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
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
|
||||
{
|
||||
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 ),
|
||||
m_isEnabled( true ), m_isInferred( false )
|
||||
SIM_MODEL::SIM_MODEL( TYPE aType, std::unique_ptr<SPICE_GENERATOR> aSpiceGenerator ) :
|
||||
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 result;
|
||||
|
|
|
@ -108,6 +108,50 @@ namespace SIM_MODEL_GRAMMAR
|
|||
class SIM_MODEL
|
||||
{
|
||||
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 VALUE_FIELD = "Value";
|
||||
|
||||
|
@ -463,6 +507,8 @@ public:
|
|||
static void SetFieldValue( std::vector<T>& aFields, const wxString& aFieldName,
|
||||
const wxString& aValue );
|
||||
|
||||
const SPICE_GENERATOR& SpiceGenerator() const { return *m_spiceGenerator; }
|
||||
|
||||
|
||||
// Move semantics.
|
||||
// Rule of five.
|
||||
|
@ -472,7 +518,6 @@ public:
|
|||
SIM_MODEL( SIM_MODEL&& aOther ) = default;
|
||||
SIM_MODEL& operator=(SIM_MODEL&& aOther ) = delete;
|
||||
|
||||
|
||||
virtual void ReadSpiceCode( const wxString& aSpiceCode );
|
||||
|
||||
template <typename T>
|
||||
|
@ -493,23 +538,7 @@ public:
|
|||
|
||||
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() ); }
|
||||
virtual std::vector<wxString> GenerateSpiceCurrentNames( const wxString& aRefName ) const;
|
||||
|
||||
void AddPin( const PIN& aPin );
|
||||
int FindModelPinIndex( const wxString& aSymbolPinNumber );
|
||||
|
@ -541,7 +570,6 @@ public:
|
|||
const PARAM* FindParam( const wxString& aParamName ) 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& GetBaseParam( unsigned aParamIndex ) const; // Always return base parameter if it exists.
|
||||
|
@ -564,20 +592,14 @@ public:
|
|||
bool IsEnabled() const { return m_isEnabled; }
|
||||
|
||||
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 );
|
||||
|
||||
template <typename T>
|
||||
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;
|
||||
|
||||
wxString GenerateParamsField( const wxString& aPairSeparator ) const;
|
||||
|
@ -586,11 +608,6 @@ protected:
|
|||
void ParsePinsField( unsigned aSymbolPinCount, const wxString& aPinsField );
|
||||
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,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation
|
||||
= SIM_VALUE_GRAMMAR::NOTATION::SPICE );
|
||||
|
@ -629,6 +646,7 @@ private:
|
|||
virtual std::vector<wxString> getPinNames() const { return {}; }
|
||||
|
||||
|
||||
std::unique_ptr<SPICE_GENERATOR> m_spiceGenerator;
|
||||
const SIM_MODEL* m_baseModel;
|
||||
|
||||
const TYPE m_type;
|
||||
|
|
|
@ -25,10 +25,54 @@
|
|||
#include <sim/sim_model_behavioral.h>
|
||||
#include <locale_io.h>
|
||||
|
||||
using SPICE_GENERATOR = SIM_MODEL_BEHAVIORAL::SPICE_GENERATOR;
|
||||
|
||||
SIM_MODEL_BEHAVIORAL::SIM_MODEL_BEHAVIORAL( TYPE aType )
|
||||
: SIM_MODEL( aType ),
|
||||
m_isInferred( false )
|
||||
|
||||
wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
|
||||
{
|
||||
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 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 )
|
||||
{
|
||||
wxString expr = aValueField;
|
||||
|
|
|
@ -31,6 +31,19 @@
|
|||
class SIM_MODEL_BEHAVIORAL : public SIM_MODEL
|
||||
{
|
||||
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 );
|
||||
|
||||
void ReadDataSchFields( unsigned aSymbolPinCount,
|
||||
|
@ -41,12 +54,6 @@ public:
|
|||
void WriteDataSchFields( std::vector<SCH_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:
|
||||
bool parseValueField( const wxString& aValueField );
|
||||
|
@ -61,6 +68,7 @@ private:
|
|||
|
||||
static PARAM::INFO makeParams( wxString aName, wxString aDescription, wxString aUnit );
|
||||
|
||||
|
||||
bool m_isInferred;
|
||||
};
|
||||
|
||||
|
|
|
@ -26,10 +26,33 @@
|
|||
#include <pegtl.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 ),
|
||||
m_isInferred( false )
|
||||
|
||||
wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
|
||||
{
|
||||
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 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>
|
||||
void SIM_MODEL_IDEAL::inferredWriteDataFields( std::vector<T>& aFields ) const
|
||||
{
|
||||
|
|
|
@ -31,6 +31,19 @@
|
|||
class SIM_MODEL_IDEAL : public SIM_MODEL
|
||||
{
|
||||
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 );
|
||||
|
||||
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 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:
|
||||
template <typename T>
|
||||
void inferredWriteDataFields( std::vector<T>& aFields ) const;
|
||||
|
|
|
@ -24,8 +24,22 @@
|
|||
|
||||
#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();
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
std::vector<PARAM::INFO> paramInfos;
|
||||
|
|
|
@ -31,9 +31,15 @@
|
|||
class SIM_MODEL_MUTUAL_INDUCTOR : public SIM_MODEL
|
||||
{
|
||||
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:
|
||||
static const std::vector<PARAM::INFO> makeParamInfos();
|
||||
|
|
|
@ -25,34 +25,15 @@
|
|||
#include <sim/sim_model_ngspice.h>
|
||||
#include <locale_io.h>
|
||||
|
||||
using SPICE_GENERATOR = SIM_MODEL_NGSPICE::SPICE_GENERATOR;
|
||||
using TYPE = SIM_MODEL::TYPE;
|
||||
|
||||
|
||||
SIM_MODEL_NGSPICE::SIM_MODEL_NGSPICE( TYPE aType )
|
||||
: 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
|
||||
std::vector<wxString> SPICE_GENERATOR::CurrentNames( const wxString& aRefName ) const
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
|
||||
switch( TypeInfo( GetType() ).deviceType )
|
||||
switch( m_model.GetTypeInfo().deviceType )
|
||||
{
|
||||
case DEVICE_TYPE_::NPN:
|
||||
case DEVICE_TYPE_::PNP:
|
||||
|
@ -74,7 +55,7 @@ std::vector<wxString> SIM_MODEL_NGSPICE::GenerateSpiceCurrentNames( const wxStri
|
|||
case DEVICE_TYPE_::C:
|
||||
case DEVICE_TYPE_::L:
|
||||
case DEVICE_TYPE_::D:
|
||||
return SIM_MODEL::GenerateSpiceCurrentNames( aRefName );
|
||||
return CurrentNames( aRefName );
|
||||
|
||||
default:
|
||||
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,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation )
|
||||
{
|
||||
|
|
|
@ -33,9 +33,16 @@ class SIM_MODEL_NGSPICE : public SIM_MODEL
|
|||
public:
|
||||
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,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation ) override;
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
#include <locale_io.h>
|
||||
|
||||
using SPICE_GENERATOR = SIM_MODEL_SOURCE::SPICE_GENERATOR;
|
||||
|
||||
|
||||
namespace SIM_MODEL_SOURCE_PARSER
|
||||
{
|
||||
|
@ -38,63 +40,36 @@ namespace SIM_MODEL_SOURCE_PARSER
|
|||
}
|
||||
|
||||
|
||||
SIM_MODEL_SOURCE::SIM_MODEL_SOURCE( TYPE aType )
|
||||
: 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
|
||||
wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName,
|
||||
const wxString& aModelName,
|
||||
const std::vector<wxString>& aSymbolPinNumbers,
|
||||
const std::vector<wxString>& aPinNetNames ) const
|
||||
wxString SPICE_GENERATOR::ItemLine( const wxString& aRefName,
|
||||
const wxString& aModelName,
|
||||
const std::vector<wxString>& aSymbolPinNumbers,
|
||||
const std::vector<wxString>& aPinNetNames ) const
|
||||
{
|
||||
LOCALE_IO toggle;
|
||||
wxString model;
|
||||
|
||||
wxString ac = FindParam( "ac" )->value->ToSpiceString();
|
||||
wxString ph = FindParam( "ph" )->value->ToSpiceString();
|
||||
wxString ac = m_model.FindParam( "ac" )->value->ToSpiceString();
|
||||
wxString ph = m_model.FindParam( "ph" )->value->ToSpiceString();
|
||||
|
||||
if( ac != "" )
|
||||
model << wxString::Format( "AC %s %s ", ac, ph );
|
||||
|
||||
if( GetSpiceInfo().inlineTypeString != "" )
|
||||
if( m_model.GetSpiceInfo().inlineTypeString != "" )
|
||||
{
|
||||
wxString args = "";
|
||||
|
||||
switch( GetType() )
|
||||
switch( m_model.GetType() )
|
||||
{
|
||||
case TYPE::V_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" );
|
||||
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( "td", "0" ) << " ";
|
||||
|
||||
auto min = dynamic_cast<SIM_VALUE_FLOAT&>( *FindParam( "max" )->value );
|
||||
auto max = dynamic_cast<SIM_VALUE_FLOAT&>( *FindParam( "min" )->value );
|
||||
auto min = dynamic_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "max" )->value );
|
||||
auto max = dynamic_cast<SIM_VALUE_FLOAT&>( *m_model.FindParam( "min" )->value );
|
||||
SIM_VALUE_FLOAT range = max - min;
|
||||
SIM_VALUE_FLOAT offset = ( max + min ) / SIM_VALUE_FLOAT( 2 );
|
||||
|
||||
|
@ -196,7 +171,7 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName,
|
|||
break;*/
|
||||
|
||||
default:
|
||||
for( const PARAM& param : GetParams() )
|
||||
for( const PARAM& param : m_model.GetParams() )
|
||||
{
|
||||
wxString argStr = param.value->ToString( SIM_VALUE_GRAMMAR::NOTATION::SPICE );
|
||||
|
||||
|
@ -206,12 +181,51 @@ wxString SIM_MODEL_SOURCE::GenerateSpiceItemLine( const wxString& aRefName,
|
|||
break;
|
||||
}
|
||||
|
||||
model << wxString::Format( "%s( %s)", GetSpiceInfo().inlineTypeString, args );
|
||||
model << wxString::Format( "%s( %s)", m_model.GetSpiceInfo().inlineTypeString, args );
|
||||
}
|
||||
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 )
|
||||
{
|
||||
static std::vector<SIM_MODEL::PARAM::INFO> vdc = makeDcParamInfos( "y", "V" );
|
||||
|
|
|
@ -46,17 +46,28 @@ namespace SIM_MODEL_SOURCE_GRAMMAR
|
|||
class SIM_MODEL_SOURCE : public SIM_MODEL
|
||||
{
|
||||
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 );
|
||||
|
||||
void WriteDataSchFields( std::vector<SCH_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,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation = SIM_VALUE_GRAMMAR::NOTATION::SI )
|
||||
override;
|
||||
|
@ -72,8 +83,6 @@ private:
|
|||
|
||||
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 std::vector<PARAM::INFO> makeDcParamInfos( wxString aPrefix, wxString aUnit );
|
||||
|
@ -94,6 +103,7 @@ private:
|
|||
|
||||
static void appendAcParamInfos( std::vector<PARAM::INFO>& aParamInfos, wxString aUnit );
|
||||
|
||||
|
||||
bool m_isInferred;
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <pegtl.hpp>
|
||||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
|
||||
using SPICE_GENERATOR = SIM_MODEL_SPICE::SPICE_GENERATOR;
|
||||
|
||||
|
||||
namespace SIM_MODEL_SPICE_PARSER
|
||||
{
|
||||
|
@ -36,8 +38,85 @@ namespace SIM_MODEL_SPICE_PARSER
|
|||
}
|
||||
|
||||
|
||||
SIM_MODEL_SPICE::SIM_MODEL_SPICE( TYPE aType )
|
||||
: SIM_MODEL( aType )
|
||||
wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
|
||||
{
|
||||
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();
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
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,
|
||||
const wxString& aParamValue,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation )
|
||||
|
|
|
@ -31,6 +31,25 @@
|
|||
class SIM_MODEL_SPICE : public SIM_MODEL
|
||||
{
|
||||
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,
|
||||
TYPE,
|
||||
MODEL,
|
||||
|
@ -53,29 +72,16 @@ public:
|
|||
void WriteDataSchFields( std::vector<SCH_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:
|
||||
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,
|
||||
SIM_VALUE_GRAMMAR::NOTATION aNotation
|
||||
= SIM_VALUE_GRAMMAR::NOTATION::SPICE ) override;
|
||||
|
||||
private:
|
||||
std::vector<PARAM::INFO> makeParamInfos();
|
||||
static std::vector<PARAM::INFO> makeParamInfos();
|
||||
|
||||
template <typename T>
|
||||
void readLegacyDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
||||
|
@ -84,6 +90,7 @@ private:
|
|||
|
||||
bool requiresSpiceModelLine() const override { return false; }
|
||||
|
||||
|
||||
std::vector<std::unique_ptr<PARAM::INFO>> m_paramInfos;
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <pegtl.hpp>
|
||||
#include <pegtl/contrib/parse_tree.hpp>
|
||||
|
||||
using SPICE_GENERATOR = SIM_MODEL_SUBCKT::SPICE_GENERATOR;
|
||||
|
||||
|
||||
namespace SIM_MODEL_SUBCKT_SPICE_PARSER
|
||||
{
|
||||
|
@ -46,8 +48,29 @@ namespace SIM_MODEL_SUBCKT_SPICE_PARSER
|
|||
}
|
||||
|
||||
|
||||
SIM_MODEL_SUBCKT::SIM_MODEL_SUBCKT( TYPE aType )
|
||||
: SIM_MODEL( aType )
|
||||
wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
|
||||
{
|
||||
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 )
|
||||
{
|
||||
SIM_MODEL::SetBaseModel( aBaseModel );
|
||||
|
|
|
@ -31,11 +31,19 @@
|
|||
class SIM_MODEL_SUBCKT : public SIM_MODEL
|
||||
{
|
||||
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 );
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
|
@ -44,6 +52,7 @@ protected:
|
|||
private:
|
||||
bool requiresSpiceModelLine() const override { return true; }
|
||||
|
||||
|
||||
std::vector<std::unique_ptr<PARAM::INFO>> m_paramInfos;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,8 +24,84 @@
|
|||
|
||||
#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> 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
|
||||
{
|
||||
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()
|
||||
{
|
||||
std::vector<PARAM::INFO> paramInfos;
|
||||
|
|
|
@ -31,16 +31,23 @@
|
|||
class SIM_MODEL_SWITCH : public SIM_MODEL
|
||||
{
|
||||
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 GenerateSpiceItemLine( const wxString& aRefName, const wxString& aModelName,
|
||||
const std::vector<wxString>& aSymbolPinNumbers,
|
||||
const std::vector<wxString>& aPinNetNames ) const override;
|
||||
wxString ItemLine( const wxString& aRefName, const wxString& aModelName,
|
||||
const std::vector<wxString>& aSymbolPinNumbers,
|
||||
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:
|
||||
wxString GenerateParamValuePair( const PARAM& aParam, bool& aIsFirst ) const override;
|
||||
std::vector<std::reference_wrapper<const PIN>> GetSpicePins() const override;
|
||||
|
||||
private:
|
||||
std::vector<wxString> getPinNames() const override
|
||||
|
|
|
@ -25,12 +25,53 @@
|
|||
#include <sim/sim_model_tline.h>
|
||||
#include <locale_io.h>
|
||||
|
||||
using SPICE_GENERATOR = SIM_MODEL_TLINE::SPICE_GENERATOR;
|
||||
using PARAM = SIM_MODEL::PARAM;
|
||||
|
||||
|
||||
SIM_MODEL_TLINE::SIM_MODEL_TLINE( TYPE aType )
|
||||
: SIM_MODEL( aType ),
|
||||
m_isInferred( false )
|
||||
wxString SPICE_GENERATOR::ModelLine( const wxString& aModelName ) const
|
||||
{
|
||||
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> 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>
|
||||
void SIM_MODEL_TLINE::inferredWriteDataFields( std::vector<T>& aFields ) const
|
||||
{
|
||||
|
|
|
@ -31,13 +31,20 @@
|
|||
class SIM_MODEL_TLINE : public SIM_MODEL
|
||||
{
|
||||
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 );
|
||||
|
||||
void WriteDataSchFields( std::vector<SCH_FIELD>& aFields ) const override;
|
||||
void WriteDataLibFields( std::vector<LIB_FIELD>& aFields ) const override;
|
||||
|
||||
wxString GenerateSpiceModelLine( const wxString& aModelName ) const override;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void inferredReadDataFields( unsigned aSymbolPinCount, const std::vector<T>* aFields );
|
||||
|
|
|
@ -823,7 +823,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
|
|||
symbol->GetFields() );
|
||||
|
||||
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 )
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue