2019-03-11 21:32:05 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2018 CERN
|
2021-03-25 14:07:16 +00:00
|
|
|
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
2019-03-11 21:32:05 +00:00
|
|
|
* @author Jon Evans <jon@craftyjon.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _CONNECTION_GRAPH_H
|
|
|
|
#define _CONNECTION_GRAPH_H
|
|
|
|
|
|
|
|
#include <mutex>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <erc_settings.h>
|
|
|
|
#include <sch_connection.h>
|
2019-05-10 19:57:24 +00:00
|
|
|
#include <sch_item.h>
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
// Uncomment this line to enable connectivity debugging features
|
|
|
|
// #define CONNECTIVITY_DEBUG
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2020-05-13 02:00:37 +00:00
|
|
|
class CONNECTION_GRAPH;
|
|
|
|
class SCHEMATIC;
|
2019-03-11 21:32:05 +00:00
|
|
|
class SCH_EDIT_FRAME;
|
2019-04-20 01:45:33 +00:00
|
|
|
class SCH_HIERLABEL;
|
|
|
|
class SCH_PIN;
|
|
|
|
class SCH_SHEET_PIN;
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
2019-04-20 01:45:33 +00:00
|
|
|
* A subgraph is a set of items that are electrically connected on a single sheet.
|
2019-03-11 21:32:05 +00:00
|
|
|
*
|
|
|
|
* For example, a label connected to a wire and so on.
|
|
|
|
* A net is composed of one or more subgraphs.
|
|
|
|
*
|
|
|
|
* A set of items that appears to be physically connected may actually be more
|
|
|
|
* than one subgraph, because some items don't connect electrically.
|
|
|
|
*
|
|
|
|
* For example, multiple bus wires can come together at a junction but have
|
|
|
|
* different labels on each branch. Each label+wire branch is its own subgraph.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
class CONNECTION_SUBGRAPH
|
|
|
|
{
|
|
|
|
public:
|
2020-01-03 03:09:02 +00:00
|
|
|
enum class PRIORITY
|
|
|
|
{
|
|
|
|
INVALID = -1,
|
|
|
|
NONE = 0,
|
|
|
|
PIN,
|
|
|
|
SHEET_PIN,
|
|
|
|
HIER_LABEL,
|
|
|
|
LOCAL_LABEL,
|
|
|
|
POWER_PIN,
|
|
|
|
GLOBAL
|
2019-05-07 01:36:01 +00:00
|
|
|
};
|
|
|
|
|
2020-05-13 02:00:37 +00:00
|
|
|
explicit CONNECTION_SUBGRAPH( CONNECTION_GRAPH* aGraph ) :
|
|
|
|
m_graph( aGraph ),
|
|
|
|
m_dirty( false ),
|
|
|
|
m_absorbed( false ),
|
2023-04-04 19:17:17 +00:00
|
|
|
m_is_bus_member( false ),
|
2020-05-13 02:00:37 +00:00
|
|
|
m_absorbed_by( nullptr ),
|
|
|
|
m_code( -1 ),
|
|
|
|
m_multiple_drivers( false ),
|
|
|
|
m_strong_driver( false ),
|
|
|
|
m_local_driver( false ),
|
|
|
|
m_no_connect( nullptr ),
|
|
|
|
m_bus_entry( nullptr ),
|
|
|
|
m_driver( nullptr ),
|
|
|
|
m_driver_connection( nullptr ),
|
2021-01-13 04:03:31 +00:00
|
|
|
m_hier_parent( nullptr ),
|
|
|
|
m_first_driver( nullptr ),
|
|
|
|
m_second_driver( nullptr )
|
2019-03-11 21:32:05 +00:00
|
|
|
{}
|
2020-01-07 05:12:37 +00:00
|
|
|
|
|
|
|
~CONNECTION_SUBGRAPH() = default;
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
/**
|
|
|
|
* Determines which potential driver should drive the subgraph.
|
|
|
|
*
|
|
|
|
* If multiple possible drivers exist, picks one according to the priority.
|
|
|
|
* If multiple "winners" exist, returns false and sets m_driver to nullptr.
|
|
|
|
*
|
2021-01-13 04:03:31 +00:00
|
|
|
* @param aCheckMultipleDrivers controls whether the second driver should be captured for ERC
|
2019-03-11 21:32:05 +00:00
|
|
|
* @return true if m_driver was set, or false if a conflict occurred
|
|
|
|
*/
|
2021-01-13 04:03:31 +00:00
|
|
|
bool ResolveDrivers( bool aCheckMultipleDrivers = false );
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the fully-qualified net name for this subgraph (if one exists)
|
|
|
|
*/
|
2019-04-20 01:45:33 +00:00
|
|
|
wxString GetNetName() const;
|
2019-03-11 21:32:05 +00:00
|
|
|
|
2023-04-04 19:17:17 +00:00
|
|
|
/// Returns all the vector-based bus labels attached to this subgraph (if any)
|
|
|
|
std::vector<SCH_ITEM*> GetVectorBusLabels() const;
|
|
|
|
|
|
|
|
/// Returns all the all bus labels attached to this subgraph (if any)
|
|
|
|
std::vector<SCH_ITEM*> GetAllBusLabels() const;
|
2019-04-20 01:45:33 +00:00
|
|
|
|
|
|
|
/// Returns the candidate net name for a driver
|
2023-01-24 01:20:05 +00:00
|
|
|
const wxString& GetNameForDriver( SCH_ITEM* aItem ) const;
|
2021-01-13 04:03:31 +00:00
|
|
|
|
2022-08-14 11:03:18 +00:00
|
|
|
const wxString GetNetclassForDriver( SCH_ITEM* aItem ) const;
|
|
|
|
|
2019-04-20 01:45:33 +00:00
|
|
|
/// Combines another subgraph on the same sheet into this one.
|
|
|
|
void Absorb( CONNECTION_SUBGRAPH* aOther );
|
|
|
|
|
|
|
|
/// Adds a new item to the subgraph
|
|
|
|
void AddItem( SCH_ITEM* aItem );
|
|
|
|
|
|
|
|
/// Updates all items to match the driver connection
|
|
|
|
void UpdateItemConnections();
|
2019-04-04 02:41:26 +00:00
|
|
|
|
2023-04-08 15:22:34 +00:00
|
|
|
/// Provides a read-only reference to the items in the subgraph
|
|
|
|
const std::vector<SCH_ITEM*>& GetItems() const
|
|
|
|
{
|
|
|
|
return m_items;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Finds all items in the subgraph as well as child subgraphs recursively
|
|
|
|
void getAllConnectedItems( std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>>& aItems, std::set<CONNECTION_SUBGRAPH*>& aSubgraphs );
|
|
|
|
|
2019-05-07 01:36:01 +00:00
|
|
|
/**
|
2021-06-14 18:00:08 +00:00
|
|
|
* Return the priority (higher is more important) of a candidate driver
|
2019-05-07 01:36:01 +00:00
|
|
|
*
|
|
|
|
* 0: Invalid driver
|
2021-06-14 18:00:08 +00:00
|
|
|
* 1: Symbol pin
|
2019-05-07 01:36:01 +00:00
|
|
|
* 2: Hierarchical sheet pin
|
|
|
|
* 3: Hierarchical label
|
|
|
|
* 4: Local label
|
|
|
|
* 5: Power pin
|
|
|
|
* 6: Global label
|
|
|
|
*
|
|
|
|
* @param aDriver is the item to inspect
|
|
|
|
* @return a PRIORITY
|
|
|
|
*/
|
|
|
|
static PRIORITY GetDriverPriority( SCH_ITEM* aDriver );
|
|
|
|
|
2020-10-11 23:29:06 +00:00
|
|
|
PRIORITY GetDriverPriority()
|
|
|
|
{
|
|
|
|
if( m_driver )
|
|
|
|
return GetDriverPriority( m_driver );
|
|
|
|
else
|
|
|
|
return PRIORITY::NONE;
|
|
|
|
}
|
|
|
|
|
2021-03-25 14:07:16 +00:00
|
|
|
private:
|
|
|
|
wxString driverName( SCH_ITEM* aItem ) const;
|
|
|
|
|
|
|
|
public:
|
2020-05-13 02:00:37 +00:00
|
|
|
CONNECTION_GRAPH* m_graph;
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
bool m_dirty;
|
|
|
|
|
2019-05-05 04:03:58 +00:00
|
|
|
/// True if this subgraph has been absorbed into another. No pointers here are safe if so!
|
2019-04-20 01:45:33 +00:00
|
|
|
bool m_absorbed;
|
|
|
|
|
2023-04-04 19:17:17 +00:00
|
|
|
/**
|
|
|
|
* True if the subgraph is not actually part of a net. These are created for bus members
|
|
|
|
* to ensure that bus-to-bus connection happens but they don't have any valid data
|
|
|
|
*/
|
|
|
|
bool m_is_bus_member;
|
|
|
|
|
2019-05-05 23:48:43 +00:00
|
|
|
/// If this subgraph is absorbed, points to the absorbing (and valid) subgraph
|
|
|
|
CONNECTION_SUBGRAPH* m_absorbed_by;
|
|
|
|
|
2023-04-08 15:22:34 +00:00
|
|
|
/// Set of subgraphs that have been absorbed by this subgraph
|
|
|
|
std::set<CONNECTION_SUBGRAPH*> m_absorbed_subgraphs;
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
long m_code;
|
|
|
|
|
2019-04-04 02:41:26 +00:00
|
|
|
/**
|
|
|
|
* True if this subgraph contains more than one driver that should be
|
|
|
|
* shorted together in the netlist. For example, two labels or
|
|
|
|
* two power ports.
|
|
|
|
*/
|
|
|
|
bool m_multiple_drivers;
|
2019-03-11 21:32:05 +00:00
|
|
|
|
2019-03-18 22:38:06 +00:00
|
|
|
/// True if the driver is "strong": a label or power object
|
|
|
|
bool m_strong_driver;
|
|
|
|
|
2019-04-08 03:54:24 +00:00
|
|
|
/// True if the driver is a local (i.e. non-global) type
|
|
|
|
bool m_local_driver;
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
/// No-connect item in graph, if any
|
|
|
|
SCH_ITEM* m_no_connect;
|
|
|
|
|
2019-04-04 01:47:26 +00:00
|
|
|
/// Bus entry in graph, if any
|
|
|
|
SCH_ITEM* m_bus_entry;
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
std::vector<SCH_ITEM*> m_items;
|
|
|
|
|
|
|
|
std::vector<SCH_ITEM*> m_drivers;
|
|
|
|
|
|
|
|
SCH_ITEM* m_driver;
|
|
|
|
|
|
|
|
SCH_SHEET_PATH m_sheet;
|
|
|
|
|
2019-03-31 18:49:26 +00:00
|
|
|
/// Cache for driver connection
|
|
|
|
SCH_CONNECTION* m_driver_connection;
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
/**
|
2019-04-20 01:45:33 +00:00
|
|
|
* If a subgraph is a bus, this map contains links between the bus members and any
|
|
|
|
* local sheet neighbors with the same connection name.
|
2019-03-11 21:32:05 +00:00
|
|
|
*
|
2019-04-20 01:45:33 +00:00
|
|
|
* For example, if this subgraph is a bus D[7..0], and on the same sheet there is
|
|
|
|
* a net with label D7, this map will contain an entry for the D7 bus member, and
|
2023-04-08 15:22:34 +00:00
|
|
|
* the set will contain a pointer to the D7 net subgraph.
|
2019-03-11 21:32:05 +00:00
|
|
|
*/
|
|
|
|
std::unordered_map< std::shared_ptr<SCH_CONNECTION>,
|
2019-05-05 23:48:43 +00:00
|
|
|
std::unordered_set<CONNECTION_SUBGRAPH*> > m_bus_neighbors;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If this is a net, this vector contains links to any same-sheet buses that contain it.
|
|
|
|
* The string key is the name of the connection that forms the link (which isn't necessarily
|
|
|
|
* the same as the name of the connection driving this subgraph)
|
|
|
|
*/
|
|
|
|
std::unordered_map< std::shared_ptr<SCH_CONNECTION>,
|
|
|
|
std::unordered_set<CONNECTION_SUBGRAPH*> > m_bus_parents;
|
2019-04-20 01:45:33 +00:00
|
|
|
|
|
|
|
// Cache for lookup of any hierarchical (sheet) pins on this subgraph (for referring down)
|
|
|
|
std::vector<SCH_SHEET_PIN*> m_hier_pins;
|
|
|
|
|
|
|
|
// Cache for lookup of any hierarchical ports on this subgraph (for referring up)
|
|
|
|
std::vector<SCH_HIERLABEL*> m_hier_ports;
|
2019-11-30 02:10:16 +00:00
|
|
|
|
|
|
|
// If not null, this indicates the subgraph on a higher level sheet that is linked to this one
|
|
|
|
CONNECTION_SUBGRAPH* m_hier_parent;
|
2020-07-09 22:14:27 +00:00
|
|
|
|
2023-04-08 15:22:34 +00:00
|
|
|
// If not null, this indicates the subgraph(s) on a lower level sheet that are linked to this one
|
|
|
|
std::unordered_set<CONNECTION_SUBGRAPH*> m_hier_children;
|
|
|
|
|
2020-07-09 22:14:27 +00:00
|
|
|
/// A cache of escaped netnames from schematic items
|
2023-01-24 01:20:05 +00:00
|
|
|
mutable std::unordered_map<SCH_ITEM*, wxString> m_driver_name_cache;
|
2021-01-13 04:03:31 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores the primary driver for the multiple drivers ERC check. This is the chosen driver
|
|
|
|
* before subgraphs are absorbed (so m_driver may be different)
|
|
|
|
*/
|
|
|
|
SCH_ITEM* m_first_driver;
|
|
|
|
|
|
|
|
/// Used for multiple drivers ERC message; stores the second possible driver (or nullptr)
|
|
|
|
SCH_ITEM* m_second_driver;
|
2019-03-11 21:32:05 +00:00
|
|
|
};
|
|
|
|
|
2022-08-03 09:10:23 +00:00
|
|
|
struct NET_NAME_CODE_CACHE_KEY
|
|
|
|
{
|
|
|
|
wxString Name;
|
|
|
|
int Netcode;
|
|
|
|
|
|
|
|
bool operator==(const NET_NAME_CODE_CACHE_KEY& other) const
|
|
|
|
{
|
|
|
|
return Name == other.Name && Netcode == other.Netcode;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
template <>
|
|
|
|
struct hash<NET_NAME_CODE_CACHE_KEY>
|
|
|
|
{
|
|
|
|
std::size_t operator()( const NET_NAME_CODE_CACHE_KEY& k ) const
|
|
|
|
{
|
|
|
|
const std::size_t prime = 19937;
|
|
|
|
|
|
|
|
return hash<wxString>()( k.Name ) ^ ( hash<int>()( k.Netcode ) * prime );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2020-01-18 17:57:02 +00:00
|
|
|
|
|
|
|
/// Associates a NET_CODE_NAME with all the subgraphs in that net
|
2022-08-03 09:10:23 +00:00
|
|
|
typedef std::unordered_map<NET_NAME_CODE_CACHE_KEY, std::vector<CONNECTION_SUBGRAPH*>> NET_MAP;
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculates the connectivity of a schematic and generates netlists
|
|
|
|
*/
|
|
|
|
class CONNECTION_GRAPH
|
|
|
|
{
|
|
|
|
public:
|
2020-05-13 02:00:37 +00:00
|
|
|
CONNECTION_GRAPH( SCHEMATIC* aSchematic = nullptr ) :
|
|
|
|
m_last_net_code( 1 ),
|
2020-01-12 13:00:42 +00:00
|
|
|
m_last_bus_code( 1 ),
|
|
|
|
m_last_subgraph_code( 1 ),
|
2020-05-13 02:00:37 +00:00
|
|
|
m_schematic( aSchematic )
|
2019-03-11 21:32:05 +00:00
|
|
|
{}
|
|
|
|
|
2020-01-07 05:12:37 +00:00
|
|
|
~CONNECTION_GRAPH()
|
|
|
|
{
|
|
|
|
Reset();
|
|
|
|
}
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
void Reset();
|
|
|
|
|
2020-05-13 02:00:37 +00:00
|
|
|
void SetSchematic( SCHEMATIC* aSchematic )
|
|
|
|
{
|
|
|
|
m_schematic = aSchematic;
|
|
|
|
}
|
|
|
|
|
2023-04-08 15:22:34 +00:00
|
|
|
void SetLastCodes( const CONNECTION_GRAPH* aOther )
|
|
|
|
{
|
|
|
|
m_last_net_code = aOther->m_last_net_code;
|
|
|
|
m_last_bus_code = aOther->m_last_bus_code;
|
|
|
|
m_last_subgraph_code = aOther->m_last_subgraph_code;
|
|
|
|
}
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
/**
|
|
|
|
* Updates the connection graph for the given list of sheets.
|
|
|
|
*
|
2019-03-30 15:57:30 +00:00
|
|
|
* @param aSheetList is the list of possibly modified sheets
|
|
|
|
* @param aUnconditional is true if an unconditional full recalculation should be done
|
2020-12-06 21:23:16 +00:00
|
|
|
* @param aChangedItemHandler an optional handler to receive any changed items
|
2019-03-11 21:32:05 +00:00
|
|
|
*/
|
2020-12-06 21:23:16 +00:00
|
|
|
void Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnconditional = false,
|
|
|
|
std::function<void( SCH_ITEM* )>* aChangedItemHandler = nullptr );
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a bus alias pointer for the given name if it exists (from cache)
|
|
|
|
*
|
|
|
|
* CONNECTION_GRAPH caches these, they are owned by the SCH_SCREEN that
|
|
|
|
* the alias was defined on. The cache is only used to update the graph.
|
|
|
|
*/
|
2019-05-05 23:48:43 +00:00
|
|
|
std::shared_ptr<BUS_ALIAS> GetBusAlias( const wxString& aName );
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines which subgraphs have more than one conflicting bus label.
|
|
|
|
*
|
|
|
|
* @see DIALOG_MIGRATE_BUSES
|
|
|
|
* @return a list of subgraphs that need migration
|
|
|
|
*/
|
|
|
|
|
2019-04-20 01:45:33 +00:00
|
|
|
std::vector<const CONNECTION_SUBGRAPH*> GetBusesNeedingMigration();
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Runs electrical rule checks on the connectivity graph.
|
|
|
|
*
|
|
|
|
* Precondition: graph is up-to-date
|
|
|
|
*
|
|
|
|
* @return the number of errors found
|
|
|
|
*/
|
2020-03-10 18:46:57 +00:00
|
|
|
int RunERC();
|
2019-03-11 21:32:05 +00:00
|
|
|
|
2020-01-18 17:57:02 +00:00
|
|
|
const NET_MAP& GetNetMap() const { return m_net_code_to_subgraphs_map; }
|
|
|
|
|
2020-05-21 03:40:31 +00:00
|
|
|
/**
|
|
|
|
* Returns the subgraph for a given net name on a given sheet
|
|
|
|
* @param aNetName is the local net name to look for
|
|
|
|
* @param aPath is a sheet path to look on
|
|
|
|
* @return the subgraph matching the query, or nullptr if none is found
|
|
|
|
*/
|
|
|
|
CONNECTION_SUBGRAPH* FindSubgraphByName( const wxString& aNetName,
|
|
|
|
const SCH_SHEET_PATH& aPath );
|
|
|
|
|
2020-05-24 14:46:05 +00:00
|
|
|
/**
|
|
|
|
* Retrieves a subgraph for the given net name, if one exists.
|
|
|
|
* Searches every sheet
|
|
|
|
* @param aNetName is the full net name to search for
|
|
|
|
* @return the subgraph matching the query, or nullptr if none is found
|
|
|
|
*/
|
|
|
|
CONNECTION_SUBGRAPH* FindFirstSubgraphByName( const wxString& aNetName );
|
|
|
|
|
|
|
|
CONNECTION_SUBGRAPH* GetSubgraphForItem( SCH_ITEM* aItem );
|
|
|
|
|
2022-12-06 22:08:36 +00:00
|
|
|
/**
|
|
|
|
* Returns the fully-resolved netname for a given subgraph
|
|
|
|
* @param aSubGraph Reference to the subgraph
|
|
|
|
* @return Netname string usable with m_net_name_to_subgraphs_map
|
|
|
|
*/
|
|
|
|
wxString GetResolvedSubgraphName( const CONNECTION_SUBGRAPH* aSubGraph ) const;
|
|
|
|
|
2023-04-08 15:22:34 +00:00
|
|
|
/**
|
|
|
|
* For a set of items, this will remove the connected items and their
|
|
|
|
* associated data including subgraphs and generated codes from the connection graph.
|
|
|
|
*
|
|
|
|
* @param aItems A vector of items whose presence should be removed from the graph
|
|
|
|
* @return The full set of all items associated with the input items that were removed
|
|
|
|
*/
|
|
|
|
std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> ExtractAffectedItems(
|
|
|
|
const std::set<SCH_ITEM*> &aItems );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Combines the input graph contents into the current graph. After merging, the
|
|
|
|
* original graph is invalid.
|
|
|
|
*
|
|
|
|
* @param aGraph Input graph reference to add to the current graph
|
|
|
|
*/
|
|
|
|
void Merge( CONNECTION_GRAPH& aGraph );
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
private:
|
|
|
|
/**
|
|
|
|
* Updates the graphical connectivity between items (i.e. where they touch)
|
|
|
|
* The items passed in must be on the same sheet.
|
|
|
|
*
|
|
|
|
* In the first phase, all items in aItemList have their connections
|
|
|
|
* initialized for the given sheet (since they may have connections on more
|
|
|
|
* than one sheet, and each needs to be calculated individually). The
|
|
|
|
* graphical connection points for the item are added to a map that stores
|
|
|
|
* (x, y) -> [list of items].
|
|
|
|
*
|
|
|
|
* Any item that is stored in the list of items that have a connection point
|
|
|
|
* at a given (x, y) location will eventually be electrically connected.
|
2021-06-10 14:10:55 +00:00
|
|
|
* This means that we can't store SCH_SYMBOLs in this map -- we must store
|
2021-05-05 21:41:51 +00:00
|
|
|
* a structure that links a specific pin on a symbol back to that symbol: a
|
|
|
|
* SCH_PIN_CONNECTION. This wrapper class is a convenience for linking a pin
|
|
|
|
* and symbol to a specific (x, y) point.
|
2019-03-11 21:32:05 +00:00
|
|
|
*
|
|
|
|
* In the second phase, we iterate over each value in the map, which is a
|
|
|
|
* vector of items that have overlapping connection points. After some
|
|
|
|
* checks to ensure that the items should actually connect, the items are
|
|
|
|
* linked together using ConnectedItems().
|
|
|
|
*
|
|
|
|
* As a side effect, items are loaded into m_items for BuildConnectionGraph()
|
|
|
|
*
|
|
|
|
* @param aSheet is the path to the sheet of all items in the list
|
|
|
|
* @param aItemList is a list of items to consider
|
|
|
|
*/
|
2020-07-08 21:42:05 +00:00
|
|
|
void updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
2020-01-12 18:40:50 +00:00
|
|
|
const std::vector<SCH_ITEM*>& aItemList );
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates the connection graph (after all item connectivity has been updated)
|
|
|
|
*
|
|
|
|
* In the first phase, the algorithm iterates over all items, and then over
|
|
|
|
* all items that are connected (graphically) to each item, placing them into
|
|
|
|
* CONNECTION_SUBGRAPHs. Items that can potentially drive connectivity (i.e.
|
|
|
|
* labels, pins, etc.) are added to the m_drivers vector of the subgraph.
|
|
|
|
*
|
|
|
|
* In the second phase, each subgraph is resolved. To resolve a subgraph,
|
|
|
|
* the driver is first selected by CONNECTION_SUBGRAPH::ResolveDrivers(),
|
|
|
|
* and then the connection for the chosen driver is propagated to all the
|
|
|
|
* other items in the subgraph.
|
|
|
|
*/
|
2022-08-14 11:03:18 +00:00
|
|
|
void buildConnectionGraph( std::function<void( SCH_ITEM* )>* aChangedItemHandler );
|
2019-03-11 21:32:05 +00:00
|
|
|
|
2022-03-11 21:46:21 +00:00
|
|
|
/**
|
|
|
|
* Generates individual item subgraphs on a per-sheet basis
|
|
|
|
*/
|
|
|
|
void buildItemSubGraphs();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Finds all subgraphs in the connection graph and calls ResolveDrivers() in
|
|
|
|
* parallel
|
|
|
|
*/
|
|
|
|
void resolveAllDrivers();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps the driver values for each subgraph
|
|
|
|
*/
|
|
|
|
void collectAllDriverValues();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Iterate through the invisible power pins to collect the global labels
|
|
|
|
* as drivers
|
|
|
|
*/
|
|
|
|
void generateInvisiblePinSubGraphs();
|
|
|
|
|
2023-04-04 19:17:17 +00:00
|
|
|
/**
|
|
|
|
* Iterate through labels to create placeholders for bus elements
|
|
|
|
*/
|
|
|
|
void generateBusAliasMembers();
|
|
|
|
|
2022-03-11 21:46:21 +00:00
|
|
|
/**
|
|
|
|
* Process all subgraphs to assign netcodes and merge subgraphs based on labels
|
|
|
|
*/
|
|
|
|
void processSubGraphs();
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
/**
|
|
|
|
* Helper to assign a new net code to a connection
|
|
|
|
*
|
|
|
|
* @return the assigned code
|
|
|
|
*/
|
|
|
|
int assignNewNetCode( SCH_CONNECTION& aConnection );
|
|
|
|
|
2023-04-04 19:17:17 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param aNetName string with the netname for coding
|
|
|
|
* @return existing netcode (if it exists) or newly created one
|
|
|
|
*/
|
|
|
|
int getOrCreateNetCode( const wxString& aNetName );
|
|
|
|
|
2019-04-20 01:45:33 +00:00
|
|
|
/**
|
|
|
|
* Ensures all members of the bus connection have a valid net code assigned
|
|
|
|
* @param aConnection is a bus connection
|
|
|
|
*/
|
|
|
|
void assignNetCodesToBus( SCH_CONNECTION* aConnection );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates all neighbors of a subgraph with this one's connectivity info
|
|
|
|
*
|
|
|
|
* If this subgraph contains hierarchical links, this method will descent the
|
|
|
|
* hierarchy and propagate the connectivity across all linked sheets.
|
2023-01-13 01:01:09 +00:00
|
|
|
*
|
|
|
|
* @param aSubgraph is the subgraph being processed
|
|
|
|
* @param aForce prevents this routine from skipping subgraphs
|
2019-04-20 01:45:33 +00:00
|
|
|
*/
|
2023-01-13 01:01:09 +00:00
|
|
|
void propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph, bool aForce );
|
2019-04-20 01:45:33 +00:00
|
|
|
|
2023-04-08 15:22:34 +00:00
|
|
|
/**
|
|
|
|
* Removes references to the given subgraphs from all structures in the
|
|
|
|
* connection graph.
|
|
|
|
*
|
|
|
|
* @param aSubgraphs set of unique subgraphs to find/remove
|
|
|
|
*/
|
|
|
|
void removeSubgraphs( std::set<CONNECTION_SUBGRAPH*>& aSubgraphs );
|
|
|
|
|
2019-05-05 23:48:43 +00:00
|
|
|
/**
|
|
|
|
* Search for a matching bus member inside a bus connection
|
|
|
|
*
|
|
|
|
* For bus groups, this returns a bus member that matches aSearch by name.
|
|
|
|
* For bus vectors, this returns a bus member that matches by vector index.
|
|
|
|
*
|
|
|
|
* @param aBusConnection is the bus connection to search
|
|
|
|
* @param aSearch is the net connection to search for
|
|
|
|
* @returns a member of aBusConnection that matches aSearch
|
|
|
|
*/
|
|
|
|
static SCH_CONNECTION* matchBusMember( SCH_CONNECTION* aBusConnection,
|
|
|
|
SCH_CONNECTION* aSearch );
|
|
|
|
|
2020-02-05 14:23:55 +00:00
|
|
|
/**
|
|
|
|
* Builds a new default connection for the given item based on its properties.
|
|
|
|
* Handles strong drivers (power pins and labels) only
|
|
|
|
*
|
|
|
|
* @param aItem is an item that can generate a connection name
|
2020-07-09 22:14:27 +00:00
|
|
|
* @param aSubgraph is used to determine the sheet to use and retrieve the cached name
|
2020-02-05 14:23:55 +00:00
|
|
|
* @return a connection generated from the item, or nullptr if item is not valid
|
|
|
|
*/
|
2020-07-08 21:42:05 +00:00
|
|
|
std::shared_ptr<SCH_CONNECTION> getDefaultConnection( SCH_ITEM* aItem,
|
2020-07-09 22:14:27 +00:00
|
|
|
CONNECTION_SUBGRAPH* aSubgraph );
|
2020-02-05 14:23:55 +00:00
|
|
|
|
2019-05-05 23:48:43 +00:00
|
|
|
void recacheSubgraphName( CONNECTION_SUBGRAPH* aSubgraph, const wxString& aOldName );
|
|
|
|
|
2021-01-13 04:03:31 +00:00
|
|
|
/**
|
|
|
|
* If the subgraph has multiple drivers of equal priority that are graphically connected,
|
|
|
|
* ResolveDrivers() will have stored the second driver for use by this function, which actually
|
|
|
|
* creates the markers
|
|
|
|
* @param aSubgraph is the subgraph to examine
|
|
|
|
* @return true for no errors, false for errors
|
|
|
|
*/
|
|
|
|
bool ercCheckMultipleDrivers( const CONNECTION_SUBGRAPH* aSubgraph );
|
|
|
|
|
2022-08-14 11:03:18 +00:00
|
|
|
bool ercCheckNetclassConflicts( const std::vector<CONNECTION_SUBGRAPH*>& subgraphs );
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
/**
|
|
|
|
* Checks one subgraph for conflicting connections between net and bus labels
|
|
|
|
*
|
|
|
|
* For example, a net wire connected to a bus port/pin, or vice versa
|
|
|
|
*
|
|
|
|
* @param aSubgraph is the subgraph to examine
|
|
|
|
* @return true for no errors, false for errors
|
|
|
|
*/
|
2020-03-10 18:46:57 +00:00
|
|
|
bool ercCheckBusToNetConflicts( const CONNECTION_SUBGRAPH* aSubgraph );
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks one subgraph for conflicting connections between two bus items
|
|
|
|
*
|
|
|
|
* For example, a labeled bus wire connected to a hierarchical sheet pin
|
|
|
|
* where the labeled bus doesn't contain any of the same bus members as the
|
|
|
|
* sheet pin
|
|
|
|
*
|
|
|
|
* @param aSubgraph is the subgraph to examine
|
|
|
|
* @return true for no errors, false for errors
|
|
|
|
*/
|
2020-03-10 18:46:57 +00:00
|
|
|
bool ercCheckBusToBusConflicts( const CONNECTION_SUBGRAPH* aSubgraph );
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks one subgraph for conflicting bus entry to bus connections
|
|
|
|
*
|
|
|
|
* For example, a wire with label "A0" is connected to a bus labeled "D[8..0]"
|
|
|
|
*
|
|
|
|
* Will also check for mistakes related to bus group names, for example:
|
|
|
|
* A bus group named "USB{DP DM}" should have bus entry connections like
|
|
|
|
* "USB.DP" but someone might accidentally just enter "DP"
|
|
|
|
*
|
|
|
|
* @param aSubgraph is the subgraph to examine
|
|
|
|
* @return true for no errors, false for errors
|
|
|
|
*/
|
2020-03-10 18:46:57 +00:00
|
|
|
bool ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH* aSubgraph );
|
2019-03-11 21:32:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks one subgraph for proper presence or absence of no-connect symbols
|
|
|
|
*
|
|
|
|
* A pin with a no-connect symbol should not have any connections
|
|
|
|
* A pin without a no-connect symbol should have at least one connection
|
|
|
|
*
|
|
|
|
* @param aSubgraph is the subgraph to examine
|
|
|
|
* @return true for no errors, false for errors
|
|
|
|
*/
|
2020-03-10 18:46:57 +00:00
|
|
|
bool ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph );
|
2019-03-11 21:32:05 +00:00
|
|
|
|
2020-08-25 22:00:07 +00:00
|
|
|
/**
|
|
|
|
* Checks one subgraph for floating wires
|
|
|
|
*
|
|
|
|
* Will throw an error for any subgraph that consists of just wires with no driver
|
|
|
|
*
|
|
|
|
* @param aSubgraph is the subgraph to examine
|
|
|
|
* @return true for no errors, false for errors
|
|
|
|
*/
|
|
|
|
bool ercCheckFloatingWires( const CONNECTION_SUBGRAPH* aSubgraph );
|
|
|
|
|
2019-03-11 21:32:05 +00:00
|
|
|
/**
|
|
|
|
* Checks one subgraph for proper connection of labels
|
|
|
|
*
|
|
|
|
* Labels should be connected to something
|
|
|
|
*
|
|
|
|
* @param aSubgraph is the subgraph to examine
|
2019-04-25 19:10:19 +00:00
|
|
|
* @param aCheckGlobalLabels is true if global labels should be checked for loneliness
|
2019-03-11 21:32:05 +00:00
|
|
|
* @return true for no errors, false for errors
|
|
|
|
*/
|
2020-03-10 18:46:57 +00:00
|
|
|
bool ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph );
|
2019-04-12 01:22:19 +00:00
|
|
|
|
2020-08-26 01:52:52 +00:00
|
|
|
/**
|
|
|
|
* Checks that a hierarchical sheet has at least one matching label inside the sheet for each
|
|
|
|
* port on the parent sheet object
|
|
|
|
*
|
|
|
|
* @param aSubgraph is the subgraph to examine
|
|
|
|
* @return the number of errors found
|
|
|
|
*/
|
|
|
|
int ercCheckHierSheets();
|
|
|
|
|
2022-12-06 22:08:36 +00:00
|
|
|
/**
|
|
|
|
* Get the number of pins in a given subgraph
|
|
|
|
* @param aLocSubgraph Subgraph to search
|
|
|
|
* @return total number of pins in the subgraph
|
|
|
|
*/
|
|
|
|
size_t hasPins( const CONNECTION_SUBGRAPH* aLocSubgraph );
|
|
|
|
|
2021-03-25 14:07:16 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
// All the sheets in the schematic (as long as we don't have partial updates)
|
|
|
|
SCH_SHEET_LIST m_sheetList;
|
|
|
|
|
|
|
|
// All connectable items in the schematic
|
|
|
|
std::vector<SCH_ITEM*> m_items;
|
|
|
|
|
|
|
|
// The owner of all CONNECTION_SUBGRAPH objects
|
|
|
|
std::vector<CONNECTION_SUBGRAPH*> m_subgraphs;
|
|
|
|
|
|
|
|
// Cache of a subset of m_subgraphs
|
|
|
|
std::vector<CONNECTION_SUBGRAPH*> m_driver_subgraphs;
|
|
|
|
|
|
|
|
// Cache to lookup subgraphs in m_driver_subgraphs by sheet path
|
|
|
|
std::unordered_map<SCH_SHEET_PATH, std::vector<CONNECTION_SUBGRAPH*>> m_sheet_to_subgraphs_map;
|
|
|
|
|
|
|
|
std::vector<std::pair<SCH_SHEET_PATH, SCH_PIN*>> m_invisible_power_pins;
|
|
|
|
|
2022-08-03 09:10:23 +00:00
|
|
|
std::unordered_map<wxString, std::shared_ptr<BUS_ALIAS>> m_bus_alias_cache;
|
2021-03-25 14:07:16 +00:00
|
|
|
|
2022-08-03 09:10:23 +00:00
|
|
|
std::unordered_map<wxString, int> m_net_name_to_code_map;
|
2021-03-25 14:07:16 +00:00
|
|
|
|
2022-08-03 09:10:23 +00:00
|
|
|
std::unordered_map<wxString, int> m_bus_name_to_code_map;
|
2021-03-25 14:07:16 +00:00
|
|
|
|
2022-08-03 09:10:23 +00:00
|
|
|
std::unordered_map<wxString, std::vector<const CONNECTION_SUBGRAPH*>> m_global_label_cache;
|
2021-03-25 14:07:16 +00:00
|
|
|
|
|
|
|
std::map< std::pair<SCH_SHEET_PATH, wxString>,
|
|
|
|
std::vector<const CONNECTION_SUBGRAPH*> > m_local_label_cache;
|
|
|
|
|
|
|
|
std::unordered_map<wxString, std::vector<CONNECTION_SUBGRAPH*>> m_net_name_to_subgraphs_map;
|
|
|
|
|
2022-08-03 09:10:23 +00:00
|
|
|
std::unordered_map<SCH_ITEM*, CONNECTION_SUBGRAPH*> m_item_to_subgraph_map;
|
2021-03-25 14:07:16 +00:00
|
|
|
|
|
|
|
NET_MAP m_net_code_to_subgraphs_map;
|
|
|
|
|
|
|
|
int m_last_net_code;
|
|
|
|
|
|
|
|
int m_last_bus_code;
|
|
|
|
|
|
|
|
int m_last_subgraph_code;
|
|
|
|
|
|
|
|
SCHEMATIC* m_schematic; ///< The schematic this graph represents
|
2019-03-11 21:32:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|