|
|
@ -3,7 +3,7 @@ |
|
|
|
* |
|
|
|
* Copyright (C) 1992-2013 jp.charras at wanadoo.fr |
|
|
|
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> |
|
|
|
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.TXT for contributors. |
|
|
|
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.TXT for contributors. |
|
|
|
* |
|
|
|
* This program is free software; you can redistribute it and/or |
|
|
|
* modify it under the terms of the GNU General Public License |
|
|
@ -239,11 +239,10 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void NETLIST_EXPORTER_SPICE::ConvertToSpiceMarkup( std::string& aNetName ) |
|
|
|
void NETLIST_EXPORTER_SPICE::ConvertToSpiceMarkup( wxString* aNetName ) |
|
|
|
{ |
|
|
|
MARKUP::MARKUP_PARSER markupParser( aNetName ); |
|
|
|
MARKUP::MARKUP_PARSER markupParser( aNetName->ToStdString() ); |
|
|
|
std::unique_ptr<MARKUP::NODE> root = markupParser.Parse(); |
|
|
|
std::string converted; |
|
|
|
|
|
|
|
std::function<void( const std::unique_ptr<MARKUP::NODE>&)> convertMarkup = |
|
|
|
[&]( const std::unique_ptr<MARKUP::NODE>& aNode ) |
|
|
@ -255,7 +254,7 @@ void NETLIST_EXPORTER_SPICE::ConvertToSpiceMarkup( std::string& aNetName ) |
|
|
|
if( aNode->isOverbar() ) |
|
|
|
{ |
|
|
|
// ~{CLK} is a different signal than CLK
|
|
|
|
converted += '~'; |
|
|
|
*aNetName += '~'; |
|
|
|
} |
|
|
|
else if( aNode->isSubscript() || aNode->isSuperscript() ) |
|
|
|
{ |
|
|
@ -263,7 +262,7 @@ void NETLIST_EXPORTER_SPICE::ConvertToSpiceMarkup( std::string& aNetName ) |
|
|
|
} |
|
|
|
|
|
|
|
if( aNode->has_content() ) |
|
|
|
converted += aNode->string(); |
|
|
|
*aNetName += aNode->string(); |
|
|
|
} |
|
|
|
|
|
|
|
for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children ) |
|
|
@ -271,43 +270,46 @@ void NETLIST_EXPORTER_SPICE::ConvertToSpiceMarkup( std::string& aNetName ) |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
*aNetName = wxEmptyString; |
|
|
|
convertMarkup( root ); |
|
|
|
|
|
|
|
// Replace all ngspice-disallowed chars in netnames by a '_'
|
|
|
|
std::replace( converted.begin(), converted.end(), '%', '_' ); |
|
|
|
std::replace( converted.begin(), converted.end(), '(', '_' ); |
|
|
|
std::replace( converted.begin(), converted.end(), ')', '_' ); |
|
|
|
std::replace( converted.begin(), converted.end(), ',', '_' ); |
|
|
|
std::replace( converted.begin(), converted.end(), '[', '_' ); |
|
|
|
std::replace( converted.begin(), converted.end(), ']', '_' ); |
|
|
|
std::replace( converted.begin(), converted.end(), '<', '_' ); |
|
|
|
std::replace( converted.begin(), converted.end(), '>', '_' ); |
|
|
|
std::replace( converted.begin(), converted.end(), '~', '_' ); |
|
|
|
std::replace( converted.begin(), converted.end(), ' ', '_' ); |
|
|
|
|
|
|
|
aNetName = converted; |
|
|
|
aNetName->Replace( '%', '_' ); |
|
|
|
aNetName->Replace( '(', '_' ); |
|
|
|
aNetName->Replace( ')', '_' ); |
|
|
|
aNetName->Replace( ',', '_' ); |
|
|
|
aNetName->Replace( '[', '_' ); |
|
|
|
aNetName->Replace( ']', '_' ); |
|
|
|
aNetName->Replace( '<', '_' ); |
|
|
|
aNetName->Replace( '>', '_' ); |
|
|
|
aNetName->Replace( '~', '_' ); |
|
|
|
aNetName->Replace( ' ', '_' ); |
|
|
|
|
|
|
|
// A net name on the root sheet with a label '/foo' is going to get titled "//foo". This
|
|
|
|
// will trip up ngspice as "//" opens a line comment.
|
|
|
|
if( aNetName->StartsWith( wxS( "//" ) ) ) |
|
|
|
aNetName->Replace( wxS( "//" ), wxS( "/root/" ), false /* replace all */ ); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::string NETLIST_EXPORTER_SPICE::GetItemName( const std::string& aRefName ) const |
|
|
|
wxString NETLIST_EXPORTER_SPICE::GetItemName( const wxString& aRefName ) const |
|
|
|
{ |
|
|
|
const SPICE_ITEM* item = FindItem( aRefName ); |
|
|
|
if( const SPICE_ITEM* item = FindItem( aRefName ) ) |
|
|
|
return item->model->SpiceGenerator().ItemName( *item ); |
|
|
|
|
|
|
|
if( !item ) |
|
|
|
return ""; |
|
|
|
|
|
|
|
return item->model->SpiceGenerator().ItemName( *item ); |
|
|
|
return wxEmptyString; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const SPICE_ITEM* NETLIST_EXPORTER_SPICE::FindItem( const std::string& aRefName ) const |
|
|
|
const SPICE_ITEM* NETLIST_EXPORTER_SPICE::FindItem( const wxString& aRefName ) const |
|
|
|
{ |
|
|
|
const std::string refName = aRefName.ToStdString(); |
|
|
|
const std::list<SPICE_ITEM>& spiceItems = GetItems(); |
|
|
|
|
|
|
|
auto it = std::find_if( spiceItems.begin(), spiceItems.end(), |
|
|
|
[aRefName]( const SPICE_ITEM& item ) |
|
|
|
[refName]( const SPICE_ITEM& item ) |
|
|
|
{ |
|
|
|
return item.refName == aRefName; |
|
|
|
return item.refName == refName; |
|
|
|
} ); |
|
|
|
|
|
|
|
if( it != spiceItems.end() ) |
|
|
@ -502,12 +504,14 @@ void NETLIST_EXPORTER_SPICE::readPinNetNames( SCH_SYMBOL& aSymbol, SPICE_ITEM& a |
|
|
|
{ |
|
|
|
for( const PIN_INFO& pinInfo : aPins ) |
|
|
|
{ |
|
|
|
std::string netName = GenerateItemPinNetName( pinInfo.netName.ToStdString(), aNcCounter ); |
|
|
|
wxString netName = GenerateItemPinNetName( pinInfo.netName, aNcCounter ); |
|
|
|
|
|
|
|
aItem.pinNetNames.push_back( netName ); |
|
|
|
aItem.pinNetNames.push_back( netName.ToStdString() ); |
|
|
|
m_nets.insert( netName ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void NETLIST_EXPORTER_SPICE::getNodePattern( SPICE_ITEM& aItem, |
|
|
|
std::vector<std::string>& aModifiers ) |
|
|
|
{ |
|
|
@ -710,16 +714,15 @@ void NETLIST_EXPORTER_SPICE::WriteDirectives( const wxString& aSimCommand, unsig |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::string NETLIST_EXPORTER_SPICE::GenerateItemPinNetName( const std::string& aNetName, |
|
|
|
int& aNcCounter ) const |
|
|
|
wxString NETLIST_EXPORTER_SPICE::GenerateItemPinNetName( const wxString& aNetName, |
|
|
|
int& aNcCounter ) const |
|
|
|
{ |
|
|
|
std::string netName = aNetName; |
|
|
|
wxString netName = UnescapeString( aNetName ); |
|
|
|
|
|
|
|
ConvertToSpiceMarkup( netName ); |
|
|
|
netName = std::string( UnescapeString( netName ).ToUTF8() ); |
|
|
|
ConvertToSpiceMarkup( &netName ); |
|
|
|
|
|
|
|
if( netName == "" ) |
|
|
|
netName = fmt::format( "NC-{}", aNcCounter++ ); |
|
|
|
if( netName.IsEmpty() ) |
|
|
|
netName.Printf( wxS( "NC-%d" ), aNcCounter++ ); |
|
|
|
|
|
|
|
return netName; |
|
|
|
} |
|
|
|