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.

425 lines
12 KiB

  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. /**
  26. * @file netlist_object.cpp
  27. * @brief Class NETLIST_OBJECT to handle 1 item connected (in netlist and erc calculations)
  28. */
  29. #include <fctsys.h>
  30. #include <macros.h>
  31. #include <sch_edit_frame.h>
  32. #include <sch_component.h>
  33. #include <netlist_object.h>
  34. #include <wx/regex.h>
  35. /**
  36. * The regular expression string for label bus notation. Valid bus labels are defined as
  37. * one or more non-whitespace characters from the beginning of the string followed by the
  38. * bus notation [nn...mm] with no characters after the closing bracket.
  39. */
  40. static wxRegEx busLabelRe( wxT( "^([^[:space:]]+)(\\[[\\d]+\\.+[\\d]+\\])$" ), wxRE_ADVANCED );
  41. bool IsBusLabel( const wxString& aLabel )
  42. {
  43. wxCHECK_MSG( busLabelRe.IsValid(), false,
  44. wxT( "Invalid regular expression in IsBusLabel()." ) );
  45. return busLabelRe.Matches( aLabel );
  46. }
  47. #if defined(DEBUG)
  48. #include <iostream>
  49. const char* ShowType( NETLIST_ITEM_T aType )
  50. {
  51. const char* ret;
  52. switch( aType )
  53. {
  54. case NET_SEGMENT:
  55. ret = "segment"; break;
  56. case NET_BUS:
  57. ret = "bus"; break;
  58. case NET_JUNCTION:
  59. ret = "junction"; break;
  60. case NET_LABEL:
  61. ret = "label"; break;
  62. case NET_HIERLABEL:
  63. ret = "hierlabel"; break;
  64. case NET_GLOBLABEL:
  65. ret = "glabel"; break;
  66. case NET_BUSLABELMEMBER:
  67. ret = "buslblmember"; break;
  68. case NET_HIERBUSLABELMEMBER:
  69. ret = "hierbuslblmember"; break;
  70. case NET_GLOBBUSLABELMEMBER:
  71. ret = "gbuslblmember"; break;
  72. case NET_SHEETBUSLABELMEMBER:
  73. ret = "sbuslblmember"; break;
  74. case NET_SHEETLABEL:
  75. ret = "sheetlabel"; break;
  76. case NET_PINLABEL:
  77. ret = "pinlabel"; break;
  78. case NET_PIN:
  79. ret = "pin"; break;
  80. case NET_NOCONNECT:
  81. ret = "noconnect"; break;
  82. default:
  83. ret = "??"; break;
  84. }
  85. return ret;
  86. }
  87. void NETLIST_OBJECT::Show( std::ostream& out, int ndx ) const
  88. {
  89. wxString path = m_SheetPath.PathHumanReadable();
  90. out << "<netItem ndx=\"" << ndx << '"' <<
  91. " type=\"" << ShowType( m_Type ) << '"' <<
  92. " netCode=\"" << GetNet() << '"' <<
  93. " sheet=\"" << TO_UTF8( path ) << '"' <<
  94. ">\n";
  95. out << " <start " << m_Start << "/> <end " << m_End << "/>\n";
  96. if( !m_Label.IsEmpty() )
  97. out << " <label>" << m_Label.mb_str() << "</label>\n";
  98. out << " <sheetpath>" << m_SheetPath.PathHumanReadable().mb_str() << "</sheetpath>\n";
  99. switch( m_Type )
  100. {
  101. case NET_PIN:
  102. /* GetRef() needs to be const
  103. out << " <refOfComp>" << GetComponentParent()->GetRef(&m_SheetPath).mb_str()
  104. << "</refOfComp>\n";
  105. */
  106. if( m_Comp )
  107. m_Comp->Show( 1, out );
  108. break;
  109. default:
  110. // not all the m_Comp classes have working Show functions.
  111. ;
  112. }
  113. /* was segfault-ing
  114. if( m_Comp )
  115. m_Comp->Show( 1, out ); // labels may not have good Show() funcs?
  116. else
  117. out << " m_Comp==NULL\n";
  118. */
  119. out << "</netItem>\n";
  120. }
  121. #endif
  122. NETLIST_OBJECT::NETLIST_OBJECT()
  123. {
  124. m_Type = NET_ITEM_UNSPECIFIED; /* Type of this item (see NETLIST_ITEM_T enum) */
  125. m_Comp = NULL; /* Pointer on the library item that created this net object
  126. * (the parent)*/
  127. m_Link = NULL; /* For SCH_SHEET_PIN:
  128. * Pointer to the hierarchy sheet that contains this
  129. * SCH_SHEET_PIN For Pins: pointer to the component that
  130. * contains this pin
  131. */
  132. m_Flag = 0; /* flag used in calculations */
  133. m_ElectricalPinType = PIN_INPUT; /* Has meaning only for Pins: electrical type of the pin
  134. * used to detect conflicts between pins in ERC
  135. */
  136. m_netCode = 0; /* net code for all items except BUS labels because a BUS
  137. * label has as many net codes as bus members
  138. */
  139. m_BusNetCode = 0; /* Used for BUS connections */
  140. m_Member = 0; /* for labels type NET_BUSLABELMEMBER ( bus member created
  141. * from the BUS label ) member number
  142. */
  143. m_ConnectionType = UNCONNECTED;
  144. m_netNameCandidate = NULL; /* a pointer to a NETLIST_OBJECT type label connected to this
  145. * object used to give a name to the net
  146. */
  147. }
  148. // Copy constructor
  149. NETLIST_OBJECT::NETLIST_OBJECT( NETLIST_OBJECT& aSource )
  150. {
  151. *this = aSource;
  152. }
  153. NETLIST_OBJECT::~NETLIST_OBJECT()
  154. {
  155. }
  156. // return true if the object is a label of any type
  157. bool NETLIST_OBJECT::IsLabelType() const
  158. {
  159. return m_Type == NET_LABEL
  160. || m_Type == NET_GLOBLABEL || m_Type == NET_HIERLABEL
  161. || m_Type == NET_BUSLABELMEMBER || m_Type == NET_GLOBBUSLABELMEMBER
  162. || m_Type == NET_HIERBUSLABELMEMBER
  163. || m_Type == NET_PINLABEL;
  164. }
  165. bool NETLIST_OBJECT::IsLabelConnected( NETLIST_OBJECT* aNetItem )
  166. {
  167. if( aNetItem == this ) // Don't compare the same net list object.
  168. return false;
  169. int at = m_Type;
  170. int bt = aNetItem->m_Type;
  171. if( ( at == NET_HIERLABEL || at == NET_HIERBUSLABELMEMBER )
  172. && ( bt == NET_SHEETLABEL || bt == NET_SHEETBUSLABELMEMBER ) )
  173. {
  174. if( m_SheetPath == aNetItem->m_SheetPathInclude )
  175. {
  176. return true; //connected!
  177. }
  178. }
  179. else if( ( at == NET_GLOBLABEL ) && ( bt == NET_GLOBLABEL ) )
  180. {
  181. if( m_Label == aNetItem->m_Label )
  182. return true; //connected!
  183. }
  184. return false; //these two are unconnected
  185. }
  186. void NETLIST_OBJECT::ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItems )
  187. {
  188. wxCHECK_RET( IsBusLabel( m_Label ),
  189. wxT( "<" ) + m_Label + wxT( "> is not a valid bus label." ) );
  190. if( m_Type == NET_HIERLABEL )
  191. m_Type = NET_HIERBUSLABELMEMBER;
  192. else if( m_Type == NET_GLOBLABEL )
  193. m_Type = NET_GLOBBUSLABELMEMBER;
  194. else if( m_Type == NET_SHEETLABEL )
  195. m_Type = NET_SHEETBUSLABELMEMBER;
  196. else if( m_Type == NET_LABEL )
  197. m_Type = NET_BUSLABELMEMBER;
  198. else
  199. wxCHECK_RET( false, wxT( "Net list object type is not valid." ) );
  200. unsigned i;
  201. wxString tmp, busName, busNumber;
  202. long begin, end, member;
  203. busName = busLabelRe.GetMatch( m_Label, 1 );
  204. busNumber = busLabelRe.GetMatch( m_Label, 2 );
  205. /* Search for '[' because a bus label is like "busname[nn..mm]" */
  206. i = busNumber.Find( '[' );
  207. i++;
  208. while( i < busNumber.Len() && busNumber[i] != '.' )
  209. {
  210. tmp.Append( busNumber[i] );
  211. i++;
  212. }
  213. tmp.ToLong( &begin );
  214. while( i < busNumber.Len() && busNumber[i] == '.' )
  215. i++;
  216. tmp.Empty();
  217. while( i < busNumber.Len() && busNumber[i] != ']' )
  218. {
  219. tmp.Append( busNumber[i] );
  220. i++;
  221. }
  222. tmp.ToLong( &end );
  223. if( begin < 0 )
  224. begin = 0;
  225. if( end < 0 )
  226. end = 0;
  227. if( begin > end )
  228. std::swap( begin, end );
  229. member = begin;
  230. tmp = busName;
  231. tmp << member;
  232. m_Label = tmp;
  233. m_Member = member;
  234. for( member++; member <= end; member++ )
  235. {
  236. NETLIST_OBJECT* item = new NETLIST_OBJECT( *this );
  237. // Conversion of bus label to the root name + the current member id.
  238. tmp = busName;
  239. tmp << member;
  240. item->m_Label = tmp;
  241. item->m_Member = member;
  242. aNetListItems.push_back( item );
  243. }
  244. }
  245. bool NETLIST_OBJECT::IsLabelGlobal() const
  246. {
  247. // return true if the object is a global label
  248. // * a actual global label
  249. // * a pin label coming from a invisible power pin
  250. return ( m_Type == NET_PINLABEL ) ||
  251. ( m_Type == NET_GLOBLABEL ) ||
  252. ( m_Type == NET_GLOBBUSLABELMEMBER );
  253. }
  254. bool NETLIST_OBJECT::IsLabelBusMemberType() const
  255. {
  256. // return true if the object is a bus label member build from a
  257. // schematic bus label (like label[xx..yy)
  258. // They are labels with very specific properties, especially for connection
  259. // between them: 2 bus label members can be connected only
  260. // if they have the same member value.
  261. return ( m_Type == NET_SHEETBUSLABELMEMBER ) ||
  262. ( m_Type == NET_BUSLABELMEMBER ) ||
  263. ( m_Type == NET_HIERBUSLABELMEMBER ) ||
  264. ( m_Type == NET_GLOBBUSLABELMEMBER );
  265. }
  266. /*
  267. * return the net name of the item
  268. */
  269. wxString NETLIST_OBJECT::GetNetName( bool adoptTimestamp ) const
  270. {
  271. if( m_netNameCandidate == NULL )
  272. return wxEmptyString;
  273. wxString netName;
  274. if( m_netNameCandidate->m_Type == NET_PIN )
  275. return GetShortNetName( adoptTimestamp );
  276. if( !m_netNameCandidate->IsLabelGlobal() )
  277. {
  278. // usual net name, prefix it by the sheet path
  279. netName = m_netNameCandidate->m_SheetPath.PathHumanReadable();
  280. }
  281. netName += m_netNameCandidate->m_Label;
  282. return netName;
  283. }
  284. /**
  285. * return the short net name of the item i.e. the net name
  286. * from the "best" label without any prefix.
  287. * 2 different nets can have the same short name
  288. */
  289. wxString NETLIST_OBJECT::GetShortNetName( bool adoptTimestamp ) const
  290. {
  291. if( m_netNameCandidate == NULL )
  292. return wxEmptyString;
  293. wxString netName;
  294. if( m_netNameCandidate->m_Type == NET_PIN )
  295. {
  296. SCH_COMPONENT* link = m_netNameCandidate->GetComponentParent();
  297. if( link ) // Should be always true
  298. {
  299. netName = wxT("Net-(");
  300. netName << link->GetRef( &m_netNameCandidate->m_SheetPath );
  301. if( adoptTimestamp && netName.Last() == '?' )
  302. netName << link->GetTimeStamp();
  303. netName << wxT("-Pad") << m_netNameCandidate->m_PinNum << wxT(")");
  304. }
  305. }
  306. else
  307. netName = m_netNameCandidate->m_Label;
  308. return netName;
  309. }
  310. /**
  311. * Set m_netNameCandidate to a connected item which will
  312. * be used to calcule the net name of the item
  313. * Obviously the candidate can be only a label
  314. * If there is no label on the net, a pad name will be
  315. * used to build a net name (something like Cmp<REF>_Pad<PAD_NAME>
  316. * @param aCandidate = the connected item candidate
  317. */
  318. void NETLIST_OBJECT::SetNetNameCandidate( NETLIST_OBJECT* aCandidate )
  319. {
  320. switch( aCandidate->m_Type )
  321. {
  322. case NET_HIERLABEL:
  323. case NET_LABEL:
  324. case NET_PINLABEL:
  325. case NET_GLOBLABEL:
  326. case NET_GLOBBUSLABELMEMBER:
  327. case NET_SHEETBUSLABELMEMBER:
  328. case NET_PIN:
  329. m_netNameCandidate = aCandidate;
  330. break;
  331. default:
  332. break;
  333. }
  334. }