KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_log_player.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <core/profile.h>
25
27#include "pns_log_file.h"
28#include "pns_log_player.h"
29
31
32#define PNSLOGINFO PNS::DEBUG_DECORATOR::SRC_LOCATION_INFO( __FILE__, __FUNCTION__, __LINE__ )
33
34using namespace PNS;
35
40
41
45
47{
50 m_router.reset( new ROUTER );
51 m_iface->SetBoard( m_board.get() );
52 m_router->SetInterface( m_iface.get() );
53 m_router->ClearWorld();
54 m_router->SyncWorld();
55
56 m_routingSettings.reset( new PNS::ROUTING_SETTINGS( nullptr, "" ) );
57 m_router->LoadSettings( m_routingSettings.get() );
58 m_router->Settings().SetMode( PNS::RM_Walkaround );
59 m_router->Sizes().SetTrackWidth( 250000 );
60
62 m_debugDecorator->Clear();
63 m_iface->SetDebugDecorator( m_debugDecorator );
64}
65
66
68{
70 std::vector<PNS::ITEM*> added, removed, heads;
71 m_router->GetUpdatedItems( removed, added, heads );
72
73 //printf("a %d r %d\n", added.size(), removed.size() );
74 for( auto item : removed )
75 {
76 if( item->Parent() )
77 {
78 state.m_removedIds.insert( item->Parent()->m_Uuid );
79 }
80 }
81
82 for( auto item : added )
83 {
84 state.m_addedItems.push_back( item );
85 }
86
87 // fixme: update the state with the head trace (not supported in current testsuite)
88 // Note: we own the head items (cloned inside GetUpdatedItems) - we need to delete them!
89 for( auto head : heads )
90 delete head;
91
92 return state;
93}
94
95void PNS_LOG_PLAYER::ReplayLog( PNS_LOG_FILE* aLog, int aStartEventIndex, int aFrom, int aTo,
96 bool aUpdateExpectedResult )
97{
98 m_board = aLog->GetBoard();
99
100 createRouter();
101
102 m_router->LoadSettings( aLog->GetRoutingSettings() );
103
104 int eventIdx = 0;
105 int totalEvents = aLog->Events().size();
106
107 m_router->SetMode( aLog->GetMode() );
108
109 for( auto evt : aLog->Events() )
110 {
111 if( eventIdx < aFrom || ( aTo >= 0 && eventIdx > aTo ) )
112 continue;
113
114 auto items = aLog->ItemsById( evt );
115 PNS::ITEM_SET ritems;
116
117 ITEM* ritem = nullptr;
118
119 if( items.size() && items[0] )
120 ritem = m_router->GetWorld()->FindItemByParent( items[0] );
121
122 int routingLayer = ritem ? ritem->Layers().Start() : evt.layer;
123
124 for( BOARD_CONNECTED_ITEM* item : items )
125 {
126 if( ITEM* routerItem = m_router->GetWorld()->FindItemByParent( item ) )
127 ritems.Add( routerItem );
128 }
129
130 eventIdx++;
131
132 switch( evt.type )
133 {
135 {
136 wxString msg;
137 PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
138 m_iface->SetStartLayerFromPNS( routingLayer );
139 m_iface->ImportSizes( sizes, ritem, nullptr, evt.p );
140 m_router->UpdateSizes( sizes );
141
142 m_debugDecorator->NewStage( "route-start", 0, PNSLOGINFO );
143 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
144
145 PROF_TIMER tmr("route-start");
146 bool status = m_router->StartRouting( evt.p, ritem, routingLayer );
147 tmr.Stop();
148 double msecs = tmr.msecs();
149
150 msg = wxString::Format( "event [%d/%d]: route-start (%d, %d), layer %d, startitem %p status %d time %.0f ms", eventIdx,
151 totalEvents, evt.p.x, evt.p.y, routingLayer, ritem, status ? 1 : 0, msecs);
152
153 m_debugDecorator->Message( msg );
154 m_reporter->Report( msg );
155
156 break;
157 }
158
161 {
162 PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
163 m_iface->SetStartLayerFromPNS( routingLayer );
164 m_iface->ImportSizes( sizes, ritem, nullptr, evt.p );
165 m_router->UpdateSizes( sizes );
166
167 m_debugDecorator->NewStage( "drag-start", 0, PNSLOGINFO );
168 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
169
170
171
172 PROF_TIMER tmr("drag-start");
173 bool rv = m_router->StartDragging( evt.p, ritems, 0 );
174 tmr.Stop();
175 double msecs = tmr.msecs();
176
177
178
179 auto msg = wxString::Format( "event [%d/%d]: drag-start (%d, %d) time %.0f ms", eventIdx,
180 totalEvents, evt.p.x, evt.p.y, msecs );
181
182 m_debugDecorator->Message( msg );
183 m_reporter->Report( msg );
184
185 break;
186 }
187
188 case LOGGER::EVT_FIX:
189 {
190 m_debugDecorator->NewStage( "fix", 0, PNSLOGINFO );
191 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
192 m_debugDecorator->Message( wxString::Format( "fix (%d, %d)", evt.p.x, evt.p.y ) );
193 bool rv = m_router->FixRoute( evt.p, ritem, false, false );
194 printf( " fix -> (%d, %d) ret %d\n", evt.p.x, evt.p.y, rv ? 1 : 0 );
195 break;
196 }
197
199 {
200 m_debugDecorator->NewStage( "unfix", 0, PNSLOGINFO );
201 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
202 m_debugDecorator->Message( wxString::Format( "unfix (%d, %d)", evt.p.x, evt.p.y ) );
203 printf( " unfix\n" );
204 m_router->UndoLastSegment();
205 break;
206 }
207
208 case LOGGER::EVT_MOVE:
209 {
210 m_debugDecorator->NewStage( "move", 0, PNSLOGINFO );
211 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
212
213
214 PROF_TIMER tmr("drag-start");
215 bool ret = m_router->Move( evt.p, ritem );
216 tmr.Stop();
217 double msecs = tmr.msecs();
218
219 auto msg = wxString::Format( "event [%d/%d]: move (%d, %d) time %.0f ms", eventIdx, totalEvents, evt.p.x, evt.p.y, msecs );
220
221 m_debugDecorator->Message( msg );
222 m_reporter->Report( msg );
223 m_debugDecorator->SetCurrentStageStatus( ret );
224 break;
225 }
226
228 {
229 m_debugDecorator->NewStage( "toggle-via", 0, PNSLOGINFO );
230
231 auto msg = wxString::Format( "event [%d/%d]: toggle-via", eventIdx, totalEvents );
232
233 m_debugDecorator->Message( msg );
234 m_reporter->Report( msg );
235
236 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
237 m_router->ToggleViaPlacement();
238 break;
239 }
240
241 default: break;
242 }
243
244 PNS::NODE* node = nullptr;
245
246#if 0
247 if( m_router->GetState() == PNS::ROUTER::ROUTE_TRACK )
248 {
249 m_debugDecorator->BeginGroup( "current route", 0 );
250
251 auto traces = m_router->Placer()->Traces();
252
253 for( const auto& t : traces.CItems() )
254 {
255 const LINE *l = static_cast<LINE*>(t.item);
256 const auto& sh = l->CLine();
257
258 m_debugDecorator->AddItem( l, YELLOW, 0, wxT( "line seg" ) );
259 }
260
261 m_debugDecorator->EndGroup( PNSLOGINFO );
262
263 node = m_router->Placer()->CurrentNode( true );
264 }
265 else if( m_router->GetState() == PNS::ROUTER::DRAG_SEGMENT )
266 {
267 node = m_router->GetDragger()->CurrentNode();
268 }
269 if( !node )
270 return;
271
272 NODE::ITEM_VECTOR removed, added;
273
274 node->GetUpdatedItems( removed, added );
275
276 if( ! added.empty() )
277 {
278 bool first = true;
279 m_debugDecorator->BeginGroup( wxT( "node-added-items" ), 0 );
280
281 for( auto t : added )
282 {
283 m_debugDecorator->AddItem( t, MAGENTA, 0, wxT( "seg" ) );
284 }
285
286 m_debugDecorator->EndGroup();
287 }
288#endif
289 }
290
291 wxASSERT_MSG( m_router->Mode() == aLog->GetMode(), "didn't set the router mode correctly?" );
292
293 if( aUpdateExpectedResult )
294 {
295 std::vector<PNS::ITEM*> added, removed, heads;
296 m_router->GetUpdatedItems( removed, added, heads );
297
298 std::set<KIID> removedKIIDs;
299
300 for( auto item : removed )
301 {
302 // fixme: should we check for that?
303 // wxASSERT_MSG( item->Parent() != nullptr, "removed an item with no parent uuid?" );
304
305 if( item->Parent() )
306 removedKIIDs.insert( item->Parent()->m_Uuid );
307 }
308
309 std::vector<std::unique_ptr<PNS::ITEM>> myOwnedItems;
310 PNS_LOG_FILE::COMMIT_STATE routerCommitState;
311 routerCommitState.m_addedItems = added;
312 routerCommitState.m_removedIds = removedKIIDs;
313 routerCommitState.m_heads = heads;
314
315 for( PNS::ITEM* head : heads )
316 myOwnedItems.emplace_back( head );
317
318 aLog->SetExpectedResult( routerCommitState, std::move( myOwnedItems ) );
319
320 int test = 0;
321 }
322}
323
324
326{
327 auto cstate = GetRouterUpdatedItems();
328 return cstate.Compare( aLog->GetExpectedResult() );
329}
330
331
336
340
342{
343 //printf("DBG hide %p\n", aItem);
344 m_viewTracker->HideItem( aItem );
345}
346
347void PNS_LOG_PLAYER_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit,
348 int aFlags )
349{
350 //printf("DBG disp %p\n", aItem);
351 m_viewTracker->DisplayItem( aItem );
352}
353
354
356{
357 if( aNet )
358 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
359 else
360 return -1;
361}
362
363
365{
366 if( aNet )
367 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
368 else
369 return wxEmptyString;
370}
371
372
376
380
382{
383 m_currentStage = aStage;
385}
386
388{
389 ENTRY ent;
390 ent.m_isHideOp = true;
391 ent.m_item = aItem;
392 ent.m_ownedItem = nullptr; // I don't own it!
393 m_vitems[m_currentStage].push_back( std::move( ent ) );
394}
395
397{
398 ENTRY ent;
399 ent.m_isHideOp = false;
400 ent.m_item = aItem->Clone();
401 ent.m_ownedItem.reset( ent.m_item ); //delete me when ENTRY is deleted
402 m_vitems[m_currentStage].push_back( std::move( ent ) );
403 //printf("DBG disp cur %d cnt %d\n", m_currentStage, m_vitems[m_currentStage].size() );
404}
405
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Handle the data for a net.
Definition netinfo.h:50
static REPORTER & GetInstance()
Definition reporter.cpp:97
void Add(const LINE &aLine)
Base class for PNS router board items.
Definition pns_item.h:98
const PNS_LAYER_RANGE & Layers() const
Definition pns_item.h:212
virtual ITEM * Clone() const =0
Return a deep copy of the item.
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition pns_line.h:62
const SHAPE_LINE_CHAIN & CLine() const
Definition pns_line.h:142
@ EVT_START_MULTIDRAG
Definition pns_logger.h:68
Keep the router "world" - i.e.
Definition pns_node.h:240
std::vector< ITEM * > ITEM_VECTOR
Definition pns_node.h:251
void GetUpdatedItems(ITEM_VECTOR &aRemoved, ITEM_VECTOR &aAdded)
Return the list of items removed and added in this branch with respect to the root branch.
Contain all persistent settings of the router, such as the mode, optimization effort,...
int Start() const
void SetExpectedResult(const COMMIT_STATE &aCommitState, std::vector< std::unique_ptr< PNS::ITEM > > aParsedItems)
const COMMIT_STATE & GetExpectedResult() const
PNS::ROUTING_SETTINGS * GetRoutingSettings() const
PNS::ROUTER_MODE GetMode() const
std::vector< PNS::LOGGER::EVENT_ENTRY > & Events()
std::shared_ptr< BOARD > GetBoard() const
std::vector< BOARD_CONNECTED_ITEM * > ItemsById(const PNS::LOGGER::EVENT_ENTRY &evt)
int GetNetCode(PNS::NET_HANDLE aNet) const override
PNS_LOG_PLAYER_KICAD_IFACE(PNS_LOG_VIEW_TRACKER *aViewTracker)
PNS_LOG_VIEW_TRACKER * m_viewTracker
void HideItem(PNS::ITEM *aItem) override
void DisplayItem(const PNS::ITEM *aItem, int aClearance, bool aEdit=false, int aFlags=0) override
wxString GetNetName(PNS::NET_HANDLE aNet) const override
PNS_TEST_DEBUG_DECORATOR * m_debugDecorator
std::unique_ptr< PNS::ROUTING_SETTINGS > m_routingSettings
std::shared_ptr< BOARD > m_board
const PNS_LOG_FILE::COMMIT_STATE GetRouterUpdatedItems()
REPORTER * m_reporter
bool CompareResults(PNS_LOG_FILE *aLog)
std::unique_ptr< PNS::ROUTER > m_router
void ReplayLog(PNS_LOG_FILE *aLog, int aStartEventIndex=0, int aFrom=0, int aTo=-1, bool aUpdateExpectedResult=false)
std::shared_ptr< PNS_LOG_VIEW_TRACKER > m_viewTracker
std::unique_ptr< PNS_LOG_PLAYER_KICAD_IFACE > m_iface
void SetReporter(REPORTER *aReporter)
std::map< int, VIEW_ENTRIES > m_vitems
void DisplayItem(const PNS::ITEM *aItem)
void HideItem(PNS::ITEM *aItem)
std::vector< ENTRY > VIEW_ENTRIES
void SetStage(int aStage)
A small class to help profiling.
Definition profile.h:49
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition profile.h:88
double msecs(bool aSinceLast=false)
Definition profile.h:149
@ MAGENTA
Definition color4d.h:60
@ YELLOW
Definition color4d.h:67
Push and Shove diff pair dimensions (gap) settings dialog.
@ RM_Walkaround
Only walk around.
void * NET_HANDLE
Definition pns_item.h:55
#define PNSLOGINFO
std::set< KIID > m_removedIds
std::vector< PNS::ITEM * > m_addedItems
std::vector< PNS::ITEM * > m_heads
std::unique_ptr< const PNS::ITEM > m_ownedItem