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  for( const auto& member : alias->Members() )
255  bus_contents_vec.emplace_back( member );
256  }
257  else
258  {
259  wxCHECK_RET( conn.ParseBusGroup( m_Label, &group_name, bus_contents_vec ),
260  wxString::Format( _( "Failed to parse bus group %s" ), m_Label ) );
261  }
262 
263  // For named bus groups, like "USB{DP DM}"
264  auto group_prefix = ( group_name != "" ) ? ( group_name + "." ) : "";
265 
266  std::list<wxString> bus_contents( bus_contents_vec.begin(),
267  bus_contents_vec.end() );
268 
269  for( const auto& bus_member : bus_contents )
270  {
271  // Nested bus vector inside a bus group
272  if( conn.IsBusVectorLabel( bus_member ) )
273  {
274  wxString prefix;
275  std::vector<wxString> members;
276  long begin, end;
277 
278  conn.ParseBusVector( bus_member, &prefix, members );
279  prefix = group_prefix + prefix;
280  begin = conn.VectorStart();
281  end = conn.VectorEnd();
282 
283  if( !self_set )
284  {
285  m_Label = members[0];
286  m_Member = ( begin++ ) + ( member_offset++ );
287 
288  self_set = true;
289  begin++;
290  }
291 
292  fillBusVector( aNetListItems, prefix, begin, end, member_offset );
293  member_offset += std::abs( end - begin );
294  }
295  else if( auto nested_alias = SCH_SCREEN::GetBusAlias( bus_member ) )
296  {
297  // Nested alias inside a group
298  for( const auto& alias_member : nested_alias->Members() )
299  {
300  bus_contents.push_back( alias_member );
301  }
302  }
303  else
304  {
305  if( !self_set )
306  {
307  m_Label = group_prefix + bus_member;
308  m_Member = member_offset++;
309  self_set = true;
310  }
311  else
312  {
313  auto item = new NETLIST_OBJECT( *this );
314  item->m_Label = group_prefix + bus_member;
315  item->m_Member = member_offset++;
316  aNetListItems.push_back( item );
317  }
318  }
319  }
320  }
321  else
322  {
323  // Plain bus vector
324  wxString prefix;
325  std::vector<wxString> members;
326  long begin, end;
327 
328  conn.ParseBusVector( m_Label, &prefix, members );
329  begin = conn.VectorStart();
330  end = conn.VectorEnd();
331 
332  m_Label = members[0];
333  m_Member = begin;
334 
335  fillBusVector( aNetListItems, prefix, begin + 1, end, 0 );
336  }
337 }
338 
340  wxString aName, long aBegin, long aEnd, long aOffset )
341 {
342  for( long member = aBegin; member <= aEnd; member++ )
343  {
344  auto item = new NETLIST_OBJECT( *this );
345 
346  item->m_Label = aName;
347  item->m_Label << member;
348  item->m_Member = member;
349 
350  aNetListItems.push_back( item );
351  }
352 }
353 
354 
356 {
357  // return true if the object is a global label
358  // * a actual global label
359  // * a pin label coming from a invisible power pin
360  return ( m_Type == NET_PINLABEL ) ||
361  ( m_Type == NET_GLOBLABEL ) ||
363 }
364 
365 
367 {
368  // return true if the object is a bus label member build from a
369  // schematic bus label (like label[xx..yy)
370  // They are labels with very specific properties, especially for connection
371  // between them: 2 bus label members can be connected only
372  // if they have the same member value.
373  return ( m_Type == NET_SHEETBUSLABELMEMBER ) ||
374  ( m_Type == NET_BUSLABELMEMBER ) ||
377 }
378 
379 
380 /*
381  * return the net name of the item
382  */
383 wxString NETLIST_OBJECT::GetNetName( bool adoptTimestamp ) const
384 {
385  if( m_netNameCandidate == NULL )
386  return wxEmptyString;
387 
388  wxString netName;
389 
391  return GetShortNetName( adoptTimestamp );
392 
394  {
395  // usual net name, prefix it by the sheet path
397  }
398 
399  netName += m_netNameCandidate->m_Label;
400 
401  return netName;
402 }
403 
409 wxString NETLIST_OBJECT::GetShortNetName( bool adoptTimestamp ) const
410 {
411  if( m_netNameCandidate == NULL )
412  return wxEmptyString;
413 
414  wxString netName;
415 
417  {
419  if( link ) // Should be always true
420  {
421  netName = wxT("Net-(");
422  netName << link->GetRef( &m_netNameCandidate->m_SheetPath );
423 
424  if( adoptTimestamp && netName.Last() == '?' )
425  netName << link->GetTimeStamp();
426 
427  netName << wxT("-Pad") << m_netNameCandidate->m_PinNum << wxT(")");
428  }
429  }
430  else
431  netName = m_netNameCandidate->m_Label;
432 
433  return netName;
434 }
435 
445 {
446  switch( aCandidate->m_Type )
447  {
448  case NET_HIERLABEL:
449  case NET_LABEL:
450  case NET_PINLABEL:
451  case NET_GLOBLABEL:
454  case NET_PIN:
455  m_netNameCandidate = aCandidate;
456  break;
457 
458  default:
459  break;
460  }
461 }
462 
463 
464 const wxString NETLIST_OBJECT::GetPinNameText() const
465 {
466  wxString name;
467  // returns the pin name, for NET_PIN (usual pin) item.
468  if( m_Type == NET_PIN )
469  {
470  name = static_cast<LIB_PIN*>( m_Comp )->GetName();
471 
472  if( name == "~" ) //empty name
473  name = wxEmptyString;
474  }
475 
476  return name;
477 }
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:937
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:48
const wxString GetPinNameText() const
returns the pin name, for NET_PIN (usual pin) item.
long VectorEnd() const
timestamp_t GetTimeStamp() const
Definition: base_struct.h:216
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.
#define _(s)
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 ...
const char * name
Definition: DXF_plotter.cpp:61
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).
bool ParseBusVector(wxString aBus, wxString *aName, std::vector< wxString > &aMemberList) const
Parses a bus vector (e.g.
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
long VectorStart() const
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 ConvertBusToNetListItems(NETLIST_OBJECT_LIST &aNetListItems)
Function ConvertBusToNetListItems breaks the text of a bus label type net list object into as many me...