KiCad PCB EDA Suite
netlist_object.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
31 #include <fctsys.h>
32 #include <macros.h>
33 #include <list>
34 
35 #include <sch_component.h>
36 #include <sch_connection.h>
37 #include <netlist_object.h>
38 #include <sch_edit_frame.h>
39 
40 #if defined(DEBUG)
41 
42 #include <iostream>
43 const char* ShowType( NETLIST_ITEM_T aType )
44 {
45  const char* ret;
46 
47  switch( aType )
48  {
49  case NET_SEGMENT:
50  ret = "segment"; break;
51 
52  case NET_BUS:
53  ret = "bus"; break;
54 
55  case NET_JUNCTION:
56  ret = "junction"; break;
57 
58  case NET_LABEL:
59  ret = "label"; break;
60 
61  case NET_HIERLABEL:
62  ret = "hierlabel"; break;
63 
64  case NET_GLOBLABEL:
65  ret = "glabel"; break;
66 
67  case NET_BUSLABELMEMBER:
68  ret = "buslblmember"; break;
69 
71  ret = "hierbuslblmember"; break;
72 
74  ret = "gbuslblmember"; break;
75 
77  ret = "sbuslblmember"; break;
78 
79  case NET_SHEETLABEL:
80  ret = "sheetlabel"; break;
81 
82  case NET_PINLABEL:
83  ret = "pinlabel"; break;
84 
85  case NET_PIN:
86  ret = "pin"; break;
87 
88  case NET_NOCONNECT:
89  ret = "noconnect"; break;
90 
91  default:
92  ret = "??"; break;
93  }
94 
95  return ret;
96 }
97 
98 
99 void NETLIST_OBJECT::Show( std::ostream& out, int ndx ) const
100 {
101  wxString path = m_SheetPath.PathHumanReadable();
102 
103  out << "<netItem ndx=\"" << ndx << '"' <<
104  " type=\"" << ShowType( m_Type ) << '"' <<
105  " netCode=\"" << GetNet() << '"' <<
106  " sheet=\"" << TO_UTF8( path ) << '"' <<
107  ">\n";
108 
109  out << " <start " << m_Start << "/> <end " << m_End << "/>\n";
110 
111  if( !m_Label.IsEmpty() )
112  out << " <label>" << m_Label.mb_str() << "</label>\n";
113 
114  out << " <sheetpath>" << m_SheetPath.PathHumanReadable().mb_str() << "</sheetpath>\n";
115 
116  switch( m_Type )
117  {
118  case NET_PIN:
119  /* GetRef() needs to be const
120  out << " <refOfComp>" << GetComponentParent()->GetRef(&m_SheetPath).mb_str()
121  << "</refOfComp>\n";
122  */
123 
124  if( m_Comp )
125  m_Comp->Show( 1, out );
126 
127  break;
128 
129  default:
130  // not all the m_Comp classes have working Show functions.
131  ;
132  }
133 
134 /* was segfault-ing
135  if( m_Comp )
136  m_Comp->Show( 1, out ); // labels may not have good Show() funcs?
137  else
138  out << " m_Comp==NULL\n";
139 */
140 
141  out << "</netItem>\n";
142 }
143 
144 #endif
145 
146 
148 {
149  m_Type = NET_ITEM_UNSPECIFIED; /* Type of this item (see NETLIST_ITEM_T enum) */
150  m_Comp = NULL; /* Pointer on the library item that created this net object
151  * (the parent)*/
152  m_Link = NULL; /* For SCH_SHEET_PIN:
153  * Pointer to the hierarchy sheet that contains this
154  * SCH_SHEET_PIN For Pins: pointer to the component that
155  * contains this pin
156  */
157  m_Flag = 0; /* flag used in calculations */
158  m_ElectricalPinType = PIN_INPUT; /* Has meaning only for Pins: electrical type of the pin
159  * used to detect conflicts between pins in ERC
160  */
161  m_netCode = 0; /* net code for all items except BUS labels because a BUS
162  * label has as many net codes as bus members
163  */
164  m_BusNetCode = 0; /* Used for BUS connections */
165  m_Member = 0; /* for labels type NET_BUSLABELMEMBER ( bus member created
166  * from the BUS label ) member number
167  */
169  m_netNameCandidate = NULL; /* a pointer to a NETLIST_OBJECT type label connected to this
170  * object used to give a name to the net
171  */
172 }
173 
174 
175 // Copy constructor
177 {
178  *this = aSource;
179 }
180 
181 
183 {
184 }
185 
186 
187 // return true if the object is a label of any type
189 {
190  return m_Type == NET_LABEL
194  || m_Type == NET_PINLABEL;
195 }
196 
198 {
199  if( aNetItem == this ) // Don't compare the same net list object.
200  return false;
201 
202  int at = m_Type;
203  int bt = aNetItem->m_Type;
204 
205  if( ( at == NET_HIERLABEL || at == NET_HIERBUSLABELMEMBER )
206  && ( bt == NET_SHEETLABEL || bt == NET_SHEETBUSLABELMEMBER ) )
207  {
208  if( m_SheetPath == aNetItem->m_SheetPathInclude )
209  {
210  return true; //connected!
211  }
212  }
213  else if( ( at == NET_GLOBLABEL ) && ( bt == NET_GLOBLABEL ) )
214  {
215  if( m_Label == aNetItem->m_Label )
216  return true; //connected!
217  }
218 
219  return false; //these two are unconnected
220 }
221 
222 
224 {
225  SCH_CONNECTION conn;
226  wxCHECK_RET( conn.IsBusLabel( m_Label ),
227  wxT( "<" ) + m_Label + wxT( "> is not a valid bus label." ) );
228 
229  if( m_Type == NET_HIERLABEL )
231  else if( m_Type == NET_GLOBLABEL )
233  else if( m_Type == NET_SHEETLABEL )
235  else if( m_Type == NET_LABEL )
237  else
238  wxCHECK_RET( false, wxT( "Net list object type is not valid." ) );
239 
240  // NOTE: all netlist objects generated from a single bus definition need to have different
241  // member codes set. For bus vectors, the member code matches the vector index, but for
242  // bus groups (including with nested vectors) the code is something arbitrary.
243  long member_offset = 0;
244 
245  auto alias = SCH_SCREEN::GetBusAlias( m_Label );
246  if( alias || conn.IsBusGroupLabel( m_Label ) )
247  {
248  wxString group_name;
249  bool self_set = false;
250  std::vector<wxString> bus_contents_vec;
251 
252  if( alias )
253  {
254  bus_contents_vec = alias->Members();
255  }
256  else
257  {
258  wxCHECK_RET( conn.ParseBusGroup( m_Label, &group_name, bus_contents_vec ),
259  wxString::Format( _( "Failed to parse bus group %s" ), m_Label ) );
260  }
261 
262  // For named bus groups, like "USB{DP DM}"
263  auto group_prefix = ( group_name != "" ) ? ( group_name + "." ) : "";
264 
265  std::list<wxString> bus_contents( bus_contents_vec.begin(),
266  bus_contents_vec.end() );
267 
268  for( auto bus_member : bus_contents )
269  {
270  // Nested bus vector inside a bus group
271  if( conn.IsBusVectorLabel( bus_member ) )
272  {
273  wxString prefix;
274  long begin, end;
275 
276  conn.ParseBusVector( bus_member, &prefix, &begin, &end );
277  prefix = group_prefix + prefix;
278 
279  if( !self_set )
280  {
281  m_Label = prefix;
282  m_Label << begin;
283  m_Member = ( begin++ ) + ( member_offset++ );
284 
285  self_set = true;
286  begin++;
287  }
288 
289  fillBusVector( aNetListItems, prefix, begin, end, member_offset );
290  member_offset += std::abs( end - begin );
291  }
292  else if( auto nested_alias = SCH_SCREEN::GetBusAlias( bus_member ) )
293  {
294  // Nested alias inside a group
295  for( auto alias_member : nested_alias->Members() )
296  {
297  bus_contents.push_back( alias_member );
298  }
299  }
300  else
301  {
302  if( !self_set )
303  {
304  m_Label = group_prefix + bus_member;
305  m_Member = member_offset++;
306  self_set = true;
307  }
308  else
309  {
310  auto item = new NETLIST_OBJECT( *this );
311  item->m_Label = group_prefix + bus_member;
312  item->m_Member = member_offset++;
313  aNetListItems.push_back( item );
314  }
315  }
316  }
317  }
318  else
319  {
320  // Plain bus vector
321  wxString prefix;
322  long begin, end;
323 
324  conn.ParseBusVector( m_Label, &prefix, &begin, &end );
325 
326  m_Label = prefix;
327  m_Label << begin;
328  m_Member = begin;
329 
330  fillBusVector( aNetListItems, prefix, begin + 1, end, 0 );
331  }
332 }
333 
335  wxString aName, long aBegin, long aEnd, long aOffset )
336 {
337  for( long member = aBegin; member <= aEnd; member++ )
338  {
339  auto item = new NETLIST_OBJECT( *this );
340 
341  item->m_Label = aName;
342  item->m_Label << member;
343  item->m_Member = member;
344 
345  aNetListItems.push_back( item );
346  }
347 }
348 
349 
351 {
352  // return true if the object is a global label
353  // * a actual global label
354  // * a pin label coming from a invisible power pin
355  return ( m_Type == NET_PINLABEL ) ||
356  ( m_Type == NET_GLOBLABEL ) ||
358 }
359 
360 
362 {
363  // return true if the object is a bus label member build from a
364  // schematic bus label (like label[xx..yy)
365  // They are labels with very specific properties, especially for connection
366  // between them: 2 bus label members can be connected only
367  // if they have the same member value.
368  return ( m_Type == NET_SHEETBUSLABELMEMBER ) ||
369  ( m_Type == NET_BUSLABELMEMBER ) ||
372 }
373 
374 
375 /*
376  * return the net name of the item
377  */
378 wxString NETLIST_OBJECT::GetNetName( bool adoptTimestamp ) const
379 {
380  if( m_netNameCandidate == NULL )
381  return wxEmptyString;
382 
383  wxString netName;
384 
386  return GetShortNetName( adoptTimestamp );
387 
389  {
390  // usual net name, prefix it by the sheet path
392  }
393 
394  netName += m_netNameCandidate->m_Label;
395 
396  return netName;
397 }
398 
404 wxString NETLIST_OBJECT::GetShortNetName( bool adoptTimestamp ) const
405 {
406  if( m_netNameCandidate == NULL )
407  return wxEmptyString;
408 
409  wxString netName;
410 
412  {
414  if( link ) // Should be always true
415  {
416  netName = wxT("Net-(");
417  netName << link->GetRef( &m_netNameCandidate->m_SheetPath );
418 
419  if( adoptTimestamp && netName.Last() == '?' )
420  netName << link->GetTimeStamp();
421 
422  netName << wxT("-Pad") << m_netNameCandidate->m_PinNum << wxT(")");
423  }
424  }
425  else
426  netName = m_netNameCandidate->m_Label;
427 
428  return netName;
429 }
430 
440 {
441  switch( aCandidate->m_Type )
442  {
443  case NET_HIERLABEL:
444  case NET_LABEL:
445  case NET_PINLABEL:
446  case NET_GLOBLABEL:
449  case NET_PIN:
450  m_netNameCandidate = aCandidate;
451  break;
452 
453  default:
454  break;
455  }
456 }
void fillBusVector(NETLIST_OBJECT_LIST &aNetListItems, wxString aName, long aBegin, long aEnd, long aOffset)
Given a bus vector, append the appropriate members into the list If given something like "DATA",...
SCH_COMPONENT * GetComponentParent() const
For Pins (NET_PINS):
SCH_SHEET_PATH m_SheetPathInclude
NETLIST_OBJECT * m_netNameCandidate
static bool IsBusLabel(const wxString &aLabel)
Test if aLabel has a bus notation.
int GetNet() const
static std::shared_ptr< BUS_ALIAS > GetBusAlias(const wxString &aLabel)
Returns a pointer to a bus alias object for the given label, or null if one doesn't exist.
Definition: sch_screen.cpp:932
NET_CONNECTION_T m_ConnectionType
SCH_SHEET_PATH m_SheetPath
ELECTRICAL_PINTYPE m_ElectricalPinType
bool IsLabelType() const
Function IsLabelType.
NETLIST_ITEM_T m_Type
EDA_ITEM * m_Comp
#define abs(a)
Definition: auxiliary.h:84
bool IsLabelBusMemberType() const
Function IsLabelBusMemberType.
This file contains miscellaneous commonly used macros and functions.
bool IsLabelGlobal() const
Function IsLabelGlobal.
Class NETLIST_OBJECT_LIST is a container holding and owning NETLIST_OBJECTs, which are connected item...
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:47
timestamp_t GetTimeStamp() const
Definition: base_struct.h:210
static bool IsBusVectorLabel(const wxString &aLabel)
Test if aLabel has a bus vector notation (simple bus, e.g.
bool ParseBusGroup(wxString aGroup, wxString *name, std::vector< wxString > &aMemberList) const
Parses a bus group label into the name and a list of components.
const wxString GetRef(const SCH_SHEET_PATH *aSheet)
Return the reference for the given sheet path.
NETLIST_ITEM_T
bool IsLabelConnected(NETLIST_OBJECT *aNetItem)
Function IsLabelConnected tests if the net list object is a hierarchical label or sheet label and is ...
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString GetNetName(bool adoptTimestamp=false) const
Function GetNetName.
void SetNetNameCandidate(NETLIST_OBJECT *aCandidate)
Set m_netNameCandidate to a connected item which will be used to calcule the net name of the item Obv...
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:73
wxString GetShortNetName(bool adoptTimestamp=false) const
Function GetShortNetName.
static bool IsBusGroupLabel(const wxString &aLabel)
Test if aLabel has a bus group notation.
wxString PathHumanReadable() const
Function PathHumanReadable returns the sheet path in a human readable form, i.e.
Definition of the NETLIST_OBJECT class.
SCH_ITEM * m_Link
void ParseBusVector(wxString vector, wxString *name, long *begin, long *end) const
Parses a bus vector (e.g.
void ConvertBusToNetListItems(NETLIST_OBJECT_LIST &aNetListItems)
Function ConvertBusToNetListItems breaks the text of a bus label type net list object into as many me...