summaryrefslogtreecommitdiff
path: root/pcbnew/router/pns_diff_pair.h
diff options
context:
space:
mode:
Diffstat (limited to 'pcbnew/router/pns_diff_pair.h')
-rw-r--r--pcbnew/router/pns_diff_pair.h495
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