/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2013 Wayne Stambaugh * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /** * @file class_netlist_object.cpp * @brief Class NETLIST_OBJECT to handle 1 item connected (in netlist and erc calculations) */ #include #include #include #include #include #include /** * The regular expression string for label bus notation. Valid bus labels are defined as * one or more non-whitespace characters from the beginning of the string followed by the * bus notation [nn...mm] with no characters after the closing bracket. */ static wxRegEx busLabelRe( wxT( "^([^[:space:]]+)(\\[[\\d]+\\.+[\\d]+\\])$" ), wxRE_ADVANCED ); bool IsBusLabel( const wxString& aLabel ) { wxCHECK_MSG( busLabelRe.IsValid(), false, wxT( "Invalid regular expression in IsBusLabel()." ) ); return busLabelRe.Matches( aLabel ); } #if defined(DEBUG) #include const char* ShowType( NETLIST_ITEM_T aType ) { const char* ret; switch( aType ) { case NET_SEGMENT: ret = "segment"; break; case NET_BUS: ret = "bus"; break; case NET_JUNCTION: ret = "junction"; break; case NET_LABEL: ret = "label"; break; case NET_HIERLABEL: ret = "hierlabel"; break; case NET_GLOBLABEL: ret = "glabel"; break; case NET_BUSLABELMEMBER: ret = "buslblmember"; break; case NET_HIERBUSLABELMEMBER: ret = "hierbuslblmember"; break; case NET_GLOBBUSLABELMEMBER: ret = "gbuslblmember"; break; case NET_SHEETBUSLABELMEMBER: ret = "sbuslblmember"; break; case NET_SHEETLABEL: ret = "sheetlabel"; break; case NET_PINLABEL: ret = "pinlabel"; break; case NET_PIN: ret = "pin"; break; case NET_NOCONNECT: ret = "noconnect"; break; default: ret = "??"; break; } return ret; } void NETLIST_OBJECT::Show( std::ostream& out, int ndx ) const { wxString path = m_SheetPath.PathHumanReadable(); out << "\n"; out << " \n"; if( !m_Label.IsEmpty() ) out << " \n"; out << " " << m_SheetPath.PathHumanReadable().mb_str() << "\n"; switch( m_Type ) { case NET_PIN: /* GetRef() needs to be const out << " " << GetComponentParent()->GetRef(&m_SheetPath).mb_str() << "\n"; */ if( m_Comp ) m_Comp->Show( 1, out ); break; default: // not all the m_Comp classes have working Show functions. ; } /* was segfault-ing if( m_Comp ) m_Comp->Show( 1, out ); // labels may not have good Show() funcs? else out << " m_Comp==NULL\n"; */ out << "\n"; } #endif NETLIST_OBJECT::NETLIST_OBJECT() { m_Type = NET_ITEM_UNSPECIFIED; /* Type of this item (see NETLIST_ITEM_T enum) */ m_Comp = NULL; /* Pointer on the library item that created this net object * (the parent)*/ m_Link = NULL; /* For SCH_SHEET_PIN: * Pointer to the hierarchy sheet that contains this * SCH_SHEET_PIN For Pins: pointer to the component that * contains this pin */ m_Flag = 0; /* flag used in calculations */ m_ElectricalType = 0; /* Has meaning only for Pins and hierarchical pins: electrical * type */ m_netCode = 0; /* net code for all items except BUS labels because a BUS * label has as many net codes as bus members */ m_BusNetCode = 0; /* Used for BUS connections */ m_Member = 0; /* for labels type NET_BUSLABELMEMBER ( bus member created * from the BUS label ) member number */ m_ConnectionType = UNCONNECTED; m_PinNum = 0; /* pin number ( 1 long = 4 bytes -> 4 ascii codes) */ m_netNameCandidate = NULL; /* a pointer to a NETLIST_OBJECT type label connected to this * object used to give a name to the net */ } // Copy constructor NETLIST_OBJECT::NETLIST_OBJECT( NETLIST_OBJECT& aSource ) { *this = aSource; } NETLIST_OBJECT::~NETLIST_OBJECT() { } // return true if the object is a label of any type bool NETLIST_OBJECT::IsLabelType() const { return m_Type == NET_LABEL || m_Type == NET_GLOBLABEL || m_Type == NET_HIERLABEL || m_Type == NET_BUSLABELMEMBER || m_Type == NET_GLOBBUSLABELMEMBER || m_Type == NET_HIERBUSLABELMEMBER || m_Type == NET_PINLABEL; } bool NETLIST_OBJECT::IsLabelConnected( NETLIST_OBJECT* aNetItem ) { if( aNetItem == this ) // Don't compare the same net list object. return false; int at = m_Type; int bt = aNetItem->m_Type; if( ( at == NET_HIERLABEL || at == NET_HIERBUSLABELMEMBER ) && ( bt == NET_SHEETLABEL || bt == NET_SHEETBUSLABELMEMBER ) ) { if( m_SheetPath == aNetItem->m_SheetPathInclude ) { return true; //connected! } } else if( ( at == NET_GLOBLABEL ) && ( bt == NET_GLOBLABEL ) ) { if( m_Label == aNetItem->m_Label ) return true; //connected! } return false; //these two are unconnected } void NETLIST_OBJECT::ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItems ) { wxCHECK_RET( IsBusLabel( m_Label ), wxT( "<" ) + m_Label + wxT( "> is not a valid bus label." ) ); if( m_Type == NET_HIERLABEL ) m_Type = NET_HIERBUSLABELMEMBER; else if( m_Type == NET_GLOBLABEL ) m_Type = NET_GLOBBUSLABELMEMBER; else if( m_Type == NET_SHEETLABEL ) m_Type = NET_SHEETBUSLABELMEMBER; else if( m_Type == NET_LABEL ) m_Type = NET_BUSLABELMEMBER; else wxCHECK_RET( false, wxT( "Net list object type is not valid." ) ); unsigned i; wxString tmp, busName, busNumber; long begin, end, member; busName = busLabelRe.GetMatch( m_Label, 1 ); busNumber = busLabelRe.GetMatch( m_Label, 2 ); /* Search for '[' because a bus label is like "busname[nn..mm]" */ i = busNumber.Find( '[' ); i++; while( i < busNumber.Len() && busNumber[i] != '.' ) { tmp.Append( busNumber[i] ); i++; } tmp.ToLong( &begin ); while( i < busNumber.Len() && busNumber[i] == '.' ) i++; tmp.Empty(); while( i < busNumber.Len() && busNumber[i] != ']' ) { tmp.Append( busNumber[i] ); i++; } tmp.ToLong( &end ); if( begin < 0 ) begin = 0; if( end < 0 ) end = 0; if( begin > end ) std::swap( begin, end ); member = begin; tmp = busName; tmp << member; m_Label = tmp; m_Member = member; for( member++; member <= end; member++ ) { NETLIST_OBJECT* item = new NETLIST_OBJECT( *this ); // Conversion of bus label to the root name + the current member id. tmp = busName; tmp << member; item->m_Label = tmp; item->m_Member = member; aNetListItems.push_back( item ); } } 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 */ wxString NETLIST_OBJECT::GetNetName() const { if( m_netNameCandidate == NULL ) return wxEmptyString; wxString netName; if( m_netNameCandidate->m_Type == NET_PIN ) return GetShortNetName(); if( !m_netNameCandidate->IsLabelGlobal() ) { // usual net name, prefix it by the sheet path netName = m_netNameCandidate->m_SheetPath.PathHumanReadable(); } netName += m_netNameCandidate->m_Label; return netName; } /** * return the short net name of the item i.e. the net name * from the "best" label without any prefix. * 2 different nets can have the same short name */ wxString NETLIST_OBJECT::GetShortNetName() const { if( m_netNameCandidate == NULL ) return wxEmptyString; wxString netName; if( m_netNameCandidate->m_Type == NET_PIN ) { SCH_COMPONENT* link = m_netNameCandidate->GetComponentParent(); if( link ) // Should be always true { netName = wxT("Net-("); netName << link->GetRef( &m_netNameCandidate->m_SheetPath ); netName << wxT("-Pad") << LIB_PIN::PinStringNum( m_netNameCandidate->m_PinNum ) << wxT(")"); } } else netName = m_netNameCandidate->m_Label; return netName; } /** * Set m_netNameCandidate to a connected item which will * be used to calcule the net name of the item * Obviously the candidate can be only a label * If there is no label on the net, a pad name will be * used to build a net name (something like Cmp_Pad * @param aCandidate = the connected item candidate */ void NETLIST_OBJECT::SetNetNameCandidate( NETLIST_OBJECT* aCandidate ) { switch( aCandidate->m_Type ) { case NET_HIERLABEL: case NET_LABEL: case NET_PINLABEL: case NET_GLOBLABEL: case NET_GLOBBUSLABELMEMBER: case NET_SHEETBUSLABELMEMBER: case NET_PIN: m_netNameCandidate = aCandidate; break; default: break; } }