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.

327 lines
11 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018 CERN
  5. * @author Jon Evans <jon@craftyjon.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #ifndef _CONNECTION_GRAPH_H
  21. #define _CONNECTION_GRAPH_H
  22. #include <mutex>
  23. #include <vector>
  24. #include <common.h>
  25. #include <erc_settings.h>
  26. #include <sch_connection.h>
  27. #include <sch_item_struct.h>
  28. #ifdef DEBUG
  29. // Uncomment this line to enable connectivity debugging features
  30. // #define CONNECTIVITY_DEBUG
  31. #endif
  32. class SCH_PIN_CONNECTION;
  33. class SCH_EDIT_FRAME;
  34. /**
  35. * A subgraph is a set of items that are "physically" connected in the schematic.
  36. *
  37. * For example, a label connected to a wire and so on.
  38. * A net is composed of one or more subgraphs.
  39. *
  40. * A set of items that appears to be physically connected may actually be more
  41. * than one subgraph, because some items don't connect electrically.
  42. *
  43. * For example, multiple bus wires can come together at a junction but have
  44. * different labels on each branch. Each label+wire branch is its own subgraph.
  45. *
  46. */
  47. class CONNECTION_SUBGRAPH
  48. {
  49. public:
  50. CONNECTION_SUBGRAPH( SCH_EDIT_FRAME* aFrame ) :
  51. m_dirty( false ), m_code( -1 ), m_multiple_power_ports( false ),
  52. m_no_connect( nullptr ), m_driver( nullptr ), m_frame( aFrame )
  53. {}
  54. /**
  55. * Determines which potential driver should drive the subgraph.
  56. *
  57. * If multiple possible drivers exist, picks one according to the priority.
  58. * If multiple "winners" exist, returns false and sets m_driver to nullptr.
  59. *
  60. * @param aCreateMarkers controls whether ERC markers should be added for conflicts
  61. * @return true if m_driver was set, or false if a conflict occurred
  62. */
  63. bool ResolveDrivers( bool aCreateMarkers = false );
  64. /**
  65. * Returns the fully-qualified net name for this subgraph (if one exists)
  66. */
  67. wxString GetNetName();
  68. /// Returns all the bus labels attached to this subgraph (if any)
  69. std::vector<SCH_ITEM*> GetBusLabels();
  70. bool m_dirty;
  71. long m_code;
  72. /// True if this subgraph contains multiple power ports to join in one net
  73. bool m_multiple_power_ports;
  74. /// No-connect item in graph, if any
  75. SCH_ITEM* m_no_connect;
  76. std::vector<SCH_ITEM*> m_items;
  77. std::vector<SCH_ITEM*> m_drivers;
  78. SCH_ITEM* m_driver;
  79. SCH_SHEET_PATH m_sheet;
  80. // Needed for m_UserUnits for now; maybe refactor later
  81. SCH_EDIT_FRAME* m_frame;
  82. /**
  83. * This map stores pointers to other subgraphs on the same sheet as this one
  84. * which should be connected to this one.
  85. *
  86. * For example, if this subgraph is part of the bus D[7..0] and there is
  87. * another subgraph on this sheet with connection D7, this map will include
  88. * a pointer to that subgraph under the key D7 (where the key comes from
  89. * the m_members list of the SCH_CONNECTION that drives this subgraph)
  90. */
  91. std::unordered_map< std::shared_ptr<SCH_CONNECTION>,
  92. std::vector<CONNECTION_SUBGRAPH*> > m_neighbor_map;
  93. };
  94. /**
  95. * Calculates the connectivity of a schematic and generates netlists
  96. */
  97. class CONNECTION_GRAPH
  98. {
  99. public:
  100. CONNECTION_GRAPH( SCH_EDIT_FRAME* aFrame) :
  101. m_frame( aFrame )
  102. {}
  103. void Reset();
  104. /**
  105. * Updates the connection graph for the given list of sheets.
  106. *
  107. * @param aSheetList should be the whole schematic for now
  108. */
  109. void Recalculate( SCH_SHEET_LIST aSheetList );
  110. /**
  111. * Updates the connectivity graph based on a single item
  112. */
  113. void RebuildGraphForItem( SCH_ITEM* aItem );
  114. /**
  115. * Returns a bus alias pointer for the given name if it exists (from cache)
  116. *
  117. * CONNECTION_GRAPH caches these, they are owned by the SCH_SCREEN that
  118. * the alias was defined on. The cache is only used to update the graph.
  119. */
  120. std::shared_ptr<BUS_ALIAS> GetBusAlias( wxString aName );
  121. /**
  122. * Determines which subgraphs have more than one conflicting bus label.
  123. *
  124. * @see DIALOG_MIGRATE_BUSES
  125. * @return a list of subgraphs that need migration
  126. */
  127. std::vector<CONNECTION_SUBGRAPH*> GetBusesNeedingMigration();
  128. /**
  129. * Returns true if the graph makes use of any of the new bus features
  130. *
  131. * For quality control during rollout of new bus features:
  132. * - Aliases
  133. * - Bus groups
  134. */
  135. bool UsesNewBusFeatures() const;
  136. /**
  137. * Runs electrical rule checks on the connectivity graph.
  138. *
  139. * Precondition: graph is up-to-date
  140. *
  141. * @param aSettings is used to control which tests to run
  142. * @param aCreateMarkers controls whether error markers are created
  143. * @return the number of errors found
  144. */
  145. int RunERC( const ERC_SETTINGS& aSettings, bool aCreateMarkers = true );
  146. // TODO(JE) firm up API and move to private
  147. std::map<int, std::vector<CONNECTION_SUBGRAPH*> > m_net_code_to_subgraphs_map;
  148. private:
  149. std::vector<SCH_ITEM*> m_items;
  150. std::vector<CONNECTION_SUBGRAPH*> m_subgraphs;
  151. std::vector<SCH_PIN_CONNECTION*> m_invisible_power_pins;
  152. std::map<wxString, std::shared_ptr<BUS_ALIAS>> m_bus_alias_cache;
  153. std::map<wxString, int> m_net_name_to_code_map;
  154. std::map<wxString, int> m_bus_name_to_code_map;
  155. std::unordered_map<int, CONNECTION_SUBGRAPH*> m_subgraph_code_map;
  156. int m_last_net_code;
  157. int m_last_bus_code;
  158. int m_last_subgraph_code;
  159. std::mutex m_item_mutex;
  160. // Needed for m_UserUnits for now; maybe refactor later
  161. SCH_EDIT_FRAME* m_frame;
  162. /**
  163. * Updates the graphical connectivity between items (i.e. where they touch)
  164. * The items passed in must be on the same sheet.
  165. *
  166. * In the first phase, all items in aItemList have their connections
  167. * initialized for the given sheet (since they may have connections on more
  168. * than one sheet, and each needs to be calculated individually). The
  169. * graphical connection points for the item are added to a map that stores
  170. * (x, y) -> [list of items].
  171. *
  172. * Any item that is stored in the list of items that have a connection point
  173. * at a given (x, y) location will eventually be electrically connected.
  174. * This means that we can't store SCH_COMPONENTs in this map -- we must store
  175. * a structure that links a specific pin on a component back to that
  176. * component: a SCH_PIN_CONNECTION. This wrapper class is a convenience for
  177. * linking a pin and component to a specific (x, y) point.
  178. *
  179. * In the second phase, we iterate over each value in the map, which is a
  180. * vector of items that have overlapping connection points. After some
  181. * checks to ensure that the items should actually connect, the items are
  182. * linked together using ConnectedItems().
  183. *
  184. * As a side effect, items are loaded into m_items for BuildConnectionGraph()
  185. *
  186. * @param aSheet is the path to the sheet of all items in the list
  187. * @param aItemList is a list of items to consider
  188. */
  189. void updateItemConnectivity( SCH_SHEET_PATH aSheet,
  190. std::vector<SCH_ITEM*> aItemList );
  191. /**
  192. * Generates the connection graph (after all item connectivity has been updated)
  193. *
  194. * In the first phase, the algorithm iterates over all items, and then over
  195. * all items that are connected (graphically) to each item, placing them into
  196. * CONNECTION_SUBGRAPHs. Items that can potentially drive connectivity (i.e.
  197. * labels, pins, etc.) are added to the m_drivers vector of the subgraph.
  198. *
  199. * In the second phase, each subgraph is resolved. To resolve a subgraph,
  200. * the driver is first selected by CONNECTION_SUBGRAPH::ResolveDrivers(),
  201. * and then the connection for the chosen driver is propagated to all the
  202. * other items in the subgraph.
  203. */
  204. void buildConnectionGraph();
  205. /**
  206. * Helper to assign a new net code to a connection
  207. *
  208. * @return the assigned code
  209. */
  210. int assignNewNetCode( SCH_CONNECTION& aConnection );
  211. /**
  212. * Checks one subgraph for conflicting connections between net and bus labels
  213. *
  214. * For example, a net wire connected to a bus port/pin, or vice versa
  215. *
  216. * @param aSubgraph is the subgraph to examine
  217. * @param aCreateMarkers controls whether error markers are created
  218. * @return true for no errors, false for errors
  219. */
  220. bool ercCheckBusToNetConflicts( CONNECTION_SUBGRAPH* aSubgraph,
  221. bool aCreateMarkers );
  222. /**
  223. * Checks one subgraph for conflicting connections between two bus items
  224. *
  225. * For example, a labeled bus wire connected to a hierarchical sheet pin
  226. * where the labeled bus doesn't contain any of the same bus members as the
  227. * sheet pin
  228. *
  229. * @param aSubgraph is the subgraph to examine
  230. * @param aCreateMarkers controls whether error markers are created
  231. * @return true for no errors, false for errors
  232. */
  233. bool ercCheckBusToBusConflicts( CONNECTION_SUBGRAPH* aSubgraph,
  234. bool aCreateMarkers );
  235. /**
  236. * Checks one subgraph for conflicting bus entry to bus connections
  237. *
  238. * For example, a wire with label "A0" is connected to a bus labeled "D[8..0]"
  239. *
  240. * Will also check for mistakes related to bus group names, for example:
  241. * A bus group named "USB{DP DM}" should have bus entry connections like
  242. * "USB.DP" but someone might accidentally just enter "DP"
  243. *
  244. * @param aSubgraph is the subgraph to examine
  245. * @param aCreateMarkers controls whether error markers are created
  246. * @return true for no errors, false for errors
  247. */
  248. bool ercCheckBusToBusEntryConflicts( CONNECTION_SUBGRAPH* aSubgraph,
  249. bool aCreateMarkers );
  250. /**
  251. * Checks one subgraph for proper presence or absence of no-connect symbols
  252. *
  253. * A pin with a no-connect symbol should not have any connections
  254. * A pin without a no-connect symbol should have at least one connection
  255. *
  256. * @param aSubgraph is the subgraph to examine
  257. * @param aCreateMarkers controls whether error markers are created
  258. * @return true for no errors, false for errors
  259. */
  260. bool ercCheckNoConnects( CONNECTION_SUBGRAPH* aSubgraph,
  261. bool aCreateMarkers );
  262. /**
  263. * Checks one subgraph for proper connection of labels
  264. *
  265. * Labels should be connected to something
  266. *
  267. * @param aSubgraph is the subgraph to examine
  268. * @param aCreateMarkers controls whether error markers are created
  269. * @return true for no errors, false for errors
  270. */
  271. bool ercCheckLabels( CONNECTION_SUBGRAPH* aSubgraph, bool aCreateMarkers );
  272. };
  273. #endif