Raw spice models don't have pin names.

This commit is contained in:
Jeff Young 2024-05-10 20:53:30 +01:00
parent 6537f9fa15
commit 29360b1aef
18 changed files with 105 additions and 106 deletions

View File

@ -409,7 +409,7 @@ bool DIALOG_SIM_MODEL<T>::TransferDataFromWindow()
wxString modelPinName = m_pinAssignmentsGrid->GetCellValue( row, PIN_COLUMN::MODEL );
wxString symbolPinName = m_sortedPartPins.at( row )->GetShownNumber();
model.SetPinSymbolPinNumber( getModelPinIndex( modelPinName ),
model.AssignSymbolPinNumberToModelPin( getModelPinIndex( modelPinName ),
std::string( symbolPinName.ToUTF8() ) );
}
@ -797,7 +797,7 @@ void DIALOG_SIM_MODEL<T>::removeOrphanedPinAssignments( SIM_MODEL* aModel )
for( int i = 0; i < aModel->GetPinCount(); ++i )
{
if( !m_symbol.GetPin( aModel->GetPin( i ).symbolPinNumber ) )
aModel->SetPinSymbolPinNumber( i, "" );
aModel->AssignSymbolPinNumberToModelPin( i, "" );
}
}
@ -1127,16 +1127,16 @@ wxString DIALOG_SIM_MODEL<T>::getSymbolPinString( int symbolPinIndex ) const
template <typename T>
wxString DIALOG_SIM_MODEL<T>::getModelPinString( SIM_MODEL* aModel, int aModelPinIndex ) const
{
const wxString& pinName = aModel->GetPin( aModelPinIndex ).name;
const wxString& modelPinName = aModel->GetPin( aModelPinIndex ).modelPinName;
LOCALE_IO toggle;
wxString pinNumber = wxString::Format( "%d", aModelPinIndex + 1 );
wxString modelPinNumber = wxString::Format( "%d", aModelPinIndex + 1 );
if( !pinName.IsEmpty() && pinName != pinNumber )
pinNumber += wxString::Format( wxT( " (%s)" ), pinName );
if( !modelPinName.IsEmpty() && modelPinName != modelPinNumber )
modelPinNumber += wxString::Format( wxT( " (%s)" ), modelPinName );
return pinNumber;
return modelPinNumber;
}
@ -1144,7 +1144,7 @@ template <typename T>
int DIALOG_SIM_MODEL<T>::getModelPinIndex( const wxString& aModelPinString ) const
{
if( aModelPinString == "Not Connected" )
return SIM_MODEL::PIN::NOT_CONNECTED;
return SIM_MODEL_PIN::NOT_CONNECTED;
int length = aModelPinString.Find( " " );
@ -1423,13 +1423,14 @@ void DIALOG_SIM_MODEL<T>::onPinAssignmentsGridCellChange( wxGridEvent& aEvent )
int oldModelPinIndex = getModelPinIndex( oldModelPinName );
int modelPinIndex = getModelPinIndex( modelPinName );
if( oldModelPinIndex != SIM_MODEL::PIN::NOT_CONNECTED )
curModel().SetPinSymbolPinNumber( oldModelPinIndex, "" );
if( oldModelPinIndex != SIM_MODEL_PIN::NOT_CONNECTED )
curModel().AssignSymbolPinNumberToModelPin( oldModelPinIndex, "" );
if( modelPinIndex != SIM_MODEL::PIN::NOT_CONNECTED )
if( modelPinIndex != SIM_MODEL_PIN::NOT_CONNECTED )
{
curModel().SetPinSymbolPinNumber( modelPinIndex,
std::string( m_sortedPartPins.at( symbolPinIndex )->GetShownNumber().ToUTF8() ) );
SCH_PIN* symbolPin = m_sortedPartPins.at( symbolPinIndex );
curModel().AssignSymbolPinNumberToModelPin( modelPinIndex, symbolPin->GetShownNumber() );
}
updatePinAssignments( &curModel(), FORCE_UPDATE_PINS );

View File

@ -1573,7 +1573,7 @@ void SCH_EDIT_FRAME::RefreshOperatingPointDisplay()
for( const auto& modelPin : model.GetPins() )
{
SCH_PIN* symbolPin = symbol->GetPin( modelPin.get().symbolPinNumber );
wxString signalName = ref + wxS( ":" ) + modelPin.get().name;
wxString signalName = ref + wxS( ":" ) + modelPin.get().modelPinName;
wxString op = m_schematic->GetOperatingPoint( signalName,
settings.m_OPO_IPrecision,
settings.m_OPO_IRange );

View File

@ -1329,7 +1329,7 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i
{
pin = pin.SubString( 1, -1 ); // Strip ':' from front
for( const std::reference_wrapper<const SIM_MODEL::PIN>& modelPin : model.GetPins() )
for( const std::reference_wrapper<const SIM_MODEL_PIN>& modelPin : model.GetPins() )
{
SCH_PIN* symbolPin = GetPin( modelPin.get().symbolPinNumber );
@ -1341,7 +1341,7 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i
}
else
{
wxString signalName = spiceRef + wxS( ":" ) + modelPin.get().name;
wxString signalName = spiceRef + wxS( ":" ) + modelPin.get().modelPinName;
*token = schematic->GetOperatingPoint( signalName, precision, range );
}

View File

@ -693,15 +693,15 @@ void SIM_MODEL::SetFieldValue( std::vector<SCH_FIELD>& aFields, const wxString&
SIM_MODEL::~SIM_MODEL() = default;
void SIM_MODEL::AddPin( const PIN& aPin )
void SIM_MODEL::AddPin( const SIM_MODEL_PIN& aPin )
{
m_pins.push_back( aPin );
m_modelPins.push_back( aPin );
}
void SIM_MODEL::ClearPins()
{
m_pins.clear();
m_modelPins.clear();
}
@ -713,7 +713,7 @@ int SIM_MODEL::FindModelPinIndex( const std::string& aSymbolPinNumber )
return modelPinIndex;
}
return PIN::NOT_CONNECTED;
return SIM_MODEL_PIN::NOT_CONNECTED;
}
@ -736,9 +736,9 @@ void SIM_MODEL::SetBaseModel( const SIM_MODEL& aBaseModel )
}
std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> SIM_MODEL::GetPins() const
std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> SIM_MODEL::GetPins() const
{
std::vector<std::reference_wrapper<const PIN>> pins;
std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> pins;
for( int modelPinIndex = 0; modelPinIndex < GetPinCount(); ++modelPinIndex )
pins.emplace_back( GetPin( modelPinIndex ) );
@ -746,19 +746,20 @@ std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> SIM_MODEL::GetPins() c
return pins;
}
void SIM_MODEL::SetPinSymbolPinNumber( int aPinIndex, const std::string& aSymbolPinNumber )
void SIM_MODEL::AssignSymbolPinNumberToModelPin( int aModelPinIndex,
const wxString& aSymbolPinNumber )
{
if( aPinIndex >= 0 && aPinIndex < (int) m_pins.size() )
m_pins.at( aPinIndex ).symbolPinNumber = aSymbolPinNumber;
if( aModelPinIndex >= 0 && aModelPinIndex < (int) m_modelPins.size() )
m_modelPins.at( aModelPinIndex ).symbolPinNumber = aSymbolPinNumber;
}
void SIM_MODEL::SetPinSymbolPinNumber( const std::string& aPinName,
const std::string& aSymbolPinNumber )
void SIM_MODEL::AssignSymbolPinNumberToModelPin( const std::string& aModelPinName,
const wxString& aSymbolPinNumber )
{
for( PIN& pin : m_pins )
for( SIM_MODEL_PIN& pin : m_modelPins )
{
if( pin.name == aPinName )
if( pin.modelPinName == aModelPinName )
{
pin.symbolPinNumber = aSymbolPinNumber;
return;
@ -767,12 +768,12 @@ void SIM_MODEL::SetPinSymbolPinNumber( const std::string& aPinName,
// If aPinName wasn't in fact a name, see if it's a raw (1-based) index. This is required
// for legacy files which didn't use pin names.
int aPinIndex = (int) strtol( aPinName.c_str(), nullptr, 10 );
int pinIndex = (int) strtol( aModelPinName.c_str(), nullptr, 10 );
if( aPinIndex < 1 || aPinIndex > (int) m_pins.size() )
THROW_IO_ERROR( wxString::Format( _( "Unknown simulation model pin '%s'" ), aPinName ) );
if( pinIndex < 1 || pinIndex > (int) m_modelPins.size() )
THROW_IO_ERROR( wxString::Format( _( "Unknown simulation model pin '%s'" ), aModelPinName ) );
m_pins[ --aPinIndex /* convert to 0-based */ ].symbolPinNumber = aSymbolPinNumber;
m_modelPins[ --pinIndex /* convert to 0-based */ ].symbolPinNumber = aSymbolPinNumber;
}

View File

@ -65,13 +65,21 @@ class REPORTER;
#define SIM_LEGACY_LIBRARY_FIELD wxS( "Spice_Lib_File" )
struct SIM_MODEL_PIN
{
const std::string modelPinName;
wxString symbolPinNumber;
static constexpr auto NOT_CONNECTED = -1;
};
class SIM_MODEL
{
public:
friend class SPICE_GENERATOR;
friend class NETLIST_EXPORTER_SPICE;
struct PIN;
struct PARAM;
// There's a trailing '_' because `DEVICE_TYPE` collides with something in Windows headers.
@ -303,15 +311,6 @@ public:
};
struct PIN
{
const std::string name;
std::string symbolPinNumber;
static constexpr auto NOT_CONNECTED = -1;
};
struct PARAM
{
// MS Windows compilers complain about the names IN and OUT, so we prefix them.
@ -452,7 +451,7 @@ public:
SPICE_INFO GetSpiceInfo() const { return SpiceInfo( GetType() ); }
void AddPin( const PIN& aPin );
void AddPin( const SIM_MODEL_PIN& aPin );
void ClearPins();
int FindModelPinIndex( const std::string& aSymbolPinNumber );
@ -469,14 +468,14 @@ public:
virtual std::vector<std::string> GetPinNames() const { return {}; }
int GetPinCount() const { return static_cast<int>( m_pins.size() ); }
const PIN& GetPin( unsigned aIndex ) const { return m_pins.at( aIndex ); }
int GetPinCount() const { return static_cast<int>( m_modelPins.size() ); }
const SIM_MODEL_PIN& GetPin( unsigned aIndex ) const { return m_modelPins.at( aIndex ); }
std::vector<std::reference_wrapper<const PIN>> GetPins() const;
std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> GetPins() const;
void SetPinSymbolPinNumber( int aPinIndex, const std::string& aSymbolPinNumber );
virtual void SetPinSymbolPinNumber( const std::string& aPinName,
const std::string& aSymbolPinNumber );
void AssignSymbolPinNumberToModelPin( int aPinIndex, const wxString& aSymbolPinNumber );
virtual void AssignSymbolPinNumberToModelPin( const std::string& aPinName,
const wxString& aSymbolPinNumber );
int GetParamCount() const { return static_cast<int>( m_params.size() ); }
@ -539,7 +538,7 @@ private:
protected:
std::vector<PARAM> m_params;
std::vector<PIN> m_pins;
std::vector<SIM_MODEL_PIN> m_modelPins;
const SIM_MODEL* m_baseModel;
std::unique_ptr<SIM_MODEL_SERIALIZER> m_serializer;

View File

@ -51,8 +51,8 @@ std::vector<std::string> SPICE_GENERATOR_KIBIS::CurrentNames( const SPICE_ITEM&
{
std::vector<std::string> currentNames;
for( const SIM_MODEL::PIN& pin : GetPins() )
currentNames.push_back( fmt::format( "I({}:{})", ItemName( aItem ), pin.name ) );
for( const SIM_MODEL_PIN& pin : GetPins() )
currentNames.push_back( fmt::format( "I({}:{})", ItemName( aItem ), pin.modelPinName ) );
return currentNames;
}

View File

@ -63,7 +63,7 @@ std::string SPICE_GENERATOR_RAW_SPICE::ItemPins( const SPICE_ITEM& aItem ) const
if( !GetPins().empty() )
{
for( const SIM_MODEL::PIN& pin : GetPins() )
for( const SIM_MODEL_PIN& pin : GetPins() )
{
auto it = std::find( aItem.pinNumbers.begin(), aItem.pinNumbers.end(),
pin.symbolPinNumber );
@ -139,19 +139,19 @@ SIM_MODEL_RAW_SPICE::SIM_MODEL_RAW_SPICE( const std::string& aSpiceSource ) :
}
void SIM_MODEL_RAW_SPICE::SetPinSymbolPinNumber( const std::string& aPinName,
const std::string& aSymbolPinNumber )
void SIM_MODEL_RAW_SPICE::AssignSymbolPinNumberToModelPin( const std::string& aModelPinName,
const wxString& aSymbolPinNumber )
{
for( PIN& pin : m_pins )
{
if( pin.name == aPinName )
{
pin.symbolPinNumber = aSymbolPinNumber;
return;
}
}
// SPICE doesn't name model inputs so we have to assume they're indexes here.
int pinIndex = (int) strtol( aModelPinName.c_str(), nullptr, 10 );
m_pins.push_back( { aPinName, aSymbolPinNumber } );
if( pinIndex > 0 )
{
while( m_modelPins.size() < pinIndex )
m_modelPins.push_back( { fmt::format( "{}", m_modelPins.size() + 1 ), wxEmptyString } );
m_modelPins[ --pinIndex /* convert to 0-based */ ].symbolPinNumber = aSymbolPinNumber;
}
}

View File

@ -68,8 +68,8 @@ public:
return m_spiceCode;
}
void SetPinSymbolPinNumber( const std::string& aPinName,
const std::string& aSymbolPinNumber ) override;
void AssignSymbolPinNumberToModelPin( const std::string& aModelPinName,
const wxString& aSymbolPinNumber ) override;
private:
static std::vector<PARAM::INFO> makeParamInfos();

View File

@ -123,29 +123,27 @@ std::string SIM_MODEL_SERIALIZER::GeneratePins() const
{
std::string result;
std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> pins = m_model.GetPins();
std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> pins = m_model.GetPins();
// m_model.GetPins() returns pins in the order they appear in the model, but the keys in the
// key=value pairs we create here are symbol pin numbers, so we sort the pins so that they are
// ordered by the latter instead.
std::sort( pins.begin(), pins.end(),
[]( const SIM_MODEL::PIN& lhs, const SIM_MODEL::PIN& rhs )
[]( const SIM_MODEL_PIN& lhs, const SIM_MODEL_PIN& rhs )
{
return StrNumCmp( lhs.symbolPinNumber, rhs.symbolPinNumber, true ) < 0;
} );
bool isFirst = true;
for( const SIM_MODEL_PIN& pin : pins )
{
std::string symbolPinNumber( pin.symbolPinNumber.ToUTF8() );
for( const SIM_MODEL::PIN& pin : pins )
if( symbolPinNumber != "" )
{
if( pin.symbolPinNumber != "" )
{
if( !isFirst )
if( !result.empty() )
result.append( " " );
else
isFirst = false;
result.append( fmt::format( "{}={}", pin.symbolPinNumber, pin.name ) );
result.append( fmt::format( "{}={}", symbolPinNumber, pin.modelPinName ) );
}
}
@ -275,9 +273,9 @@ void SIM_MODEL_SERIALIZER::ParsePins( const std::string& aPins )
for( const auto& node : root->children )
{
std::string symbolPinNumber = node->children.at( 0 )->string();
std::string pinName = node->children.at( 1 )->string();
std::string modelPinName = node->children.at( 1 )->string();
m_model.SetPinSymbolPinNumber( pinName, symbolPinNumber );
m_model.AssignSymbolPinNumberToModelPin( modelPinName, symbolPinNumber );
}
}
catch( const tao::pegtl::parse_error& e )

View File

@ -38,18 +38,18 @@ SIM_MODEL_SPICE_FALLBACK::SIM_MODEL_SPICE_FALLBACK( TYPE aType, const std::strin
}
void SIM_MODEL_SPICE_FALLBACK::SetPinSymbolPinNumber( const std::string& aPinName,
const std::string& aSymbolPinNumber )
void SIM_MODEL_SPICE_FALLBACK::AssignSymbolPinNumberToModelPin( const std::string& aModelPinName,
const wxString& aSymbolPinNumber )
{
try
{
SIM_MODEL::SetPinSymbolPinNumber( aPinName, aSymbolPinNumber );
SIM_MODEL::AssignSymbolPinNumberToModelPin( aModelPinName, aSymbolPinNumber );
}
catch( IO_ERROR& )
{
// This is a fall-back, so we won't necessarily know the pin names. If we didn't find
// it, then just create a new pin.
m_pins.push_back( { aPinName, aSymbolPinNumber } );
m_modelPins.push_back( { aModelPinName, aSymbolPinNumber } );
}
}

View File

@ -32,8 +32,8 @@ class SIM_MODEL_SPICE_FALLBACK : public SIM_MODEL_SPICE
public:
SIM_MODEL_SPICE_FALLBACK( TYPE aType, const std::string& aRawSpiceCode = "" );
void SetPinSymbolPinNumber( const std::string& aPinName,
const std::string& aSymbolPinNumber ) override;
void AssignSymbolPinNumberToModelPin( const std::string& aModelPinName,
const wxString& aSymbolPinNumber ) override;
std::vector<std::string> GetPinNames() const override;

View File

@ -59,8 +59,8 @@ std::vector<std::string> SPICE_GENERATOR_SUBCKT::CurrentNames( const SPICE_ITEM&
{
std::vector<std::string> currentNames;
for( const SIM_MODEL::PIN& pin : GetPins() )
currentNames.push_back( fmt::format( "I({}:{})", ItemName( aItem ), pin.name ) );
for( const SIM_MODEL_PIN& pin : GetPins() )
currentNames.push_back( fmt::format( "I({}:{})", ItemName( aItem ), pin.modelPinName ) );
return currentNames;
}
@ -147,7 +147,7 @@ void SIM_MODEL_SUBCKT::SetBaseModel( const SIM_MODEL& aBaseModel )
SIM_MODEL::SetBaseModel( aBaseModel );
// Pins aren't constant for subcircuits, so they need to be copied from the base model.
for( const PIN& pin : GetBaseModel()->GetPins() )
for( const SIM_MODEL_PIN& pin : GetBaseModel()->GetPins() )
AddPin( pin );
// Same for parameters.

View File

@ -79,7 +79,7 @@ std::string SPICE_GENERATOR_SWITCH::ItemParams() const
}
std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> SPICE_GENERATOR_SWITCH::GetPins() const
std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> SPICE_GENERATOR_SWITCH::GetPins() const
{
switch( m_model.GetType() )
{

View File

@ -36,7 +36,7 @@ public:
std::string ItemLine( const SPICE_ITEM& aItem ) const override;
std::string ItemParams() const override;
std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> GetPins() const override;
std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> GetPins() const override;
};

View File

@ -123,8 +123,8 @@ std::string SPICE_GENERATOR::ItemLine( const SPICE_ITEM& aItem ) const
if( item.pinNetNames.empty() )
{
for( const SIM_MODEL::PIN& pin : GetPins() )
item.pinNetNames.push_back( pin.name );
for( const SIM_MODEL_PIN& pin : GetPins() )
item.pinNetNames.push_back( pin.modelPinName );
}
std::string result;
@ -151,7 +151,7 @@ std::string SPICE_GENERATOR::ItemPins( const SPICE_ITEM& aItem ) const
std::string result;
int ncCounter = 0;
for( const SIM_MODEL::PIN& pin : GetPins() )
for( const SIM_MODEL_PIN& pin : GetPins() )
{
auto it = std::find( aItem.pinNumbers.begin(), aItem.pinNumbers.end(),
pin.symbolPinNumber );

View File

@ -65,7 +65,7 @@ public:
virtual std::string Preview( const SPICE_ITEM& aItem ) const;
protected:
virtual std::vector<std::reference_wrapper<const SIM_MODEL::PIN>> GetPins() const
virtual std::vector<std::reference_wrapper<const SIM_MODEL_PIN>> GetPins() const
{
return m_model.GetPins();
}

View File

@ -602,7 +602,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
int modelPinIndex = model.FindModelPinIndex( pin->GetNumber().ToStdString() );
if( modelPinIndex != SIM_MODEL::PIN::NOT_CONNECTED )
if( modelPinIndex != SIM_MODEL_PIN::NOT_CONNECTED )
{
wxString name = currentNames.at( modelPinIndex );
simFrame->AddCurrentTrace( name );

View File

@ -182,8 +182,8 @@ BOOST_AUTO_TEST_CASE( Subckts )
BOOST_CHECK_EQUAL( model.GetParam( 0 ).info.name, "PARAM1" );
BOOST_CHECK_EQUAL( model.GetParam( 0 ).info.defaultValue, "1" );
BOOST_REQUIRE_EQUAL( model.GetPinCount(), 2 );
BOOST_CHECK_EQUAL( model.GetPin( 0 ).name, "1" );
BOOST_CHECK_EQUAL( model.GetPin( 1 ).name, "2" );
BOOST_CHECK_EQUAL( model.GetPin( 0 ).modelPinName, "1" );
BOOST_CHECK_EQUAL( model.GetPin( 1 ).modelPinName, "2" );
break;
case 2:
@ -192,8 +192,8 @@ BOOST_AUTO_TEST_CASE( Subckts )
BOOST_REQUIRE_EQUAL( model.GetParamCount(), 1 );
BOOST_CHECK_EQUAL( model.GetParam( 0 ).info.name, "PARAM1" );
BOOST_CHECK_EQUAL( model.GetParam( 0 ).info.defaultValue, "1.0" );
BOOST_CHECK_EQUAL( model.GetPin( 0 ).name, "1" );
BOOST_CHECK_EQUAL( model.GetPin( 1 ).name, "2" );
BOOST_CHECK_EQUAL( model.GetPin( 0 ).modelPinName, "1" );
BOOST_CHECK_EQUAL( model.GetPin( 1 ).modelPinName, "2" );
break;
case 3:
@ -205,8 +205,8 @@ BOOST_AUTO_TEST_CASE( Subckts )
BOOST_CHECK_EQUAL( model.GetParam( 1 ).info.name, "param2" );
BOOST_CHECK_EQUAL( model.GetParam( 1 ).info.defaultValue, "2.2e+2" );
BOOST_REQUIRE_EQUAL( model.GetPinCount(), 2 );
BOOST_CHECK_EQUAL( model.GetPin( 0 ).name, "1" );
BOOST_CHECK_EQUAL( model.GetPin( 1 ).name, "2" );
BOOST_CHECK_EQUAL( model.GetPin( 0 ).modelPinName, "1" );
BOOST_CHECK_EQUAL( model.GetPin( 1 ).modelPinName, "2" );
break;
case 4:
@ -218,8 +218,8 @@ BOOST_AUTO_TEST_CASE( Subckts )
BOOST_CHECK_EQUAL( model.GetParam( 1 ).info.name, "param2" );
BOOST_CHECK_EQUAL( model.GetParam( 1 ).info.defaultValue, "2.2E+2" );
BOOST_REQUIRE_EQUAL( model.GetPinCount(), 2 );
BOOST_CHECK_EQUAL( model.GetPin( 0 ).name, "1" );
BOOST_CHECK_EQUAL( model.GetPin( 1 ).name, "2" );
BOOST_CHECK_EQUAL( model.GetPin( 0 ).modelPinName, "1" );
BOOST_CHECK_EQUAL( model.GetPin( 1 ).modelPinName, "2" );
break;
case 5: