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() )
|
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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" );
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue