Changed the way of looking up NETINFO_ITEM using net names (using boost::unordered_map). Added a hash function (wxString) for that. Introduced NETINFO_ITEM::GetNetItem( wxString ). BOARD::FindNet() uses the map.

Net codes are updated upon net list update. (BOARD::ReplaceNetlist())
Added in some places (mostly class_board.cpp) pad->SetNet() calls to synchronize net codes.
On creation of NETINFO_LIST, the first NETINFO_ITEM is added (the unconnected items net).
Removed COMPONENT_NET::m_netNumber, as it was not used anywhere.
Added an assert to D_PAD::GetNetname(), checking if net code and net name is consistent for unconnected pads. Added an assert for NETINFO_LIST::AppendNet() to assure that appended nets are unique.

It seems that at this point:
- Updating net lists works fine. The only difference between the file ouput is that after changes it contains empty nets as well.
- Nets are not saved in the lexical order. Still, net names and net codes are properly assigned to all items in the .kicad_pcb file. It is going to be addressed in the next commit. I believe it should not create any problems, as pads are sorted by their net names anyway (NETINFO_LIST::buildPadsFullList())

Performed tests:
- Created a blank PCB, saved as pic_programmer.kicad_pcb (from demos folder). Updated net lists. .kicad_pcb file (comparing to the results from master branch) differ with net order (as mentioned before), net codes and timestamps.
- Removed some of components from the above .kicad_pcb file and updated net lists. Modules reappeared. .kicad_pcb file differs in the same way as described above.
- Trying to change a pad net name (via properties dialog) results in assert being fired. It is done on purpose (as there is a call to GetNetname() and net name and net code do not match). This will not happen after the next commit.
- Prepared a simple project (starting with schematics). Imported net list, changed schematic, reimported net list - changes are applied.
- Eagle & KiCad legacy boards seem to load without any problem.
This commit is contained in:
Maciej Suminski 2014-01-10 18:04:07 +01:00
parent 386d1fc257
commit bf80cc770e
8 changed files with 84 additions and 93 deletions

View File

@ -98,6 +98,24 @@ struct fnv_1a
};
/// Hash function for wxString, counterpart of std::string hash
struct WXSTRING_HASH : std::unary_function<wxString, std::size_t>
{
std::size_t operator()( const wxString& aString ) const
{
std::size_t hash = 2166136261u;
for( wxString::const_iterator it = aString.begin(); it != aString.end(); ++it )
{
hash ^= (unsigned char) *it;
hash *= 16777619;
}
return hash;
}
};
/**
* Type KEYWORD_MAP
* is a hashtable made of a const char* and an int. Note that use of this

View File

@ -1355,79 +1355,7 @@ NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
{
// the first valid netcode is 1.
// zero is reserved for "no connection" and is not used.
if( aNetname.IsEmpty() )
return NULL;
int ncount = m_NetInfo.GetNetCount();
// Search for a netname = aNetname
#if 0
// Use a sequential search: easy to understand, but slow
for( int ii = 1; ii < ncount; ii++ )
{
NETINFO_ITEM* item = m_NetInfo.GetNetItem( ii );
if( item && item->GetNetname() == aNetname )
{
return item;
}
}
#else
// Use a fast binary search,
// this is possible because Nets are alphabetically ordered in list
// see NETINFO_LIST::BuildListOfNets() and
// NETINFO_LIST::Build_Pads_Full_List()
int imax = ncount - 1;
int index = imax;
while( ncount > 0 )
{
int ii = ncount;
ncount >>= 1;
if( (ii & 1) && ( ii > 1 ) )
ncount++;
NETINFO_ITEM* item = m_NetInfo.GetNetItem( index );
if( item == NULL )
return NULL;
int icmp = item->GetNetname().Cmp( aNetname );
if( icmp == 0 ) // found !
{
return item;
}
if( icmp < 0 ) // must search after item
{
index += ncount;
if( index > imax )
index = imax;
continue;
}
if( icmp > 0 ) // must search before item
{
index -= ncount;
if( index < 1 )
index = 1;
continue;
}
}
#endif
return NULL;
return m_NetInfo.GetNetItem( aNetname );
}
@ -2618,7 +2546,10 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
}
if( !aNetlist.IsDryRun() )
{
pad->SetNetname( wxEmptyString );
pad->SetNet( 0 );
}
}
}
else // Footprint pad has a net.
@ -2638,7 +2569,19 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
}
if( !aNetlist.IsDryRun() )
{
pad->SetNetname( net.GetNetName() );
NETINFO_ITEM* netinfo = FindNet( net.GetNetName() );
if( netinfo == NULL )
{
// It is a new net, we have to add it
netinfo = new NETINFO_ITEM( this, net.GetNetName(), m_NetInfo.GetNetCount() );
m_NetInfo.AppendNet( netinfo );
}
pad->SetNet( netinfo->GetNet() );
}
}
}
}
@ -2711,6 +2654,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
aReporter->Report( msg );
}
previouspad->SetNetname( wxEmptyString );
previouspad->SetNet( 0 );
}
netname = pad->GetNetname();
count = 1;
@ -2723,7 +2667,10 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
// Examine last pad
if( pad && count == 1 )
{
pad->SetNetname( wxEmptyString );
pad->SetNet( 0 );
}
}
// Last step: Some tests:

View File

@ -37,6 +37,8 @@
#include <vector>
#include <gr_basic.h>
#include <class_netclass.h>
#include <boost/unordered_map.hpp>
#include <hashtables.h>
class wxDC;
@ -115,7 +117,6 @@ public:
};
/**
* Class NETINFO
* is a container class for NETINFO_ITEM elements, which are the nets. That makes
@ -141,6 +142,20 @@ public:
return m_NetBuffer[aNetcode];
}
/**
* Function GetItem
* @param aNetName = net name to identify a given NETINFO_ITEM
* @return NETINFO_ITEM* - by \a aNetName, or NULL if not found
*/
NETINFO_ITEM* GetNetItem( const wxString& aNetName ) const
{
NETNAMES_MAP::const_iterator result = m_netNames.find( aNetName );
if( result != m_netNames.end() )
return (*result).second;
return NULL;
}
/**
* Function GetNetCount
* @return the number of nets ( always >= 1 )
@ -188,6 +203,8 @@ public:
void Show() const;
#endif
typedef boost::unordered_map<const wxString, NETINFO_ITEM*, WXSTRING_HASH> NETNAMES_MAP;
private:
/**
@ -214,6 +231,7 @@ private:
void buildPadsFullList();
BOARD* m_Parent;
NETNAMES_MAP m_netNames; ///< map for a fast look up by net names
std::vector<NETINFO_ITEM*> m_NetBuffer; ///< net list (name, design constraints ..)
std::vector<D_PAD*> m_PadsFullList; ///< contains all pads, sorted by pad's netname.
@ -394,15 +412,15 @@ public:
/**
* Function GetNetname
* @return const wxString * , a pointer to the full netname
* @return const wxString&, a reference to the full netname
*/
wxString GetNetname() const { return m_Netname; }
const wxString& GetNetname() const { return m_Netname; }
/**
* Function GetShortNetname
* @return const wxString * , a pointer to the short netname
* @return const wxString &, a reference to the short netname
*/
wxString GetShortNetname() const { return m_ShortNetname; }
const wxString& GetShortNetname() const { return m_ShortNetname; }
/**
* Function GetMsgPanelInfo

View File

@ -15,9 +15,10 @@
// Constructor and destructor
NETINFO_LIST::NETINFO_LIST( BOARD* aParent )
NETINFO_LIST::NETINFO_LIST( BOARD* aParent ) : m_Parent( aParent )
{
m_Parent = aParent;
// Make sure that the unconnected net has number 0
AppendNet( new NETINFO_ITEM( aParent, wxEmptyString, 0 ) );
}
@ -34,14 +35,20 @@ void NETINFO_LIST::clear()
m_NetBuffer.clear();
m_PadsFullList.clear();
m_netNames.clear();
}
void NETINFO_LIST::AppendNet( NETINFO_ITEM* aNewElement )
{
// net names & codes are supposed to be unique
assert( GetNetItem( aNewElement->GetNetname() ) == NULL );
assert( GetNetItem( aNewElement->GetNet() ) == NULL );
m_NetBuffer.push_back( aNewElement );
// D(Show();)
// add an entry for fast look up by a net name using a map
m_netNames.insert( std::make_pair( aNewElement->GetNetname(), aNewElement ) );
}
@ -74,18 +81,13 @@ void NETINFO_LIST::buildListOfNets()
{
D_PAD* pad;
int nodes_count = 0;
NETINFO_ITEM* net_item;
// Build the PAD list, sorted by net
buildPadsFullList();
// Restore the initial state of NETINFO_ITEMs
for( unsigned i = 0; i < GetNetCount(); ++i )
{
GetNetItem( i )->Clear();
}
std::cout << m_PadsFullList.size() << std::endl;
// Assign pads to appropriate NETINFO_ITEMs
for( unsigned ii = 0; ii < m_PadsFullList.size(); ii++ )
@ -95,8 +97,8 @@ void NETINFO_LIST::buildListOfNets()
if( pad->GetNet() == 0 ) // pad not connected
continue;
net_item = GetNetItem( pad->GetNet() );
net_item->m_PadInNetList.push_back( pad );
// Add pad to the appropriate list of pads
GetNetItem( pad->GetNet() )->m_PadInNetList.push_back( pad );
++nodes_count;
}

View File

@ -413,6 +413,7 @@ void D_PAD::CopyNetlistSettings( D_PAD* aPad )
wxCHECK_RET( aPad != NULL && aPad != this, wxT( "Cannot copy to NULL or yourself." ) );
aPad->SetNetname( GetNetname() );
aPad->SetNet( GetNet() );
aPad->SetLocalClearance( m_LocalClearance );
aPad->SetLocalSolderMaskMargin( m_LocalSolderMaskMargin );

View File

@ -128,7 +128,13 @@ public:
* Function GetNetname
* @return const wxString& - the full netname
*/
const wxString& GetNetname() const { return m_Netname; }
const wxString& GetNetname() const
{
assert( ( GetNet() == 0 ) == m_Netname.IsEmpty() );
// assert( GetBoard()->FindNet( GetNet() ) == GetBoard()->FindNet( m_Netname ) );
return m_Netname;
}
/**
* Function GetShortNetname

View File

@ -142,6 +142,7 @@ void PCB_BASE_FRAME::AddPad( MODULE* aModule, bool draw )
// Update the pad properties.
Import_Pad_Settings( pad, false );
pad->SetNetname( wxEmptyString );
pad->SetNet( 0 );
pad->SetPosition( GetCrossHairPosition() );

View File

@ -47,16 +47,14 @@ class REPORTER;
class COMPONENT_NET
{
wxString m_pinName;
wxString m_netNumber;
wxString m_netName;
public:
COMPONENT_NET() {}
COMPONENT_NET( const wxString& aPinName, const wxString& aNetName )
COMPONENT_NET( const wxString& aPinName, const wxString& aNetName ) :
m_pinName( aPinName ), m_netName( aNetName )
{
m_pinName = aPinName;
m_netName = aNetName;
}
const wxString& GetPinName() const { return m_pinName; }