diff options
Diffstat (limited to 'pcbnew/router/pns_diff_pair.h')
-rw-r--r-- | pcbnew/router/pns_diff_pair.h | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/pcbnew/router/pns_diff_pair.h b/pcbnew/router/pns_diff_pair.h new file mode 100644 index 0000000..234ef89 --- /dev/null +++ b/pcbnew/router/pns_diff_pair.h @@ -0,0 +1,495 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2015 CERN + * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> + * + * 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 3 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 __PNS_DIFF_PAIR_H +#define __PNS_DIFF_PAIR_H + +#include <vector> + +#include <geometry/shape.h> +#include <geometry/shape_line_chain.h> + +#include "pns_line.h" +#include "pns_via.h" + +#include "ranged_num.h" + +class PNS_DIFF_PAIR; + +/** + * Class PNS_DP_GATEWAY + * + * Defines a "gateway" for routing a differential pair - e.g. a pair of points (anchors) with certain + * orientation, spacing and (optionally) predefined entry paths. The routing algorithm connects such + * gateways with parallel lines, thus creating a difrerential pair. + **/ +class PNS_DP_GATEWAY { +public: + PNS_DP_GATEWAY( const VECTOR2I& aAnchorP, + const VECTOR2I& aAnchorN, + bool aIsDiagonal, + int aAllowedEntryAngles = DIRECTION_45::ANG_OBTUSE, + int aPriority = 0 ) + : m_anchorP( aAnchorP ), + m_anchorN( aAnchorN ), + m_isDiagonal( aIsDiagonal ), + m_allowedEntryAngles( aAllowedEntryAngles ), + m_priority( aPriority ) + { + m_hasEntryLines = false; + } + + ~PNS_DP_GATEWAY() + { + } + + /** + * Function IsDiagonal() + * + * @return true, if the gateway anchors lie on a diagonal line + */ + bool IsDiagonal() const + { + return m_isDiagonal; + } + + const VECTOR2I& AnchorP() const { return m_anchorP; } + + const VECTOR2I& AnchorN() const { return m_anchorN; } + + /** + * Function AllowedAngles() + * + * @return a mask of 45-degree entry directoins allowed for the + * gateway. + */ + int AllowedAngles () const { return m_allowedEntryAngles; } + + /** + * Function Priority() + * + * @return priority/score value for gateway matching + */ + int Priority() const + { + return m_priority; + } + + void SetPriority(int aPriority) + { + m_priority = aPriority; + } + + void SetEntryLines( const SHAPE_LINE_CHAIN& aEntryP, const SHAPE_LINE_CHAIN& aEntryN ) + { + m_entryP = aEntryP; + m_entryN = aEntryN; + m_hasEntryLines = true; + } + + const SHAPE_LINE_CHAIN& EntryP() const { return m_entryP; } + const SHAPE_LINE_CHAIN& EntryN() const { return m_entryN; } + const PNS_DIFF_PAIR Entry() const ; + + void Reverse(); + + bool HasEntryLines () const + { + return m_hasEntryLines; + } + +private: + SHAPE_LINE_CHAIN m_entryP, m_entryN; + bool m_hasEntryLines; + VECTOR2I m_anchorP, m_anchorN; + bool m_isDiagonal; + int m_allowedEntryAngles; + int m_priority; +}; + +/** + * Class PNS_DP_PRIMITIVE_PAIR + * + * Stores staring/ending primitives (pads, vias or segments) for a differential pair. + **/ +class PNS_DP_PRIMITIVE_PAIR +{ +public: + PNS_DP_PRIMITIVE_PAIR(): + m_primP( NULL ), m_primN( NULL ) {}; + + PNS_DP_PRIMITIVE_PAIR( const PNS_DP_PRIMITIVE_PAIR& aOther ); + PNS_DP_PRIMITIVE_PAIR( PNS_ITEM* aPrimP, PNS_ITEM* aPrimN ); + PNS_DP_PRIMITIVE_PAIR( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN ); + + ~PNS_DP_PRIMITIVE_PAIR(); + + void SetAnchors( const VECTOR2I& aAnchorP, const VECTOR2I& aAnchorN ); + + const VECTOR2I& AnchorP() const { return m_anchorP; } + const VECTOR2I& AnchorN() const { return m_anchorN; } + + PNS_DP_PRIMITIVE_PAIR& operator=( const PNS_DP_PRIMITIVE_PAIR& aOther ); + + PNS_ITEM* PrimP() const { return m_primP; } + PNS_ITEM* PrimN() const { return m_primN; } + + bool Directional() const; + + DIRECTION_45 DirP() const; + DIRECTION_45 DirN() const; + +private: + DIRECTION_45 anchorDirection( PNS_ITEM* aItem, const VECTOR2I& aP ) const; + + PNS_ITEM* m_primP; + PNS_ITEM* m_primN; + VECTOR2I m_anchorP, m_anchorN; +}; + +/** + * Class PNS_GATEWAYS + * + * A set of gateways calculated for the cursor or starting/ending primitive pair. + **/ + +class PNS_DP_GATEWAYS +{ + + public: + PNS_DP_GATEWAYS ( int aGap ): + m_gap(aGap), m_viaGap( aGap ) + { + // Do not leave unitialized members, and keep static analyser quiet: + m_viaDiameter = 0; + m_fitVias = true; + } + + void SetGap ( int aGap ) + { + m_gap = aGap; + m_viaGap = aGap; + } + + void Clear() + { + m_gateways.clear(); + } + + void SetFitVias ( bool aEnable, int aDiameter = 0, int aViaGap = -1 ) + { + m_fitVias = aEnable; + m_viaDiameter = aDiameter; + if(aViaGap < 0) + m_viaGap = m_gap; + else + m_viaGap = aViaGap; + } + + + void BuildForCursor ( const VECTOR2I& aCursorPos ); + void BuildOrthoProjections ( PNS_DP_GATEWAYS &aEntries, const VECTOR2I& aCursorPos, int aOrthoScore ); + void BuildGeneric ( const VECTOR2I& p0_p, const VECTOR2I& p0_n, bool aBuildEntries = false, bool aViaMode = false ); + void BuildFromPrimitivePair( PNS_DP_PRIMITIVE_PAIR aPair, bool aPreferDiagonal ); + + bool FitGateways ( PNS_DP_GATEWAYS& aEntry, PNS_DP_GATEWAYS& aTarget, bool aPrefDiagonal, PNS_DIFF_PAIR& aDp ); + + std::vector<PNS_DP_GATEWAY>& Gateways() + { + return m_gateways; + } + + private: + + struct DP_CANDIDATE + { + SHAPE_LINE_CHAIN p, n; + VECTOR2I gw_p, gw_n; + int score; + }; + + bool checkDiagonalAlignment ( const VECTOR2I& a, const VECTOR2I& b) const; + void buildDpContinuation ( PNS_DP_PRIMITIVE_PAIR aPair, bool aIsDiagonal ); + void buildEntries ( const VECTOR2I& p0_p, const VECTOR2I& p0_n ); + + int m_gap; + int m_viaGap; + int m_viaDiameter; + bool m_fitVias; + + std::vector<PNS_DP_GATEWAY> m_gateways; +}; + + +/** + * Class PNS_DIFF_PAIR + * + * Basic class for a differential pair. Stores two PNS_LINEs (for positive and negative nets, respectively), + * the gap and coupling constraints. + **/ +class PNS_DIFF_PAIR : public PNS_ITEM { + +public: + struct COUPLED_SEGMENTS { + COUPLED_SEGMENTS ( const SEG& aCoupledP, const SEG& aParentP, int aIndexP, + const SEG& aCoupledN, const SEG& aParentN, int aIndexN ) : + coupledP ( aCoupledP ), + coupledN ( aCoupledN ), + parentP ( aParentP ), + parentN ( aParentN ), + indexP ( aIndexP ), + indexN ( aIndexN ) + {} + + SEG coupledP; + SEG coupledN; + SEG parentP; + SEG parentN; + int indexP; + int indexN; + }; + + typedef std::vector<COUPLED_SEGMENTS> COUPLED_SEGMENTS_VEC; + + PNS_DIFF_PAIR ( ) : PNS_ITEM ( DIFF_PAIR ), m_hasVias (false) + { + // Initialize some members, to avoid uninitialized variables. + m_net_p = 0; + m_net_n = 0;; + m_width = 0; + m_gap = 0; + m_viaGap = 0; + m_maxUncoupledLength = 0; + m_chamferLimit = 0; + } + + PNS_DIFF_PAIR ( int aGap ) : + PNS_ITEM ( DIFF_PAIR ), + m_hasVias (false) + { + m_gapConstraint = aGap; + + // Initialize other members, to avoid uninitialized variables. + m_net_p = 0; + m_net_n = 0;; + m_width = 0; + m_gap = 0; + m_viaGap = 0; + m_maxUncoupledLength = 0; + m_chamferLimit = 0; + } + + PNS_DIFF_PAIR ( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, int aGap = 0 ): + PNS_ITEM ( DIFF_PAIR ), + m_n (aN), + m_p (aP), + m_hasVias (false) + { + m_gapConstraint = aGap; + + // Initialize other members, to avoid uninitialized variables. + m_net_p = 0; + m_net_n = 0;; + m_width = 0; + m_gap = 0; + m_viaGap = 0; + m_maxUncoupledLength = 0; + m_chamferLimit = 0; + } + + PNS_DIFF_PAIR ( const PNS_LINE &aLineP, const PNS_LINE &aLineN, int aGap = 0 ): + PNS_ITEM ( DIFF_PAIR ), + m_line_p ( aLineP ), + m_line_n ( aLineN ), + m_hasVias (false) + { + m_gapConstraint = aGap; + m_net_p = aLineP.Net(); + m_net_n = aLineN.Net(); + m_p = aLineP.CLine(); + m_n = aLineN.CLine(); + + // Do not leave unitialized members, and keep static analyser quiet: + m_width = 0; + m_gap = 0; + m_viaGap = 0; + m_maxUncoupledLength = 0; + m_chamferLimit = 0; + } + + static inline bool ClassOf( const PNS_ITEM* aItem ) + { + return aItem && DIFF_PAIR == aItem->Kind(); + } + + PNS_DIFF_PAIR * Clone() const { assert(false); return NULL; } + + static PNS_DIFF_PAIR* AssembleDp ( PNS_LINE *aLine ); + + void SetShape ( const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN& aN, bool aSwapLanes = false) + { + if (aSwapLanes) + { + m_p = aN; + m_n = aP; + } else { + m_p = aP; + m_n = aN; + } + } + + void SetShape ( const PNS_DIFF_PAIR& aPair ) + { + m_p = aPair.m_p; + m_n = aPair.m_n; + } + + void SetNets ( int aP, int aN ) + { + m_net_p = aP; + m_net_n = aN; + } + + void SetWidth ( int aWidth ) + { + m_width = aWidth; + } + + int Width() const { return m_width; } + + void SetGap ( int aGap) + { + m_gap = aGap; + m_gapConstraint = RANGED_NUM<int> ( m_gap, 10000, 10000 ); + } + + int Gap() const { + return m_gap; + } + + void AppendVias ( const PNS_VIA &aViaP, const PNS_VIA& aViaN ) + { + m_hasVias = true; + m_via_p = aViaP; + m_via_n = aViaN; + } + + void RemoveVias () + { + m_hasVias = false; + } + + bool EndsWithVias() const + { + return m_hasVias; + } + + int NetP() const + { + return m_net_p; + } + + int NetN() const + { + return m_net_n; + } + + PNS_LINE& PLine() + { + if ( !m_line_p.IsLinked ( ) ) + updateLine(m_line_p, m_p, m_net_p, m_via_p ); + return m_line_p; + } + + PNS_LINE& NLine() + { + if ( !m_line_n.IsLinked ( ) ) + updateLine(m_line_n, m_n, m_net_n, m_via_n ); + return m_line_n; + } + + PNS_DP_PRIMITIVE_PAIR EndingPrimitives(); + + double CoupledLength() const; + double TotalLength() const; + double CoupledLengthFactor () const; + double Skew () const; + + void CoupledSegmentPairs ( COUPLED_SEGMENTS_VEC& aPairs ) const; + + void Clear() + { + m_n.Clear(); + m_p.Clear(); + } + + void Append (const PNS_DIFF_PAIR& aOther ) + { + m_n.Append ( aOther.m_n ); + m_p.Append ( aOther.m_p ); + } + + bool Empty() const + { + return (m_n.SegmentCount() == 0) || (m_p.SegmentCount() == 0); + } + const SHAPE_LINE_CHAIN& CP() const { return m_p; } + const SHAPE_LINE_CHAIN& CN() const { return m_n; } + + bool BuildInitial ( PNS_DP_GATEWAY& aEntry, PNS_DP_GATEWAY& aTarget, bool aPrefDiagonal ); + bool CheckConnectionAngle ( const PNS_DIFF_PAIR &aOther, int allowedAngles ) const; + int CoupledLength ( const SEG& aP, const SEG& aN ) const; + + int64_t CoupledLength ( const SHAPE_LINE_CHAIN& aP, const SHAPE_LINE_CHAIN& aN ) const; + + const RANGED_NUM<int> GapConstraint() const { + return m_gapConstraint; + } + +private: + + void updateLine( PNS_LINE &aLine, const SHAPE_LINE_CHAIN& aShape, int aNet, PNS_VIA& aVia ) + { + aLine.SetShape( aShape ); + aLine.SetWidth( m_width ); + aLine.SetNet(aNet); + aLine.SetLayer (Layers().Start()); + + if(m_hasVias) + aLine.AppendVia ( aVia ); + } + + SHAPE_LINE_CHAIN m_n, m_p; + PNS_LINE m_line_p, m_line_n; + PNS_VIA m_via_p, m_via_n; + + bool m_hasVias; + int m_net_p, m_net_n; + int m_width; + int m_gap; + int m_viaGap; + int m_maxUncoupledLength; + int m_chamferLimit; + RANGED_NUM<int> m_gapConstraint; +}; + + +#endif |