Read/write "no net" (0) for pins with a no-connection marker.

Fixes https://gitlab.com/kicad/code/kicad/issues/2273

Fixes https://gitlab.com/kicad/code/kicad/issues/5587
This commit is contained in:
Jeff Young 2020-11-23 19:46:42 +00:00
parent c94001839b
commit 5f8a8c6850
2 changed files with 69 additions and 46 deletions

View File

@ -566,7 +566,7 @@ XNODE* NETLIST_EXPORTER_XML::makeListOfNets( unsigned aCtl )
wxString netName;
wxString ref;
XNODE* xnet = 0;
XNODE* xnet = nullptr;
/* output:
<net code="123" name="/cfcard.sch/WAIT#">
@ -575,19 +575,31 @@ XNODE* NETLIST_EXPORTER_XML::makeListOfNets( unsigned aCtl )
</net>
*/
int code = 0;
typedef std::pair<SCH_PIN*, SCH_SHEET_PATH> MEMBER_RECORD;
typedef std::pair<wxString, std::vector<MEMBER_RECORD>> NET_RECORD;
std::vector<NET_RECORD*> nets;
// Pre-allocate the no-net node
nets.emplace_back( new NET_RECORD() );
for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() )
{
bool added = false;
wxString net_name = it.first.first;
auto subgraphs = it.second;
wxString net_name = it.first.first;
auto subgraphs = it.second;
NET_RECORD* net_record;
// Code starts at 1
code++;
if( subgraphs.empty() )
continue;
XNODE* xnode;
std::vector<std::pair<SCH_PIN*, SCH_SHEET_PATH>> sorted_items;
if( !subgraphs[0]->m_strong_driver && subgraphs[0]->m_no_connect )
{
net_record = nets[0];
}
else
{
nets.emplace_back( new NET_RECORD( net_name, std::vector<MEMBER_RECORD>() ) );
net_record = nets.back();
}
for( CONNECTION_SUBGRAPH* subgraph : subgraphs )
{
@ -607,40 +619,52 @@ XNODE* NETLIST_EXPORTER_XML::makeListOfNets( unsigned aCtl )
continue;
}
sorted_items.emplace_back( pin, sheet );
net_record->second.emplace_back( pin, sheet );
}
}
}
}
for( int i = 0; i < (int) nets.size(); ++i )
{
NET_RECORD* net_record = nets[i];
bool added = false;
XNODE* xnode;
// Netlist ordering: Net name, then ref des, then pin name
std::sort( sorted_items.begin(), sorted_items.end(),
std::sort( net_record->second.begin(), net_record->second.end(),
[]( const std::pair<SCH_PIN*, SCH_SHEET_PATH>& a,
const std::pair<SCH_PIN*, SCH_SHEET_PATH>& b )
{
wxString ref_a = a.first->GetParentSymbol()->GetRef( &a.second );
wxString ref_b = b.first->GetParentSymbol()->GetRef( &b.second );
SCH_PIN* pinA = a.first;
SCH_PIN* pinB = b.first;
wxString refA = pinA->GetParentSymbol()->GetRef( &a.second );
wxString refB = pinB->GetParentSymbol()->GetRef( &b.second );
if( ref_a == ref_b )
return a.first->GetNumber() < b.first->GetNumber();
if( refA == refB )
return pinA->GetNumber() < pinB->GetNumber();
return ref_a < ref_b;
return refA < refB;
} );
// Some duplicates can exist, for example on multi-unit parts with duplicated
// pins across units. If the user connects the pins on each unit, they will
// appear on separate subgraphs. Remove those here:
sorted_items.erase( std::unique( sorted_items.begin(), sorted_items.end(),
[]( const std::pair<SCH_PIN*, SCH_SHEET_PATH>& a,
const std::pair<SCH_PIN*, SCH_SHEET_PATH>& b )
{
wxString ref_a = a.first->GetParentSymbol()->GetRef( &a.second );
wxString ref_b = b.first->GetParentSymbol()->GetRef( &b.second );
net_record->second.erase(
std::unique( net_record->second.begin(), net_record->second.end(),
[]( const std::pair<SCH_PIN*, SCH_SHEET_PATH>& a,
const std::pair<SCH_PIN*, SCH_SHEET_PATH>& b )
{
SCH_PIN* pinA = a.first;
SCH_PIN* pinB = b.first;
wxString refA = pinA->GetParentSymbol()->GetRef( &a.second );
wxString refB = pinB->GetParentSymbol()->GetRef( &b.second );
return ref_a == ref_b && a.first->GetNumber() == b.first->GetNumber();
} ),
sorted_items.end() );
return refA == refB && pinA->GetNumber() == pinB->GetNumber();
} ),
net_record->second.end() );
for( const std::pair<SCH_PIN*, SCH_SHEET_PATH>& pair : sorted_items )
for( const std::pair<SCH_PIN*, SCH_SHEET_PATH>& pair : net_record->second )
{
SCH_PIN* pin = pair.first;
SCH_SHEET_PATH sheet = pair.second;
@ -655,9 +679,9 @@ XNODE* NETLIST_EXPORTER_XML::makeListOfNets( unsigned aCtl )
if( !added )
{
xnets->AddChild( xnet = node( "net" ) );
netCodeTxt.Printf( "%d", code );
netCodeTxt.Printf( "%d", i );
xnet->AddAttribute( "code", netCodeTxt );
xnet->AddAttribute( "name", net_name );
xnet->AddAttribute( "name", net_record->first );
added = true;
}

View File

@ -189,7 +189,6 @@ void KICAD_NETLIST_PARSER::parseNet()
wxString reference;
wxString pin_number;
wxString pin_function;
int nodecount = 0;
// The token net was read, so the next data is (code <number>)
while( (token = NextTok()) != T_EOF )
@ -211,10 +210,6 @@ void KICAD_NETLIST_PARSER::parseNet()
NeedSYMBOLorNUMBER();
name = FROM_UTF8( CurText() );
NeedRIGHT();
if( name.IsEmpty() ) // Give a dummy net name like N-000109
name = wxT("N-00000") + code;
break;
case T_node:
@ -253,21 +248,25 @@ void KICAD_NETLIST_PARSER::parseNet()
}
}
component = m_netlist->GetComponentByReference( reference );
// Cannot happen if the netlist is valid.
if( component == NULL )
if( strtol( code, NULL, 10 ) >= 1 )
{
wxString msg;
msg.Printf( _( "Cannot find component with reference designator \"%s\" in netlist." ),
reference );
THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), m_lineReader->Line(),
m_lineReader->LineNumber(), m_lineReader->Length() );
}
if( name.IsEmpty() ) // Give a dummy net name like N-000009
name = wxT("N-00000") + code;
component->AddNet( pin_number, name, pin_function );
nodecount++;
component = m_netlist->GetComponentByReference( reference );
// Cannot happen if the netlist is valid.
if( component == NULL )
{
wxString msg;
msg.Printf( _( "Cannot find component with ref '%s' in netlist." ),
reference );
THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), m_lineReader->Line(),
m_lineReader->LineNumber(), m_lineReader->Length() );
}
component->AddNet( pin_number, name, pin_function );
}
break;
default: