Fix netlist error when editing schematic symbols in place.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/8798
This commit is contained in:
Wayne Stambaugh 2021-07-30 18:37:18 -04:00
parent 5155093ec0
commit f485ba9338
4 changed files with 107 additions and 82 deletions

View File

@ -72,7 +72,10 @@ wxString NETLIST_EXPORTER_BASE::MakeCommandLine( const wxString& aFormatString,
SCH_SYMBOL* NETLIST_EXPORTER_BASE::findNextSymbol( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath )
{
wxString ref;
wxCHECK( aItem, nullptr );
wxCHECK( aSheetPath, nullptr );
wxString ref;
if( aItem->Type() != SCH_SYMBOL_T )
return nullptr;
@ -87,16 +90,16 @@ SCH_SYMBOL* NETLIST_EXPORTER_BASE::findNextSymbol( EDA_ITEM* aItem, SCH_SHEET_PA
if( ref[0] == wxChar( '#' ) )
return nullptr;
// if( symbol->m_FlagControlMulti == 1 )
// continue; /* yes */
// removed because with multiple instances of one schematic (several sheets pointing to
// 1 screen), this will be erroneously be toggled.
SCH_SCREEN* screen = aSheetPath->LastScreen();
if( !symbol->GetLibSymbolRef() )
return nullptr;
wxCHECK( screen, nullptr );
LIB_SYMBOL* libSymbol = screen->GetLibSymbols()[ symbol->GetSchSymbolLibraryName() ];
wxCHECK( libSymbol, nullptr );
// If symbol is a "multi parts per package" type
if( symbol->GetLibSymbolRef()->GetUnitCount() > 1 )
if( libSymbol->GetUnitCount() > 1 )
{
// test if this reference has already been processed, and if so skip
if( m_referencesAlreadyFound.Lookup( ref ) )
@ -104,7 +107,7 @@ SCH_SYMBOL* NETLIST_EXPORTER_BASE::findNextSymbol( EDA_ITEM* aItem, SCH_SHEET_PA
}
// record the usage of this library symbol entry.
m_libParts.insert( symbol->GetLibSymbolRef().get() ); // rejects non-unique pointers
m_libParts.insert( libSymbol ); // rejects non-unique pointers
return symbol;
}

View File

@ -90,72 +90,6 @@ struct PIN_INFO
*/
class NETLIST_EXPORTER_BASE
{
protected:
/// Used to temporarily store and filter the list of pins of a schematic symbol when
/// generating schematic symbol data in netlist (comp section). No ownership of members.
/// TODO(snh): Descope this object
std::vector<PIN_INFO> m_sortedSymbolPinList;
/// Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than
/// once
UNIQUE_STRINGS m_referencesAlreadyFound;
/// unique library symbols used. LIB_SYMBOL items are sorted by names
std::set<LIB_SYMBOL*, LIB_SYMBOL_LESS_THAN> m_libParts;
/// The schematic we're generating a netlist for
SCHEMATIC_IFACE* m_schematic;
/// The schematic's CurrentSheet when we entered. Restore on exiting.
SCH_SHEET_PATH m_savedCurrentSheet;
/**
* Find a symbol from the DrawList and builds its pin list in m_sortedSymbolPinList.
*
* This list is sorted by pin number. The symbol is the next actual symbol after \a aSymbol.
* Power symbols and virtual symbols that have their reference designators starting with
* '#' are skipped.
* if aKeepUnconnectedPins = false, unconnected pins will be removed from list
* but usually we need all pins in netlists.
*/
void CreatePinList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPath,
bool aKeepUnconnectedPins );
/**
* Check if the given symbol should be processed for netlisting.
*
* Prevent processing multi-unit symbols more than once, etc.
*
* @param aItem is a symbol to check
* @param aSheetPath is the sheet to check the symbol for
* @return the symbol if it should be processed, or nullptr
*/
SCH_SYMBOL* findNextSymbol( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath );
/**
* Erase duplicate pins from m_sortedSymbolPinList (i.e. set pointer in this list to NULL).
*
* (This is a list of pins found in the whole schematic, for a single symbol.) These
* duplicate pins were put in list because some pins (power pins...) are found more than
* once when in "multiple symbols per package" symbols. For instance, a 74ls00 has 4 symbols,
* and therefore the VCC pin and GND pin appears 4 times in the list.
* Note: this list *MUST* be sorted by pin number (.m_PinNum member value)
* Also set the m_Flag member of "removed" NETLIST_OBJECT pin item to 1
*/
void eraseDuplicatePins();
/**
* Find all units for symbols with multiple symbols per package.
*
* Search the entire design for all units of \a aSymbol based on matching reference
* designator, and for each unit, add all its pins to the temporary sorted pin list,
* m_sortedSymbolPinList.
* if aKeepUnconnectedPins = false, unconnected pins will be removed from list
* but usually we need all pins in netlists.
*/
void findAllUnitsOfSymbol( SCH_SYMBOL* aSchSymbol, LIB_SYMBOL* aLibSymbol,
SCH_SHEET_PATH* aSheetPath, bool aKeepUnconnectedPins );
public:
/**
* @param aMasterList we take ownership of this here.
@ -213,6 +147,72 @@ public:
static wxString MakeCommandLine( const wxString& aFormatString, const wxString& aNetlistFile,
const wxString& aFinalFile,
const wxString& aProjectDirectory );
protected:
/**
* Find a symbol from the DrawList and builds its pin list in m_sortedSymbolPinList.
*
* This list is sorted by pin number. The symbol is the next actual symbol after \a aSymbol.
* Power symbols and virtual symbols that have their reference designators starting with
* '#' are skipped.
* if aKeepUnconnectedPins = false, unconnected pins will be removed from list
* but usually we need all pins in netlists.
*/
void CreatePinList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPath,
bool aKeepUnconnectedPins );
/**
* Check if the given symbol should be processed for netlisting.
*
* Prevent processing multi-unit symbols more than once, etc.
*
* @param aItem is a symbol to check
* @param aSheetPath is the sheet to check the symbol for
* @return the symbol if it should be processed, or nullptr
*/
SCH_SYMBOL* findNextSymbol( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath );
/**
* Erase duplicate pins from m_sortedSymbolPinList (i.e. set pointer in this list to NULL).
*
* (This is a list of pins found in the whole schematic, for a single symbol.) These
* duplicate pins were put in list because some pins (power pins...) are found more than
* once when in "multiple symbols per package" symbols. For instance, a 74ls00 has 4 symbols,
* and therefore the VCC pin and GND pin appears 4 times in the list.
* Note: this list *MUST* be sorted by pin number (.m_PinNum member value)
* Also set the m_Flag member of "removed" NETLIST_OBJECT pin item to 1
*/
void eraseDuplicatePins();
/**
* Find all units for symbols with multiple symbols per package.
*
* Search the entire design for all units of \a aSymbol based on matching reference
* designator, and for each unit, add all its pins to the temporary sorted pin list,
* m_sortedSymbolPinList.
* if aKeepUnconnectedPins = false, unconnected pins will be removed from list
* but usually we need all pins in netlists.
*/
void findAllUnitsOfSymbol( SCH_SYMBOL* aSchSymbol, LIB_SYMBOL* aLibSymbol,
SCH_SHEET_PATH* aSheetPath, bool aKeepUnconnectedPins );
/// Used to temporarily store and filter the list of pins of a schematic symbol when
/// generating schematic symbol data in netlist (comp section). No ownership of members.
/// TODO(snh): Descope this object
std::vector<PIN_INFO> m_sortedSymbolPinList;
/// Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than
/// once
UNIQUE_STRINGS m_referencesAlreadyFound;
/// unique library symbols used. LIB_SYMBOL items are sorted by names
std::set<LIB_SYMBOL*, LIB_SYMBOL_LESS_THAN> m_libParts;
/// The schematic we're generating a netlist for
SCHEMATIC_IFACE* m_schematic;
/// The schematic's CurrentSheet when we entered. Restore on exiting.
SCH_SHEET_PATH m_savedCurrentSheet;
};
#endif

View File

@ -297,12 +297,23 @@ XNODE* NETLIST_EXPORTER_XML::makeSymbols( unsigned aCtl )
// "logical" library name, which is in anticipation of a better search algorithm
// for parts based on "logical_lib.part" and where logical_lib is merely the library
// name minus path and extension.
if( symbol->GetLibSymbolRef() )
xlibsource->AddAttribute( "lib",
symbol->GetLibSymbolRef()->GetLibId().GetLibNickname() );
wxString libName;
wxString partName;
if( symbol->UseLibIdLookup() )
{
libName = symbol->GetLibId().GetLibNickname();
partName = symbol->GetLibId().GetLibItemName();
}
else
{
partName = symbol->GetSchSymbolLibraryName();
}
xlibsource->AddAttribute( "lib", libName );
// We only want the symbol name, not the full LIB_ID.
xlibsource->AddAttribute( "part", symbol->GetLibId().GetLibItemName() );
xlibsource->AddAttribute( "part", partName );
xlibsource->AddAttribute( "description", symbol->GetDescription() );

View File

@ -178,16 +178,27 @@ void SCH_SCREEN::Append( SCH_ITEM* aItem )
int cnt = 1;
wxString newName;
newName.Printf( "%s_%d", symbol->GetLibId().Format().wx_str(), cnt );
newName.Printf( "%s_%d", symbol->GetLibId().GetUniStringLibItemName(),
cnt );
while( m_libSymbols.find( newName ) != m_libSymbols.end() )
{
cnt += 1;
newName.Printf( "%s_%d", symbol->GetLibId().Format().wx_str(), cnt );
newName.Printf( "%s_%d", symbol->GetLibId().GetUniStringLibItemName(),
cnt );
}
// Update the schematic symbol library link as this symbol only exists
// in the schematic.
symbol->SetSchSymbolLibraryName( newName );
m_libSymbols[newName] = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
LIB_ID newLibId( wxEmptyString, newName );
newLibSymbol->SetLibId( newLibId );
newLibSymbol->SetName( newName );
symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
m_libSymbols[newName] = newLibSymbol;
}
}
}