Commit bf80cc77 authored by Maciej Suminski's avatar Maciej Suminski
Browse files

Changed the way of looking up NETINFO_ITEM using net names (using...

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.
parent 386d1fc2
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -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
+20 −73
Original line number Diff line number Diff line
@@ -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:
+23 −5
Original line number Diff line number Diff line
@@ -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
+12 −10
Original line number Diff line number Diff line
@@ -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;
    }
+1 −0
Original line number Diff line number Diff line
@@ -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 );
Loading