/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2013 Wayne Stambaugh * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. * * 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, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /** * @file netlist_object.h * @brief Definition of the NETLIST_OBJECT class. */ #ifndef NETLIST_OBJECT_H #define NETLIST_OBJECT_H #include #include #include class NETLIST_OBJECT_LIST; class SCH_COMPONENT; /* Type of Net objects (wires, labels, pins...) */ enum class NETLIST_ITEM { ITEM_UNSPECIFIED, // only for not yet initialized instances SEGMENT, // connection by wire BUS, // connection by bus JUNCTION, // connection by junction: can connect to // or more crossing wires LABEL, // this is a local label GLOBLABEL, // this is a global label that connect all // others global label in whole hierarchy HIERLABEL, // element to indicate connection to a // higher-level sheet SHEETLABEL, // element to indicate connection to a // lower-level sheet. BUSLABELMEMBER, /* created when a bus label is found: * the bus label (like DATA[0..7] is * converted to n single labels like * DATA0, DATA1 ... * These objects are living only in the current * NETLIST_OBJECT_LIST, not in shematic. */ GLOBBUSLABELMEMBER, // see NET_BUSLABELMEMBER, used when a // global bus label is found HIERBUSLABELMEMBER, // see NET_BUSLABELMEMBER, used when a // hierarchical bus label is found SHEETBUSLABELMEMBER, // see NET_BUSLABELMEMBER, used when a // pin sheet label using bus notation // is found PINLABEL, /* created when a pin is POWER (IN or * OUT) with invisible attribute is found: * these pins are equivalent to a global * label and are automatically connected */ PIN, // this is an usual pin NOCONNECT // this is a no connect symbol }; /* Values for .m_FlagOfConnection member */ enum class NET_CONNECTION { UNCONNECTED = 0, /* Pin or Label not connected (error) */ NOCONNECT_SYMBOL_PRESENT, /* Pin not connected but have a NoConnect * symbol on it (no error) */ PAD_CONNECT /* Normal connection (no error) */ }; class NETLIST_OBJECT { public: NETLIST_ITEM m_Type; /* Type of item (see NETLIST_ITEM_T enum) */ EDA_ITEM* m_Comp; /* Pointer to the library item that * created this net object (the parent) */ SCH_ITEM* m_Link; /* For SCH_SHEET_PIN: * Pointer to the hierarchy sheet that * contains this SCH_SHEET_PIN * For Pins: pointer to the schematic component * that contains this pin */ int m_Flag; /* flag used in calculations */ SCH_SHEET_PATH m_SheetPath; // the sheet path which contains this item SCH_SHEET_PATH m_SheetPathInclude; // sheet path which contains the hierarchical label ELECTRICAL_PINTYPE m_ElectricalPinType; // Has meaning only for Pins: electrical type of the pin int m_BusNetCode; /* Used for BUS connections */ int m_Member; /* for labels type NET_BUSLABELMEMBER ( bus member * created from the BUS label ) member number. */ NET_CONNECTION m_ConnectionType; // Used to store the connection type wxString m_PinNum; // pin number wxString m_Label; // Label text (for labels) or Pin name (for pins) wxPoint m_Start; // Position of object or for segments: starting point wxPoint m_End; // For segments (wire and buses): ending point private: int m_netCode; /* net code for all items except BUS * labels because a BUS label has * as many net codes as bus members */ NETLIST_OBJECT* m_netNameCandidate; /* a pointer to a label connected to the net, * that can be used to give a name to the net * or a pin if there is no label in net * When no label, the pin is used to build * default net name. */ public: #if defined(DEBUG) void Show( std::ostream& out, int ndx ) const; #endif NETLIST_OBJECT(); NETLIST_OBJECT( NETLIST_OBJECT& aSource ); // Copy constructor ~NETLIST_OBJECT(); // Accessors: void SetNet( int aNetCode ) { m_netCode = aNetCode; } int GetNet() const { return m_netCode; } /** * Set the item connection type: * UNCONNECTED Pin or Label not connected (error) * NOCONNECT_SYMBOL_PRESENT Pin not connected but have a NoConnect * symbol on it (no error) * PAD_CONNECT Normal connection (no error) */ void SetConnectionType( NET_CONNECTION aFlg = NET_CONNECTION::UNCONNECTED ) { m_ConnectionType = aFlg; } NET_CONNECTION GetConnectionType() const { return m_ConnectionType; } /** * Set m_netNameCandidate to a connected item which will * be used to calcule the net name of the item * Obviously the candidate can be only a label * when there is no label on the net a pad which will * used to build a net name (something like Cmp_Pad * @param aCandidate = the connected item candidate */ void SetNetNameCandidate( NETLIST_OBJECT* aCandidate ); /** * @return true if an item has already a net name candidate * and false if not ( m_netNameCandidate == NULL ) */ bool HasNetNameCandidate() { return m_netNameCandidate != NULL; } /** * returns a pin number in wxString form. Pin numbers are not always * numbers. \"A23\" would be a valid pin number. */ const wxString& GetPinNumText() const { return m_PinNum; } /** * returns the pin name, for NET_PIN (usual pin) item. */ const wxString GetPinNameText() const; /** For Pins (NET_PINS): * @return the schematic component which contains this pin * (Note: this is the schematic component, not the library component * for others items: return NULL */ SCH_COMPONENT* GetComponentParent() const { if( m_Link && m_Link->Type() == SCH_COMPONENT_T ) return (SCH_COMPONENT*) m_Link; return NULL; } /** * Function IsLabelConnected * tests if the net list object is a hierarchical label or sheet label and is * connected to an associated hierarchical label or sheet label of \a aNetItem. * * @param aNetItem A pointer to a NETLIST_OBJECT to test against. * @return A bool value of true if there is a connection with \a aNetItem or false * if no connection to \a aNetItem. */ bool IsLabelConnected( NETLIST_OBJECT* aNetItem ); /** * Function IsLabelGlobal * @return true if the object is a global label * (i.e. an real global label or a pin label coming * from a power pin invisible */ bool IsLabelGlobal() const; /** * Function IsLabelBusMemberType * @return true if the object is a bus label member build from a * schematic bus label (like label[xx..yy], xx and yy are the first and last * bus member id) * bus label members have specific properties: * they do not live in schematic * they have specific properties in connections: * 2 bus label members can be connected connected only if they have the same member value. */ bool IsLabelBusMemberType() const; /** * Function IsLabelType * @return true if the object is a label of any type */ bool IsLabelType() const; /** * Function GetNetName * @return the full net name of the item, i.e. the net name from the "best" label, * prefixed by the sheet path */ wxString GetNetName() const; /** * Function GetShortNetName * @return the short net name of the item i.e. the net name from the "best" label * without any prefix. 2 different nets can have the same short name */ wxString GetShortNetName() const; /** * Function ConvertBusToNetListItems * breaks the text of a bus label type net list object into as many members as * it contains and creates a #NETLIST_OBJECT for each label and adds it to \a * aNetListItems. * * @param aNetListItems A reference to vector of #NETLIST_OBJECT pointers to add * the bus label NETLIST_OBJECTs. */ void ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItems ); private: /** * Given a bus vector, append the appropriate members into the list * If given something like "DATA", 7, 0, will append "DATA7", "DATA6", etc. * * @param aNetListItems is the list to append to * @param aName is the prefix for the vector, like "DATA" * @param aBegin is the first entry in the vector * @param aEnd is the last entry in the vector * @param aOffset is an offset to add to the member code for each member */ void fillBusVector( NETLIST_OBJECT_LIST& aNetListItems, wxString aName, long aBegin, long aEnd, long aOffset ); }; /** * Type NETLIST_OBJECTS * is a container referring to (not owning) NETLIST_OBJECTs, which are connected items * in a full schematic hierarchy. It is useful when referring to NETLIST_OBJECTs * actually owned by some other container. */ typedef std::vector NETLIST_OBJECTS; /** * NETLIST_OBJECT_LIST * is a container holding and _owning_ NETLIST_OBJECTs, which are connected items * in a full schematic hierarchy. It is helpful for netlist and ERC calculations. */ class NETLIST_OBJECT_LIST : public NETLIST_OBJECTS { int m_lastNetCode; // Used in intermediate calculation: last net code created int m_lastBusNetCode; // Used in intermediate calculation: // last net code created for bus members public: /** * Constructor. * NETLIST_OBJECT_LIST handle a list of connected items. * these NETLIST_OBJECT items are freeed by the destructor */ NETLIST_OBJECT_LIST() { // Do not leave some members uninitialized: m_lastNetCode = 0; m_lastBusNetCode = 0; } ~NETLIST_OBJECT_LIST(); /** * Function BuildNetListInfo * the master function of tgis class. * Build the list of connected objects (pins, labels ...) and * all info to generate netlists or run ERC diags * @param aSheets = the flattened sheet list * @return true if OK, false is not item found */ bool BuildNetListInfo( SCH_SHEET_LIST& aSheets ); /** * Acces to an item in list */ NETLIST_OBJECT* GetItem( unsigned aIdx ) const { return *( this->begin() + aIdx ); } /** * Acces to an item type */ NETLIST_ITEM GetItemType( unsigned aIdx ) const { return GetItem( aIdx )->m_Type; } /** * Acces to an item net code */ int GetItemNet( unsigned aIdx ) const { return GetItem( aIdx )->GetNet(); } NET_CONNECTION GetConnectionType( unsigned aIdx ) { return GetItem( aIdx )->GetConnectionType(); } /** * Set the item connection type: * UNCONNECTED Pin or Label not connected (error) * NOCONNECT_SYMBOL_PRESENT Pin not connected but have a NoConnect * symbol on it (no error) * PAD_CONNECT Normal connection (no error) */ void SetConnectionType( unsigned aIdx, NET_CONNECTION aFlg = NET_CONNECTION::UNCONNECTED ) { GetItem( aIdx )->SetConnectionType( aFlg ); } /** Delete all objects in list and clear list */ void Clear(); /** * Reset the connection type of all items to UNCONNECTED type */ void ResetConnectionsType() { for( unsigned ii = 0; ii < size(); ii++ ) GetItem( ii )->SetConnectionType( NET_CONNECTION::UNCONNECTED ); } /* * Sorts the list of connected items by net code */ void SortListbyNetcode(); /* * Sorts the list of connected items by sheet. * This sorting is used when searching "physical" connection between items * because obviously only items inside the same sheet can be connected */ void SortListbySheet(); /** * Counts number of pins connected on the same net. * Used to count all pins connected to a no connect symbol * @return the pin count of the net starting at aNetStart * @param aNetStart = index in list of net objects of the first item */ int CountPinsInNet( unsigned aNetStart ); /** * Function TestforNonOrphanLabel * Sheet labels are expected to be connected to a hierarchical label. * Hierarchical labels are expected to be connected to a sheet label. * Global labels are expected to be not orphan (connected to at least one * other global label. * This function tests the connection to another suitable label. */ void TestforNonOrphanLabel( unsigned aNetItemRef, unsigned aStartNet ); /** * Function TestforSimilarLabels * detects labels which are different when using case sensitive comparisons * but are equal when using case insensitive comparisons * It can be due to a mistake from designer, so this kind of labels * is reported by TestforSimilarLabels */ void TestforSimilarLabels(); #if defined(DEBUG) void DumpNetTable() { for( unsigned idx = 0; idx < size(); ++idx ) { GetItem( idx )->Show( std::cout, idx ); } } #endif private: /* * Propagate aNewNetCode to items having an internal netcode aOldNetCode * used to interconnect group of items already physically connected, * when a new connection is found between aOldNetCode and aNewNetCode */ void propagateNetCode( int aOldNetCode, int aNewNetCode, bool aIsBus ); /* * This function merges the net codes of groups of objects already connected * to labels (wires, bus, pins ... ) when 2 labels are equivalents * (i.e. group objects connected by labels) */ void labelConnect( NETLIST_OBJECT* aLabelRef ); /* Comparison function to sort by increasing Netcode the list of connected items */ static bool sortItemsbyNetcode( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 ) { return Objet1->GetNet() < Objet2->GetNet(); } /* Comparison routine to sort items by Sheet path */ static bool sortItemsBySheet( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 ) { return Objet1->m_SheetPath.Cmp( Objet2->m_SheetPath ) < 0; } /** * Propagate net codes from a parent sheet to an include sheet, * from a pin sheet connection */ void sheetLabelConnect( NETLIST_OBJECT* aSheetLabel ); void pointToPointConnect( NETLIST_OBJECT* aRef, bool aIsBus, int start ); /** * Search connections between a junction and segments * Propagate the junction net code to objects connected by this junction. * The junction must have a valid net code * The list of objects is expected sorted by sheets. * Search is done from index aIdxStart to the last element of list */ void segmentToPointConnect( NETLIST_OBJECT* aJonction, bool aIsBus, int aIdxStart ); /** * Function connectBusLabels * Propagate the net code (and create it, if not yet existing) between * all bus label member objects connected by they name. * Search is done in the entire list */ void connectBusLabels(); /** * Set the m_FlagOfConnection member of items in list * depending on the connection type: * UNCONNECTED, PAD_CONNECT or NOCONNECT_SYMBOL_PRESENT * The list is expected sorted by order of net code, * i.e. items having the same net code are grouped */ void setUnconnectedFlag(); /** * Function findBestNetNameForEachNet * fill the .m_NetNameCandidate member of each item of aNetItemBuffer * with a reference to the "best" NETLIST_OBJECT usable to give a name to the net * If no suitable object found, .m_NetNameCandidate is filled with 0. * The "best" NETLIST_OBJECT is a NETLIST_OBJECT that have the type label * and by priority order: * the label is global or local * the label is in the first sheet in a hierarchy (the root sheet has the most priority) * alphabetic order. */ void findBestNetNameForEachNet(); }; /** * Function IsBusLabel * test if \a aLabel has a bus notation. * * @param aLabel A wxString object containing the label to test. * @return true if text is a bus notation format otherwise false is returned. */ extern bool IsBusLabel( const wxString& aLabel ); #endif // NETLIST_OBJECT_H