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.

554 lines
19 KiB

7 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018 CERN
  5. * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
  6. * @author Jon Evans <jon@craftyjon.com>
  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 along
  19. * with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #ifndef _CONNECTION_GRAPH_H
  22. #define _CONNECTION_GRAPH_H
  23. #include <mutex>
  24. #include <vector>
  25. #include <erc_settings.h>
  26. #include <sch_connection.h>
  27. #include <sch_item.h>
  28. #ifdef DEBUG
  29. // Uncomment this line to enable connectivity debugging features
  30. // #define CONNECTIVITY_DEBUG
  31. #endif
  32. class CONNECTION_GRAPH;
  33. class SCHEMATIC;
  34. class SCH_EDIT_FRAME;
  35. class SCH_HIERLABEL;
  36. class SCH_PIN;
  37. class SCH_SHEET_PIN;
  38. /**
  39. * A subgraph is a set of items that are electrically connected on a single sheet.
  40. *
  41. * For example, a label connected to a wire and so on.
  42. * A net is composed of one or more subgraphs.
  43. *
  44. * A set of items that appears to be physically connected may actually be more
  45. * than one subgraph, because some items don't connect electrically.
  46. *
  47. * For example, multiple bus wires can come together at a junction but have
  48. * different labels on each branch. Each label+wire branch is its own subgraph.
  49. *
  50. */
  51. class CONNECTION_SUBGRAPH
  52. {
  53. public:
  54. enum class PRIORITY
  55. {
  56. INVALID = -1,
  57. NONE = 0,
  58. PIN,
  59. SHEET_PIN,
  60. HIER_LABEL,
  61. LOCAL_LABEL,
  62. POWER_PIN,
  63. GLOBAL
  64. };
  65. explicit CONNECTION_SUBGRAPH( CONNECTION_GRAPH* aGraph ) :
  66. m_graph( aGraph ),
  67. m_dirty( false ),
  68. m_absorbed( false ),
  69. m_absorbed_by( nullptr ),
  70. m_code( -1 ),
  71. m_multiple_drivers( false ),
  72. m_strong_driver( false ),
  73. m_local_driver( false ),
  74. m_no_connect( nullptr ),
  75. m_bus_entry( nullptr ),
  76. m_driver( nullptr ),
  77. m_driver_connection( nullptr ),
  78. m_hier_parent( nullptr ),
  79. m_first_driver( nullptr ),
  80. m_second_driver( nullptr )
  81. {}
  82. ~CONNECTION_SUBGRAPH() = default;
  83. /**
  84. * Determines which potential driver should drive the subgraph.
  85. *
  86. * If multiple possible drivers exist, picks one according to the priority.
  87. * If multiple "winners" exist, returns false and sets m_driver to nullptr.
  88. *
  89. * @param aCheckMultipleDrivers controls whether the second driver should be captured for ERC
  90. * @return true if m_driver was set, or false if a conflict occurred
  91. */
  92. bool ResolveDrivers( bool aCheckMultipleDrivers = false );
  93. /**
  94. * Returns the fully-qualified net name for this subgraph (if one exists)
  95. */
  96. wxString GetNetName() const;
  97. /// Returns all the bus labels attached to this subgraph (if any)
  98. std::vector<SCH_ITEM*> GetBusLabels() const;
  99. /// Returns the candidate net name for a driver
  100. const wxString& GetNameForDriver( SCH_ITEM* aItem );
  101. const wxString GetNameForDriver( SCH_ITEM* aItem ) const;
  102. /// Combines another subgraph on the same sheet into this one.
  103. void Absorb( CONNECTION_SUBGRAPH* aOther );
  104. /// Adds a new item to the subgraph
  105. void AddItem( SCH_ITEM* aItem );
  106. /// Updates all items to match the driver connection
  107. void UpdateItemConnections();
  108. /**
  109. * Return the priority (higher is more important) of a candidate driver
  110. *
  111. * 0: Invalid driver
  112. * 1: Symbol pin
  113. * 2: Hierarchical sheet pin
  114. * 3: Hierarchical label
  115. * 4: Local label
  116. * 5: Power pin
  117. * 6: Global label
  118. *
  119. * @param aDriver is the item to inspect
  120. * @return a PRIORITY
  121. */
  122. static PRIORITY GetDriverPriority( SCH_ITEM* aDriver );
  123. PRIORITY GetDriverPriority()
  124. {
  125. if( m_driver )
  126. return GetDriverPriority( m_driver );
  127. else
  128. return PRIORITY::NONE;
  129. }
  130. private:
  131. wxString driverName( SCH_ITEM* aItem ) const;
  132. public:
  133. CONNECTION_GRAPH* m_graph;
  134. bool m_dirty;
  135. /// True if this subgraph has been absorbed into another. No pointers here are safe if so!
  136. bool m_absorbed;
  137. /// If this subgraph is absorbed, points to the absorbing (and valid) subgraph
  138. CONNECTION_SUBGRAPH* m_absorbed_by;
  139. long m_code;
  140. /**
  141. * True if this subgraph contains more than one driver that should be
  142. * shorted together in the netlist. For example, two labels or
  143. * two power ports.
  144. */
  145. bool m_multiple_drivers;
  146. /// True if the driver is "strong": a label or power object
  147. bool m_strong_driver;
  148. /// True if the driver is a local (i.e. non-global) type
  149. bool m_local_driver;
  150. /// No-connect item in graph, if any
  151. SCH_ITEM* m_no_connect;
  152. /// Bus entry in graph, if any
  153. SCH_ITEM* m_bus_entry;
  154. std::vector<SCH_ITEM*> m_items;
  155. std::vector<SCH_ITEM*> m_drivers;
  156. SCH_ITEM* m_driver;
  157. SCH_SHEET_PATH m_sheet;
  158. /// Cache for driver connection
  159. SCH_CONNECTION* m_driver_connection;
  160. /**
  161. * If a subgraph is a bus, this map contains links between the bus members and any
  162. * local sheet neighbors with the same connection name.
  163. *
  164. * For example, if this subgraph is a bus D[7..0], and on the same sheet there is
  165. * a net with label D7, this map will contain an entry for the D7 bus member, and
  166. * the vector will contain a pointer to the D7 net subgraph.
  167. */
  168. std::unordered_map< std::shared_ptr<SCH_CONNECTION>,
  169. std::unordered_set<CONNECTION_SUBGRAPH*> > m_bus_neighbors;
  170. /**
  171. * If this is a net, this vector contains links to any same-sheet buses that contain it.
  172. * The string key is the name of the connection that forms the link (which isn't necessarily
  173. * the same as the name of the connection driving this subgraph)
  174. */
  175. std::unordered_map< std::shared_ptr<SCH_CONNECTION>,
  176. std::unordered_set<CONNECTION_SUBGRAPH*> > m_bus_parents;
  177. // Cache for lookup of any hierarchical (sheet) pins on this subgraph (for referring down)
  178. std::vector<SCH_SHEET_PIN*> m_hier_pins;
  179. // Cache for lookup of any hierarchical ports on this subgraph (for referring up)
  180. std::vector<SCH_HIERLABEL*> m_hier_ports;
  181. // If not null, this indicates the subgraph on a higher level sheet that is linked to this one
  182. CONNECTION_SUBGRAPH* m_hier_parent;
  183. /// A cache of escaped netnames from schematic items
  184. std::unordered_map<SCH_ITEM*, wxString> m_driver_name_cache;
  185. /**
  186. * Stores the primary driver for the multiple drivers ERC check. This is the chosen driver
  187. * before subgraphs are absorbed (so m_driver may be different)
  188. */
  189. SCH_ITEM* m_first_driver;
  190. /// Used for multiple drivers ERC message; stores the second possible driver (or nullptr)
  191. SCH_ITEM* m_second_driver;
  192. };
  193. /// Associates a net code with the final name of a net
  194. typedef std::pair<wxString, int> NET_NAME_CODE;
  195. /// Associates a NET_CODE_NAME with all the subgraphs in that net
  196. typedef std::map<NET_NAME_CODE, std::vector<CONNECTION_SUBGRAPH*>> NET_MAP;
  197. /**
  198. * Calculates the connectivity of a schematic and generates netlists
  199. */
  200. class CONNECTION_GRAPH
  201. {
  202. public:
  203. CONNECTION_GRAPH( SCHEMATIC* aSchematic = nullptr ) :
  204. m_last_net_code( 1 ),
  205. m_last_bus_code( 1 ),
  206. m_last_subgraph_code( 1 ),
  207. m_schematic( aSchematic )
  208. {}
  209. ~CONNECTION_GRAPH()
  210. {
  211. Reset();
  212. }
  213. void Reset();
  214. void SetSchematic( SCHEMATIC* aSchematic )
  215. {
  216. m_schematic = aSchematic;
  217. }
  218. /**
  219. * Updates the connection graph for the given list of sheets.
  220. *
  221. * @param aSheetList is the list of possibly modified sheets
  222. * @param aUnconditional is true if an unconditional full recalculation should be done
  223. * @param aChangedItemHandler an optional handler to receive any changed items
  224. */
  225. void Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnconditional = false,
  226. std::function<void( SCH_ITEM* )>* aChangedItemHandler = nullptr );
  227. /**
  228. * Returns a bus alias pointer for the given name if it exists (from cache)
  229. *
  230. * CONNECTION_GRAPH caches these, they are owned by the SCH_SCREEN that
  231. * the alias was defined on. The cache is only used to update the graph.
  232. */
  233. std::shared_ptr<BUS_ALIAS> GetBusAlias( const wxString& aName );
  234. /**
  235. * Determines which subgraphs have more than one conflicting bus label.
  236. *
  237. * @see DIALOG_MIGRATE_BUSES
  238. * @return a list of subgraphs that need migration
  239. */
  240. std::vector<const CONNECTION_SUBGRAPH*> GetBusesNeedingMigration();
  241. /**
  242. * Runs electrical rule checks on the connectivity graph.
  243. *
  244. * Precondition: graph is up-to-date
  245. *
  246. * @return the number of errors found
  247. */
  248. int RunERC();
  249. const NET_MAP& GetNetMap() const { return m_net_code_to_subgraphs_map; }
  250. /**
  251. * Returns the subgraph for a given net name on a given sheet
  252. * @param aNetName is the local net name to look for
  253. * @param aPath is a sheet path to look on
  254. * @return the subgraph matching the query, or nullptr if none is found
  255. */
  256. CONNECTION_SUBGRAPH* FindSubgraphByName( const wxString& aNetName,
  257. const SCH_SHEET_PATH& aPath );
  258. /**
  259. * Retrieves a subgraph for the given net name, if one exists.
  260. * Searches every sheet
  261. * @param aNetName is the full net name to search for
  262. * @return the subgraph matching the query, or nullptr if none is found
  263. */
  264. CONNECTION_SUBGRAPH* FindFirstSubgraphByName( const wxString& aNetName );
  265. CONNECTION_SUBGRAPH* GetSubgraphForItem( SCH_ITEM* aItem );
  266. private:
  267. /**
  268. * Updates the graphical connectivity between items (i.e. where they touch)
  269. * The items passed in must be on the same sheet.
  270. *
  271. * In the first phase, all items in aItemList have their connections
  272. * initialized for the given sheet (since they may have connections on more
  273. * than one sheet, and each needs to be calculated individually). The
  274. * graphical connection points for the item are added to a map that stores
  275. * (x, y) -> [list of items].
  276. *
  277. * Any item that is stored in the list of items that have a connection point
  278. * at a given (x, y) location will eventually be electrically connected.
  279. * This means that we can't store SCH_SYMBOLs in this map -- we must store
  280. * a structure that links a specific pin on a symbol back to that symbol: a
  281. * SCH_PIN_CONNECTION. This wrapper class is a convenience for linking a pin
  282. * and symbol to a specific (x, y) point.
  283. *
  284. * In the second phase, we iterate over each value in the map, which is a
  285. * vector of items that have overlapping connection points. After some
  286. * checks to ensure that the items should actually connect, the items are
  287. * linked together using ConnectedItems().
  288. *
  289. * As a side effect, items are loaded into m_items for BuildConnectionGraph()
  290. *
  291. * @param aSheet is the path to the sheet of all items in the list
  292. * @param aItemList is a list of items to consider
  293. */
  294. void updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
  295. const std::vector<SCH_ITEM*>& aItemList );
  296. /**
  297. * Generates the connection graph (after all item connectivity has been updated)
  298. *
  299. * In the first phase, the algorithm iterates over all items, and then over
  300. * all items that are connected (graphically) to each item, placing them into
  301. * CONNECTION_SUBGRAPHs. Items that can potentially drive connectivity (i.e.
  302. * labels, pins, etc.) are added to the m_drivers vector of the subgraph.
  303. *
  304. * In the second phase, each subgraph is resolved. To resolve a subgraph,
  305. * the driver is first selected by CONNECTION_SUBGRAPH::ResolveDrivers(),
  306. * and then the connection for the chosen driver is propagated to all the
  307. * other items in the subgraph.
  308. */
  309. void buildConnectionGraph();
  310. /**
  311. * Helper to assign a new net code to a connection
  312. *
  313. * @return the assigned code
  314. */
  315. int assignNewNetCode( SCH_CONNECTION& aConnection );
  316. /**
  317. * Ensures all members of the bus connection have a valid net code assigned
  318. * @param aConnection is a bus connection
  319. */
  320. void assignNetCodesToBus( SCH_CONNECTION* aConnection );
  321. /**
  322. * Updates all neighbors of a subgraph with this one's connectivity info
  323. *
  324. * If this subgraph contains hierarchical links, this method will descent the
  325. * hierarchy and propagate the connectivity across all linked sheets.
  326. */
  327. void propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph );
  328. /**
  329. * Search for a matching bus member inside a bus connection
  330. *
  331. * For bus groups, this returns a bus member that matches aSearch by name.
  332. * For bus vectors, this returns a bus member that matches by vector index.
  333. *
  334. * @param aBusConnection is the bus connection to search
  335. * @param aSearch is the net connection to search for
  336. * @returns a member of aBusConnection that matches aSearch
  337. */
  338. static SCH_CONNECTION* matchBusMember( SCH_CONNECTION* aBusConnection,
  339. SCH_CONNECTION* aSearch );
  340. /**
  341. * Builds a new default connection for the given item based on its properties.
  342. * Handles strong drivers (power pins and labels) only
  343. *
  344. * @param aItem is an item that can generate a connection name
  345. * @param aSubgraph is used to determine the sheet to use and retrieve the cached name
  346. * @return a connection generated from the item, or nullptr if item is not valid
  347. */
  348. std::shared_ptr<SCH_CONNECTION> getDefaultConnection( SCH_ITEM* aItem,
  349. CONNECTION_SUBGRAPH* aSubgraph );
  350. void recacheSubgraphName( CONNECTION_SUBGRAPH* aSubgraph, const wxString& aOldName );
  351. /**
  352. * If the subgraph has multiple drivers of equal priority that are graphically connected,
  353. * ResolveDrivers() will have stored the second driver for use by this function, which actually
  354. * creates the markers
  355. * @param aSubgraph is the subgraph to examine
  356. * @return true for no errors, false for errors
  357. */
  358. bool ercCheckMultipleDrivers( const CONNECTION_SUBGRAPH* aSubgraph );
  359. /**
  360. * Checks one subgraph for conflicting connections between net and bus labels
  361. *
  362. * For example, a net wire connected to a bus port/pin, or vice versa
  363. *
  364. * @param aSubgraph is the subgraph to examine
  365. * @return true for no errors, false for errors
  366. */
  367. bool ercCheckBusToNetConflicts( const CONNECTION_SUBGRAPH* aSubgraph );
  368. /**
  369. * Checks one subgraph for conflicting connections between two bus items
  370. *
  371. * For example, a labeled bus wire connected to a hierarchical sheet pin
  372. * where the labeled bus doesn't contain any of the same bus members as the
  373. * sheet pin
  374. *
  375. * @param aSubgraph is the subgraph to examine
  376. * @return true for no errors, false for errors
  377. */
  378. bool ercCheckBusToBusConflicts( const CONNECTION_SUBGRAPH* aSubgraph );
  379. /**
  380. * Checks one subgraph for conflicting bus entry to bus connections
  381. *
  382. * For example, a wire with label "A0" is connected to a bus labeled "D[8..0]"
  383. *
  384. * Will also check for mistakes related to bus group names, for example:
  385. * A bus group named "USB{DP DM}" should have bus entry connections like
  386. * "USB.DP" but someone might accidentally just enter "DP"
  387. *
  388. * @param aSubgraph is the subgraph to examine
  389. * @return true for no errors, false for errors
  390. */
  391. bool ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH* aSubgraph );
  392. /**
  393. * Checks one subgraph for proper presence or absence of no-connect symbols
  394. *
  395. * A pin with a no-connect symbol should not have any connections
  396. * A pin without a no-connect symbol should have at least one connection
  397. *
  398. * @param aSubgraph is the subgraph to examine
  399. * @return true for no errors, false for errors
  400. */
  401. bool ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph );
  402. /**
  403. * Checks one subgraph for floating wires
  404. *
  405. * Will throw an error for any subgraph that consists of just wires with no driver
  406. *
  407. * @param aSubgraph is the subgraph to examine
  408. * @return true for no errors, false for errors
  409. */
  410. bool ercCheckFloatingWires( const CONNECTION_SUBGRAPH* aSubgraph );
  411. /**
  412. * Checks one subgraph for proper connection of labels
  413. *
  414. * Labels should be connected to something
  415. *
  416. * @param aSubgraph is the subgraph to examine
  417. * @param aCheckGlobalLabels is true if global labels should be checked for loneliness
  418. * @return true for no errors, false for errors
  419. */
  420. bool ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph );
  421. /**
  422. * Checks that a hierarchical sheet has at least one matching label inside the sheet for each
  423. * port on the parent sheet object
  424. *
  425. * @param aSubgraph is the subgraph to examine
  426. * @return the number of errors found
  427. */
  428. int ercCheckHierSheets();
  429. public:
  430. // TODO(JE) Remove this when pressure valve is removed
  431. static bool m_allowRealTime;
  432. private:
  433. // All the sheets in the schematic (as long as we don't have partial updates)
  434. SCH_SHEET_LIST m_sheetList;
  435. // All connectable items in the schematic
  436. std::vector<SCH_ITEM*> m_items;
  437. // The owner of all CONNECTION_SUBGRAPH objects
  438. std::vector<CONNECTION_SUBGRAPH*> m_subgraphs;
  439. // Cache of a subset of m_subgraphs
  440. std::vector<CONNECTION_SUBGRAPH*> m_driver_subgraphs;
  441. // Cache to lookup subgraphs in m_driver_subgraphs by sheet path
  442. std::unordered_map<SCH_SHEET_PATH, std::vector<CONNECTION_SUBGRAPH*>> m_sheet_to_subgraphs_map;
  443. std::vector<std::pair<SCH_SHEET_PATH, SCH_PIN*>> m_invisible_power_pins;
  444. std::unordered_map< wxString, std::shared_ptr<BUS_ALIAS> > m_bus_alias_cache;
  445. std::map<wxString, int> m_net_name_to_code_map;
  446. std::map<wxString, int> m_bus_name_to_code_map;
  447. std::map<wxString, std::vector<const CONNECTION_SUBGRAPH*>> m_global_label_cache;
  448. std::map< std::pair<SCH_SHEET_PATH, wxString>,
  449. std::vector<const CONNECTION_SUBGRAPH*> > m_local_label_cache;
  450. std::unordered_map<wxString, std::vector<CONNECTION_SUBGRAPH*>> m_net_name_to_subgraphs_map;
  451. std::map<SCH_ITEM*, CONNECTION_SUBGRAPH*> m_item_to_subgraph_map;
  452. NET_MAP m_net_code_to_subgraphs_map;
  453. int m_last_net_code;
  454. int m_last_bus_code;
  455. int m_last_subgraph_code;
  456. SCHEMATIC* m_schematic; ///< The schematic this graph represents
  457. };
  458. #endif