KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_meander_skew_placer.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2015 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
23
24#include <core/typeinfo.h>
26
27#include "pns_node.h"
28#include "pns_itemset.h"
29#include "pns_topology.h"
30#include "pns_solid.h"
31
32#include "pns_router.h"
33#include "pns_debug_decorator.h"
34
35namespace PNS {
36
38 MEANDER_PLACER ( aRouter )
39{
40 // Init temporary variables (do not leave uninitialized members)
47}
48
49
53
54
55bool MEANDER_SKEW_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
56{
57 if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T) )
58 {
59 Router()->SetFailureReason( _( "Please select a differential pair track you want to tune." ) );
60 return false;
61 }
62
63 m_initialSegment = static_cast<LINKED_ITEM*>( aStartItem );
64 m_currentNode = nullptr;
66
67 m_world = Router()->GetWorld( )->Branch();
68 m_originLine = m_world->AssembleLine( m_initialSegment );
69
70 TOPOLOGY topo( m_world );
71 m_tunedPath = topo.AssembleTrivialPath( m_initialSegment, nullptr, true );
72
74 {
75 Router()->SetFailureReason( _( "Unable to find complementary differential pair "
76 "net for skew tuning. Make sure the names of the nets belonging "
77 "to a differential pair end with either _N/_P or +/-." ) );
78 return false;
79 }
80
81 if( m_originPair.Gap() < 0 )
82 m_originPair.SetGap( Router()->Sizes().DiffPairGap() );
83
84 if( !m_originPair.PLine().SegmentCount() ||
85 !m_originPair.NLine().SegmentCount() )
86 return false;
87
88 m_tunedPathP = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.PLine().GetLink( 0 ), &m_startPad_p,
89 &m_endPad_p );
90
93
94 if( m_startPad_p )
95 {
96 m_padToDieLengthP += m_startPad_p->GetPadToDie();
97 m_padToDieDelayP += m_startPad_p->GetPadToDieDelay();
98 }
99
100 if( m_endPad_p )
101 {
102 m_padToDieLengthP += m_endPad_p->GetPadToDie();
103 m_padToDieDelayP += m_endPad_p->GetPadToDieDelay();
104 }
105
106 m_tunedPathN = topo.AssembleTuningPath( Router()->GetInterface(), m_originPair.NLine().GetLink( 0 ), &m_startPad_n,
107 &m_endPad_n );
108
111
112 if( m_startPad_n )
113 {
114 m_padToDieLengthN += m_startPad_n->GetPadToDie();
115 m_padToDieDelayN += m_startPad_n->GetPadToDieDelay();
116 }
117
118 if( m_endPad_n )
119 {
120 m_padToDieLengthN += m_endPad_n->GetPadToDie();
121 m_padToDieDelayN += m_endPad_n->GetPadToDieDelay();
122 }
123
124 m_world->Remove( m_originLine );
125
127 m_currentEnd = VECTOR2I( 0, 0 );
128
129 const BOARD_CONNECTED_ITEM* conItem = static_cast<BOARD_CONNECTED_ITEM*>( aStartItem->GetSourceItem() );
130 m_netClass = conItem->GetEffectiveNetClass();
131 m_settings.m_netClass = m_netClass;
132
133 if ( m_originPair.NetP() == m_originLine.Net() )
134 {
137
140
142 }
143 else
144 {
147
150
152 }
153
155
156 return true;
157}
158
159
167
168
176
177
179{
181}
182
183
184bool MEANDER_SKEW_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
185{
187
188 bool isPositive = m_originPair.NetP() == m_originLine.Net();
189
190 for( const ITEM* item : m_tunedPathP.CItems() )
191 {
192 if( const LINE* l = dyn_cast<const LINE*>( item ) )
193 {
194 PNS_DBG( Dbg(), AddItem, l, BLUE, 10000, wxT( "tuned-path-skew-p" ) );
195
196 m_router->GetInterface()->DisplayPathLine( l->CLine(), isPositive ? 1 : 0 );
197 }
198 }
199
200 for( const ITEM* item : m_tunedPathN.CItems() )
201 {
202 if( const LINE* l = dyn_cast<const LINE*>( item ) )
203 {
204 PNS_DBG( Dbg(), AddItem, l, YELLOW, 10000, wxT( "tuned-path-skew-n" ) );
205
206 m_router->GetInterface()->DisplayPathLine( l->CLine(), isPositive ? 0 : 1 );
207 }
208 }
209
210 return doMove( aP, aEndItem, m_coupledLength + m_settings.m_targetSkew.Opt(),
211 m_coupledLength + m_settings.m_targetSkew.Min(),
212 m_coupledLength + m_settings.m_targetSkew.Max() );
213}
214
215
217{
219}
220
221
226
227
229{
230 auto calculateTargetSkew = [this]( const int64_t targetSkewDelay )
231 {
232 const int64_t curSkewDelay = m_lastDelay - m_coupledDelay;
233 const int64_t skewDelayDifference = targetSkewDelay - curSkewDelay;
234
235 int64_t skewLengthDiff = m_router->GetInterface()->CalculateLengthForDelay(
236 std::abs( skewDelayDifference ), m_originPair.Width(), true, m_originPair.Gap(),
237 m_router->GetCurrentLayer(), m_netClass );
238
239 const int64_t curSkew = CurrentSkew();
240 skewLengthDiff = skewDelayDifference > 0 ? skewLengthDiff : -skewLengthDiff;
241
242 return static_cast<int>( curSkew + skewLengthDiff );
243 };
244
245 if( m_settings.m_isTimeDomain )
246 {
247 const int minSkew = calculateTargetSkew( m_settings.m_targetSkewDelay.Min() );
248 m_settings.m_targetSkew.SetMin( static_cast<int>( minSkew ) );
249
250 const int optSkew = calculateTargetSkew( m_settings.m_targetSkewDelay.Opt() );
251 m_settings.m_targetSkew.SetOpt( static_cast<int>( optSkew ) );
252
253 const int maxSkew = calculateTargetSkew( m_settings.m_targetSkewDelay.Max() );
254 m_settings.m_targetSkew.SetMax( static_cast<int>( maxSkew ) );
255 }
256}
257}
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
ROUTER * Router() const
Return current router settings.
ROUTER * m_router
DEBUG_DECORATOR * Dbg() const
Base class for PNS router board items.
Definition pns_item.h:98
BOARD_ITEM * GetSourceItem() const
Definition pns_item.h:202
bool OfKind(int aKindMask) const
Definition pns_item.h:181
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition pns_line.h:62
int m_currentWidth
Meander settings.
MEANDER_SETTINGS m_settings
The current end point.
int64_t lineDelay(const ITEM_SET &aLine, const SOLID *aStartPad, const SOLID *aEndPad) const
Calculate the total delay of the line represented by an item set (tracks and vias)
NODE * m_world
Width of the meandered trace(s).
VECTOR2I getSnappedStartPoint(LINKED_ITEM *aStartItem, VECTOR2I aStartPoint)
long long int lineLength(const ITEM_SET &aLine, const SOLID *aStartPad, const SOLID *aEndPad) const
Calculate the total length of the line represented by an item set (tracks and vias)
bool doMove(const VECTOR2I &aP, ITEM *aEndItem, long long int aTargetLength, long long int aTargetMin, long long int aTargetMax)
LINKED_ITEM * m_initialSegment
Total length added by pad to die size.
MEANDER_PLACER(ROUTER *aRouter)
VECTOR2I m_currentStart
Current world state.
int64_t origPathDelay() const override
long long int origPathLength() const override
bool Move(const VECTOR2I &aP, ITEM *aEndItem) override
Function Move()
bool Start(const VECTOR2I &aP, ITEM *aStartItem) override
Function Start()
long long int TuningLengthResult() const override
Return the resultant length or skew of the tuned traces.
void calculateTimeDomainTargets() override
current routing start point (end of tail, beginning of head)
int64_t TuningDelayResult() const override
Return the resultant delay or skew of the tuned traces.
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition pns_node.cpp:157
void SetFailureReason(const wxString &aReason)
Definition pns_router.h:231
NODE * GetWorld() const
Definition pns_router.h:182
const DIFF_PAIR AssembleDiffPair(SEGMENT *aStart)
const ITEM_SET AssembleTuningPath(ROUTER_IFACE *aRouterIface, ITEM *aStart, SOLID **aStartPad=nullptr, SOLID **aEndPad=nullptr)
Like AssembleTrivialPath, but follows the track length algorithm, which discards segments that are fu...
const ITEM_SET AssembleTrivialPath(ITEM *aStart, std::pair< const JOINT *, const JOINT * > *aTerminalJoints=nullptr, bool aFollowLockedSegments=false)
Assemble a trivial path between two joints given a starting item.
@ BLUE
Definition color4d.h:56
@ YELLOW
Definition color4d.h:67
#define _(s)
Push and Shove diff pair dimensions (gap) settings dialog.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
#define PNS_DBG(dbg, method,...)
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
Definition typeinfo.h:61
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695