You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							428 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							428 lines
						
					
					
						
							12 KiB
						
					
					
				| /* | |
|  * 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 <stambaughw@verizon.net> | |
|  * 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 <fctsys.h> | |
| #include <macros.h> | |
| #include <schframe.h> | |
|  | |
| #include <sch_component.h> | |
| #include <class_netlist_object.h> | |
|  | |
| #include <wx/regex.h> | |
|  | |
| 
 | |
| /** | |
|  * 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 <iostream> | |
| 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 << "<netItem ndx=\"" << ndx << '"' << | |
|     " type=\"" << ShowType( m_Type ) << '"' << | |
|     " netCode=\"" << GetNet() << '"' << | |
|     " sheet=\"" << TO_UTF8( path ) << '"' << | |
|     ">\n"; | |
| 
 | |
|     out << " <start " << m_Start << "/> <end " << m_End << "/>\n"; | |
| 
 | |
|     if( !m_Label.IsEmpty() ) | |
|         out << " <label>" << m_Label.mb_str() << "</label>\n"; | |
| 
 | |
|     out << " <sheetpath>" << m_SheetPath.PathHumanReadable().mb_str() << "</sheetpath>\n"; | |
| 
 | |
|     switch( m_Type ) | |
|     { | |
|     case NET_PIN: | |
|         /* GetRef() needs to be const | |
|         out << " <refOfComp>" << GetComponentParent()->GetRef(&m_SheetPath).mb_str() | |
|             << "</refOfComp>\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 << "</netItem>\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_ElectricalPinType = PIN_INPUT;   /* Has meaning only for Pins: electrical type of the pin | |
|                                      * used to detect conflicts between pins in ERC | |
|                                      */ | |
|     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( bool adoptTimestamp ) const | |
| { | |
|     if( m_netNameCandidate == NULL ) | |
|         return wxEmptyString; | |
| 
 | |
|     wxString netName; | |
| 
 | |
|     if( m_netNameCandidate->m_Type == NET_PIN ) | |
|         return GetShortNetName( adoptTimestamp ); | |
| 
 | |
|     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( bool adoptTimestamp ) 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 ); | |
| 
 | |
|             if( adoptTimestamp && netName.Last() == '?' ) | |
|                 netName << link->GetTimeStamp(); | |
| 
 | |
|             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<REF>_Pad<PAD_NAME> | |
|  * @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; | |
|     } | |
| }
 |