Fix Bug #1545708 (global bus labels ignored). This is a very old bug.
This commit is contained in:
parent
be2f79af28
commit
ca5e66a57f
|
@ -1,9 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -315,6 +315,32 @@ void NETLIST_OBJECT::ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NETLIST_OBJECT::IsLabelGlobal() const
|
||||||
|
{
|
||||||
|
// return true if the object is a global label
|
||||||
|
// * a actual global label
|
||||||
|
// * a pin label coming from a invisible power pin
|
||||||
|
return ( m_Type == NET_PINLABEL ) ||
|
||||||
|
( m_Type == NET_GLOBLABEL ) ||
|
||||||
|
( m_Type == NET_GLOBBUSLABELMEMBER );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NETLIST_OBJECT::IsLabelBusMemberType() const
|
||||||
|
{
|
||||||
|
// return true if the object is a bus label member build from a
|
||||||
|
// schematic bus label (like label[xx..yy)
|
||||||
|
// They are labels with very specific properties, especially for connection
|
||||||
|
// between them: 2 bus label members can be connected only
|
||||||
|
// if they have the same member value.
|
||||||
|
return ( m_Type == NET_SHEETBUSLABELMEMBER ) ||
|
||||||
|
( m_Type == NET_BUSLABELMEMBER ) ||
|
||||||
|
( m_Type == NET_HIERBUSLABELMEMBER ) ||
|
||||||
|
( m_Type == NET_GLOBBUSLABELMEMBER );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return the net name of the item
|
* return the net name of the item
|
||||||
*/
|
*/
|
||||||
|
@ -373,7 +399,7 @@ wxString NETLIST_OBJECT::GetShortNetName() const
|
||||||
* Set m_netNameCandidate to a connected item which will
|
* Set m_netNameCandidate to a connected item which will
|
||||||
* be used to calcule the net name of the item
|
* be used to calcule the net name of the item
|
||||||
* Obviously the candidate can be only a label
|
* Obviously the candidate can be only a label
|
||||||
* when there is no label on the net a pad which will
|
* If there is no label on the net, a pad name will be
|
||||||
* used to build a net name (something like Cmp<REF>_Pad<PAD_NAME>
|
* used to build a net name (something like Cmp<REF>_Pad<PAD_NAME>
|
||||||
* @param aCandidate = the connected item candidate
|
* @param aCandidate = the connected item candidate
|
||||||
*/
|
*/
|
||||||
|
@ -385,6 +411,8 @@ void NETLIST_OBJECT::SetNetNameCandidate( NETLIST_OBJECT* aCandidate )
|
||||||
case NET_LABEL:
|
case NET_LABEL:
|
||||||
case NET_PINLABEL:
|
case NET_PINLABEL:
|
||||||
case NET_GLOBLABEL:
|
case NET_GLOBLABEL:
|
||||||
|
case NET_GLOBBUSLABELMEMBER:
|
||||||
|
case NET_SHEETBUSLABELMEMBER:
|
||||||
case NET_PIN:
|
case NET_PIN:
|
||||||
m_netNameCandidate = aCandidate;
|
m_netNameCandidate = aCandidate;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -59,6 +59,8 @@ enum NETLIST_ITEM_T
|
||||||
* the bus label (like DATA[0..7] is
|
* the bus label (like DATA[0..7] is
|
||||||
* converted to n single labels like
|
* converted to n single labels like
|
||||||
* DATA0, DATA1 ...
|
* DATA0, DATA1 ...
|
||||||
|
* These objects are living only in the current
|
||||||
|
* NETLIST_OBJECT_LIST, not in shematic.
|
||||||
*/
|
*/
|
||||||
NET_GLOBBUSLABELMEMBER, // see NET_BUSLABELMEMBER, used when a
|
NET_GLOBBUSLABELMEMBER, // see NET_BUSLABELMEMBER, used when a
|
||||||
// global bus label is found
|
// global bus label is found
|
||||||
|
@ -217,10 +219,19 @@ public:
|
||||||
* (i.e. an real global label or a pin label coming
|
* (i.e. an real global label or a pin label coming
|
||||||
* from a power pin invisible
|
* from a power pin invisible
|
||||||
*/
|
*/
|
||||||
bool IsLabelGlobal() const
|
bool IsLabelGlobal() const;
|
||||||
{
|
|
||||||
return ( m_Type == NET_PINLABEL ) || ( m_Type == NET_GLOBLABEL );
|
/**
|
||||||
}
|
* Function IsLabelBusMemberType
|
||||||
|
* @return true if the object is a bus label member build from a
|
||||||
|
* schematic bus label (like label[xx..yy], xx and yy are the first and last
|
||||||
|
* bus member id)
|
||||||
|
* bus label members have specific properties:
|
||||||
|
* they do not live in schematic
|
||||||
|
* they have specific properties in connections:
|
||||||
|
* 2 bus label members can be connected connected only if they have the same member value.
|
||||||
|
*/
|
||||||
|
bool IsLabelBusMemberType() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function IsLabelType
|
* Function IsLabelType
|
||||||
|
@ -436,7 +447,7 @@ private:
|
||||||
return Objet1->m_SheetPath.Cmp( Objet2->m_SheetPath ) < 0;
|
return Objet1->m_SheetPath.Cmp( Objet2->m_SheetPath ) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Propagate net codes from a parent sheet to an include sheet,
|
* Propagate net codes from a parent sheet to an include sheet,
|
||||||
* from a pin sheet connection
|
* from a pin sheet connection
|
||||||
*/
|
*/
|
||||||
|
@ -444,8 +455,8 @@ private:
|
||||||
|
|
||||||
void pointToPointConnect( NETLIST_OBJECT* aRef, bool aIsBus, int start );
|
void pointToPointConnect( NETLIST_OBJECT* aRef, bool aIsBus, int start );
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Search connections betweena junction and segments
|
* Search connections between a junction and segments
|
||||||
* Propagate the junction net code to objects connected by this junction.
|
* Propagate the junction net code to objects connected by this junction.
|
||||||
* The junction must have a valid net code
|
* The junction must have a valid net code
|
||||||
* The list of objects is expected sorted by sheets.
|
* The list of objects is expected sorted by sheets.
|
||||||
|
@ -453,9 +464,16 @@ private:
|
||||||
*/
|
*/
|
||||||
void segmentToPointConnect( NETLIST_OBJECT* aJonction, bool aIsBus, int aIdxStart );
|
void segmentToPointConnect( NETLIST_OBJECT* aJonction, bool aIsBus, int aIdxStart );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function connectBusLabels
|
||||||
|
* Propagate the net code (and create it, if not yet existing) between
|
||||||
|
* all bus label member objects connected by they name.
|
||||||
|
* Search is done in the entire list
|
||||||
|
*/
|
||||||
void connectBusLabels();
|
void connectBusLabels();
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Set the m_FlagOfConnection member of items in list
|
* Set the m_FlagOfConnection member of items in list
|
||||||
* depending on the connection type:
|
* depending on the connection type:
|
||||||
* UNCONNECTED, PAD_CONNECT or NOCONNECT_SYMBOL_PRESENT
|
* UNCONNECTED, PAD_CONNECT or NOCONNECT_SYMBOL_PRESENT
|
||||||
|
|
|
@ -228,7 +228,7 @@ bool NETLIST_OBJECT_LIST::BuildNetListInfo( SCH_SHEET_LIST& aSheets )
|
||||||
switch( net_item->m_Type )
|
switch( net_item->m_Type )
|
||||||
{
|
{
|
||||||
case NET_ITEM_UNSPECIFIED:
|
case NET_ITEM_UNSPECIFIED:
|
||||||
wxMessageBox( wxT( "BuildNetListBase() error" ) );
|
wxMessageBox( wxT( "BuildNetListInfo() error" ) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NET_PIN:
|
case NET_PIN:
|
||||||
|
@ -397,8 +397,8 @@ bool NETLIST_OBJECT_LIST::BuildNetListInfo( SCH_SHEET_LIST& aSheets )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to give a priority to sort labels:
|
// Helper function to give a priority to sort labels:
|
||||||
// NET_PINLABEL and NET_GLOBLABEL are global labels
|
// NET_PINLABEL, NET_GLOBBUSLABELMEMBER and NET_GLOBLABEL are global labels
|
||||||
// and the priority is hight
|
// and the priority is high
|
||||||
static int getPriority( const NETLIST_OBJECT* Objet )
|
static int getPriority( const NETLIST_OBJECT* Objet )
|
||||||
{
|
{
|
||||||
switch( Objet->m_Type )
|
switch( Objet->m_Type )
|
||||||
|
@ -407,7 +407,8 @@ static int getPriority( const NETLIST_OBJECT* Objet )
|
||||||
case NET_LABEL: return 2;
|
case NET_LABEL: return 2;
|
||||||
case NET_HIERLABEL: return 3;
|
case NET_HIERLABEL: return 3;
|
||||||
case NET_PINLABEL: return 4;
|
case NET_PINLABEL: return 4;
|
||||||
case NET_GLOBLABEL: return 5;
|
case NET_GLOBBUSLABELMEMBER: return 5;
|
||||||
|
case NET_GLOBLABEL: return 6;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,11 +418,24 @@ static int getPriority( const NETLIST_OBJECT* Objet )
|
||||||
|
|
||||||
/* function evalLabelsPriority used by findBestNetNameForEachNet()
|
/* function evalLabelsPriority used by findBestNetNameForEachNet()
|
||||||
* evalLabelsPriority calculates the priority of alabel1 and aLabel2
|
* evalLabelsPriority calculates the priority of alabel1 and aLabel2
|
||||||
* return true if alabel1 has a highter priority than aLabel2
|
* return true if alabel1 has a higher priority than aLabel2
|
||||||
*/
|
*/
|
||||||
static bool evalLabelsPriority( const NETLIST_OBJECT* aLabel1,
|
static bool evalLabelsPriority( const NETLIST_OBJECT* aLabel1,
|
||||||
const NETLIST_OBJECT* aLabel2 )
|
const NETLIST_OBJECT* aLabel2 )
|
||||||
{
|
{
|
||||||
|
// Global labels have the highest prioriy.
|
||||||
|
// For local labels: names are prefixed by their sheetpath
|
||||||
|
// use name defined in the more top level hierarchical sheet
|
||||||
|
// (i.e. shorter timestamp path because paths are /<timestamp1>/<timestamp2>/...
|
||||||
|
// and timestamp = 8 letters.
|
||||||
|
// Note: the final net name uses human sheetpath name, not timestamp sheetpath name
|
||||||
|
// They are equivalent, but not for human readers.
|
||||||
|
if( ! aLabel1->IsLabelGlobal() && ! aLabel2->IsLabelGlobal() )
|
||||||
|
{
|
||||||
|
if( aLabel1->m_SheetPath.Path().Length() != aLabel2->m_SheetPath.Path().Length() )
|
||||||
|
return aLabel1->m_SheetPath.Path().Length() < aLabel2->m_SheetPath.Path().Length();
|
||||||
|
}
|
||||||
|
|
||||||
int priority1 = getPriority( aLabel1 );
|
int priority1 = getPriority( aLabel1 );
|
||||||
int priority2 = getPriority( aLabel2 );
|
int priority2 = getPriority( aLabel2 );
|
||||||
|
|
||||||
|
@ -429,29 +443,22 @@ static bool evalLabelsPriority( const NETLIST_OBJECT* aLabel1,
|
||||||
return priority1 > priority2;
|
return priority1 > priority2;
|
||||||
|
|
||||||
// Objects have here the same priority, therefore they have the same type.
|
// Objects have here the same priority, therefore they have the same type.
|
||||||
|
|
||||||
// for global labels, we select the best candidate by alphabetic order
|
// for global labels, we select the best candidate by alphabetic order
|
||||||
// because they have no sheetpath as prefix name
|
// because they have no sheetpath as prefix name
|
||||||
// for other labels, we select them before by sheet deep order
|
// for other labels, we select them before by sheet deep order
|
||||||
// because the actual name is /sheetpath/label
|
// because the actual name is /sheetpath/label
|
||||||
// and for a given path length, by alphabetic order
|
// and for a given path length, by alphabetic order
|
||||||
|
if( aLabel1->IsLabelGlobal() )
|
||||||
if( aLabel1->m_Type == NET_PINLABEL || aLabel1->m_Type == NET_GLOBLABEL )
|
|
||||||
return aLabel1->m_Label.Cmp( aLabel2->m_Label ) < 0;
|
return aLabel1->m_Label.Cmp( aLabel2->m_Label ) < 0;
|
||||||
|
|
||||||
// not global: names are prefixed by their sheetpath
|
// Sheet paths have here the same length: use alphabetic label name order
|
||||||
// use name defined in higher hierarchical sheet
|
|
||||||
// (i.e. shorter path because paths are /<timestamp1>/<timestamp2>/...
|
|
||||||
// and timestamp = 8 letters.
|
|
||||||
if( aLabel1->m_SheetPath.Path().Length() != aLabel2->m_SheetPath.Path().Length() )
|
|
||||||
return aLabel1->m_SheetPath.Path().Length() < aLabel2->m_SheetPath.Path().Length();
|
|
||||||
|
|
||||||
// Sheet paths have the same length: use alphabetic label name order
|
|
||||||
// For labels on sheets having an equivalent deep in hierarchy, use
|
// For labels on sheets having an equivalent deep in hierarchy, use
|
||||||
// alphabetic label name order:
|
// alphabetic label name order:
|
||||||
if( aLabel1->m_Label.Cmp( aLabel2->m_Label ) != 0 )
|
if( aLabel1->m_Label.Cmp( aLabel2->m_Label ) != 0 )
|
||||||
return aLabel1->m_Label.Cmp( aLabel2->m_Label ) < 0;
|
return aLabel1->m_Label.Cmp( aLabel2->m_Label ) < 0;
|
||||||
|
|
||||||
|
// For identical labels having the same priority: choose the
|
||||||
|
// alphabetic label full name order
|
||||||
return aLabel1->m_SheetPath.PathHumanReadable().Cmp(
|
return aLabel1->m_SheetPath.PathHumanReadable().Cmp(
|
||||||
aLabel2->m_SheetPath.PathHumanReadable() ) < 0;
|
aLabel2->m_SheetPath.PathHumanReadable() ) < 0;
|
||||||
}
|
}
|
||||||
|
@ -459,6 +466,12 @@ static bool evalLabelsPriority( const NETLIST_OBJECT* aLabel1,
|
||||||
|
|
||||||
void NETLIST_OBJECT_LIST::findBestNetNameForEachNet()
|
void NETLIST_OBJECT_LIST::findBestNetNameForEachNet()
|
||||||
{
|
{
|
||||||
|
// Important note: NET_SHEETLABEL items of sheet items should *NOT* be considered,
|
||||||
|
// because they live in a sheet but their names are actually used in the subsheet.
|
||||||
|
// Moreover, in the parent sheet, the name of NET_SHEETLABEL can be not unique,
|
||||||
|
// ( for instance when 2 different sheets share the same schematic in complex hierarchies
|
||||||
|
// and 2 identical NET_SHEETLABEL labels can be connected to 2 different nets
|
||||||
|
|
||||||
int netcode = 0; // current netcode for tested items
|
int netcode = 0; // current netcode for tested items
|
||||||
unsigned idxstart = 0; // index of the first item of this net
|
unsigned idxstart = 0; // index of the first item of this net
|
||||||
NETLIST_OBJECT* item;
|
NETLIST_OBJECT* item;
|
||||||
|
@ -481,9 +494,10 @@ void NETLIST_OBJECT_LIST::findBestNetNameForEachNet()
|
||||||
GetItem( jj )->SetNetNameCandidate( candidate );
|
GetItem( jj )->SetNetNameCandidate( candidate );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( item == NULL )
|
if( item == NULL ) // End of list
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Prepare next net analysis:
|
||||||
netcode = item->GetNet();
|
netcode = item->GetNet();
|
||||||
candidate = NULL;
|
candidate = NULL;
|
||||||
idxstart = ii;
|
idxstart = ii;
|
||||||
|
@ -495,6 +509,7 @@ void NETLIST_OBJECT_LIST::findBestNetNameForEachNet()
|
||||||
case NET_LABEL:
|
case NET_LABEL:
|
||||||
case NET_PINLABEL:
|
case NET_PINLABEL:
|
||||||
case NET_GLOBLABEL:
|
case NET_GLOBLABEL:
|
||||||
|
case NET_GLOBBUSLABELMEMBER:
|
||||||
// A candidate is found: select the better between the previous
|
// A candidate is found: select the better between the previous
|
||||||
// and this one
|
// and this one
|
||||||
if( candidate == NULL )
|
if( candidate == NULL )
|
||||||
|
@ -566,7 +581,7 @@ void NETLIST_OBJECT_LIST::findBestNetNameForEachNet()
|
||||||
|
|
||||||
// Examine all pins of the net to find the best candidate,
|
// Examine all pins of the net to find the best candidate,
|
||||||
// i.e. the first net name candidate, by alphabetic order
|
// i.e. the first net name candidate, by alphabetic order
|
||||||
// the net names are names bu_ilt by GetShortNetName
|
// the net names are built by GetShortNetName
|
||||||
// (Net-<{reference}-Pad{pad number}> like Net-<U3-Pad5>
|
// (Net-<{reference}-Pad{pad number}> like Net-<U3-Pad5>
|
||||||
// Not named nets do not have usually a lot of members.
|
// Not named nets do not have usually a lot of members.
|
||||||
// Many have only 2 members(a pad and a non connection symbol)
|
// Many have only 2 members(a pad and a non connection symbol)
|
||||||
|
@ -627,16 +642,18 @@ void NETLIST_OBJECT_LIST::sheetLabelConnect( NETLIST_OBJECT* SheetLabel )
|
||||||
|
|
||||||
void NETLIST_OBJECT_LIST::connectBusLabels()
|
void NETLIST_OBJECT_LIST::connectBusLabels()
|
||||||
{
|
{
|
||||||
|
// Propagate the net code between all bus label member objects connected by they name.
|
||||||
|
// If the net code is not yet existing, a new one is created
|
||||||
|
// Search is done in the entire list
|
||||||
for( unsigned ii = 0; ii < size(); ii++ )
|
for( unsigned ii = 0; ii < size(); ii++ )
|
||||||
{
|
{
|
||||||
NETLIST_OBJECT* Label = GetItem( ii );
|
NETLIST_OBJECT* Label = GetItem( ii );
|
||||||
|
|
||||||
if( (Label->m_Type == NET_SHEETBUSLABELMEMBER)
|
if( Label->IsLabelBusMemberType() )
|
||||||
|| (Label->m_Type == NET_BUSLABELMEMBER)
|
|
||||||
|| (Label->m_Type == NET_HIERBUSLABELMEMBER) )
|
|
||||||
{
|
{
|
||||||
if( Label->GetNet() == 0 )
|
if( Label->GetNet() == 0 )
|
||||||
{
|
{
|
||||||
|
// Not yet existiing net code: create a new one.
|
||||||
Label->SetNet( m_lastNetCode );
|
Label->SetNet( m_lastNetCode );
|
||||||
m_lastNetCode++;
|
m_lastNetCode++;
|
||||||
}
|
}
|
||||||
|
@ -644,9 +661,8 @@ void NETLIST_OBJECT_LIST::connectBusLabels()
|
||||||
for( unsigned jj = ii + 1; jj < size(); jj++ )
|
for( unsigned jj = ii + 1; jj < size(); jj++ )
|
||||||
{
|
{
|
||||||
NETLIST_OBJECT* LabelInTst = GetItem( jj );
|
NETLIST_OBJECT* LabelInTst = GetItem( jj );
|
||||||
if( (LabelInTst->m_Type == NET_SHEETBUSLABELMEMBER)
|
|
||||||
|| (LabelInTst->m_Type == NET_BUSLABELMEMBER)
|
if( LabelInTst->IsLabelBusMemberType() )
|
||||||
|| (LabelInTst->m_Type == NET_HIERBUSLABELMEMBER) )
|
|
||||||
{
|
{
|
||||||
if( LabelInTst->m_BusNetCode != Label->m_BusNetCode )
|
if( LabelInTst->m_BusNetCode != Label->m_BusNetCode )
|
||||||
continue;
|
continue;
|
||||||
|
@ -655,8 +671,10 @@ void NETLIST_OBJECT_LIST::connectBusLabels()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( LabelInTst->GetNet() == 0 )
|
if( LabelInTst->GetNet() == 0 )
|
||||||
|
// Append this object to the current net
|
||||||
LabelInTst->SetNet( Label->GetNet() );
|
LabelInTst->SetNet( Label->GetNet() );
|
||||||
else
|
else
|
||||||
|
// Merge the 2 net codes, they are connected.
|
||||||
propageNetCode( LabelInTst->GetNet(), Label->GetNet(), IS_WIRE );
|
propageNetCode( LabelInTst->GetNet(), Label->GetNet(), IS_WIRE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue