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 printf("items: %zu\n", items.size() );
118 ITEM* ritem = nullptr;
119
120 if( items.size() && items[0] )
121 ritem = m_router->GetWorld()->FindItemByParent( items[0] );
122
123 int routingLayer = ritem ? ritem->Layers().Start() : evt.layer;
124
125 for( BOARD_CONNECTED_ITEM* item : items )
126 {
127 if( ITEM* routerItem = m_router->GetWorld()->FindItemByParent( item ) )
128 ritems.Add( routerItem );
129 }
130
131 eventIdx++;
132
133 switch( evt.type )
134 {
136 {
137 wxString msg;
138 PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
139 m_iface->SetStartLayerFromPNS( routingLayer );
140 m_iface->ImportSizes( sizes, ritem, nullptr, evt.p );
141 m_router->UpdateSizes( sizes );
142
143 m_debugDecorator->NewStage( "route-start", 0, PNSLOGINFO );
144 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
145
146 PROF_TIMER tmr("route-start");
147 bool status = m_router->StartRouting( evt.p, ritem, routingLayer );
148 tmr.Stop();
149 double msecs = tmr.msecs();
150
151 msg = wxString::Format( "event [%d/%d]: route-start (%d, %d), layer %d, startitem %p status %d time %.0f ms", eventIdx,
152 totalEvents, evt.p.x, evt.p.y, routingLayer, ritem, status ? 1 : 0, msecs);
153
154 m_debugDecorator->Message( msg );
155 m_reporter->Report( msg );
156
157 break;
158 }
159
162 {
163 PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
164 m_iface->SetStartLayerFromPNS( routingLayer );
165 m_iface->ImportSizes( sizes, ritem, nullptr, evt.p );
166 m_router->UpdateSizes( sizes );
167
168 m_debugDecorator->NewStage( "drag-start", 0, PNSLOGINFO );
169 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
170
171
172
173 PROF_TIMER tmr("drag-start");
174 bool rv = m_router->StartDragging( evt.p, ritems, 0 );
175 tmr.Stop();
176 double msecs = tmr.msecs();
177
178
179
180 auto msg = wxString::Format( "event [%d/%d]: drag-start (%d, %d) time %.0f ms", eventIdx,
181 totalEvents, evt.p.x, evt.p.y, msecs );
182
183 m_debugDecorator->Message( msg );
184 m_reporter->Report( msg );
185
186 break;
187 }
188
189 case LOGGER::EVT_FIX:
190 {
191 m_debugDecorator->NewStage( "fix", 0, PNSLOGINFO );
192 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
193 m_debugDecorator->Message( wxString::Format( "fix (%d, %d)", evt.p.x, evt.p.y ) );
194 bool rv = m_router->FixRoute( evt.p, ritem, false, false );
195 printf( " fix -> (%d, %d) ret %d\n", evt.p.x, evt.p.y, rv ? 1 : 0 );
196 break;
197 }
198
200 {
201 m_debugDecorator->NewStage( "unfix", 0, PNSLOGINFO );
202 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
203 m_debugDecorator->Message( wxString::Format( "unfix (%d, %d)", evt.p.x, evt.p.y ) );
204 printf( " unfix\n" );
205 m_router->UndoLastSegment();
206 break;
207 }
208
209 case LOGGER::EVT_MOVE:
210 {
211 m_debugDecorator->NewStage( "move", 0, PNSLOGINFO );
212 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
213
214
215 PROF_TIMER tmr("drag-start");
216 bool ret = m_router->Move( evt.p, ritem );
217 tmr.Stop();
218 double msecs = tmr.msecs();
219
220 auto msg = wxString::Format( "event [%d/%d]: move (%d, %d) time %.0f ms", eventIdx, totalEvents, evt.p.x, evt.p.y, msecs );
221
222 m_debugDecorator->Message( msg );
223 m_reporter->Report( msg );
224 m_debugDecorator->SetCurrentStageStatus( ret );
225 break;
226 }
227
229 {
230 m_debugDecorator->NewStage( "toggle-via", 0, PNSLOGINFO );
231
232 auto msg = wxString::Format( "event [%d/%d]: toggle-via", eventIdx, totalEvents );
233
234 m_debugDecorator->Message( msg );
235 m_reporter->Report( msg );
236
237 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
238 m_router->ToggleViaPlacement();
239 break;
240 }
241
242 default: break;
243 }
244
245 PNS::NODE* node = nullptr;
246
247#if 0
248 if( m_router->GetState() == PNS::ROUTER::ROUTE_TRACK )
249 {
250 m_debugDecorator->BeginGroup( "current route", 0 );
251
252 auto traces = m_router->Placer()->Traces();
253
254 for( const auto& t : traces.CItems() )
255 {
256 const LINE *l = static_cast<LINE*>(t.item);
257 const auto& sh = l->CLine();
258
259 m_debugDecorator->AddItem( l, YELLOW, 0, wxT( "line seg" ) );
260 }
261
262 m_debugDecorator->EndGroup( PNSLOGINFO );
263
264 node = m_router->Placer()->CurrentNode( true );
265 }
266 else if( m_router->GetState() == PNS::ROUTER::DRAG_SEGMENT )
267 {
268 node = m_router->GetDragger()->CurrentNode();
269 }
270 if( !node )
271 return;
272
273 NODE::ITEM_VECTOR removed, added;
274
275 node->GetUpdatedItems( removed, added );
276
277 if( ! added.empty() )
278 {
279 bool first = true;
280 m_debugDecorator->BeginGroup( wxT( "node-added-items" ), 0 );
281
282 for( auto t : added )
283 {
284 m_debugDecorator->AddItem( t, MAGENTA, 0, wxT( "seg" ) );
285 }
286
287 m_debugDecorator->EndGroup();
288 }
289#endif
290 }
291
292 wxASSERT_MSG( m_router->Mode() == aLog->GetMode(), "didn't set the router mode correctly?" );
293
294 if( aUpdateExpectedResult )
295 {
296 std::vector<PNS::ITEM*> added, removed, heads;
297 m_router->GetUpdatedItems( removed, added, heads );
298
299 std::set<KIID> removedKIIDs;
300
301 for( auto item : removed )
302 {
303 // fixme: should we check for that?
304 // wxASSERT_MSG( item->Parent() != nullptr, "removed an item with no parent uuid?" );
305
306 if( item->Parent() )
307 removedKIIDs.insert( item->Parent()->m_Uuid );
308 }
309
310 std::vector<std::unique_ptr<PNS::ITEM>> myOwnedItems;
311 PNS_LOG_FILE::COMMIT_STATE routerCommitState;
312 routerCommitState.m_addedItems = added;
313 routerCommitState.m_removedIds = removedKIIDs;
314 routerCommitState.m_heads = heads;
315
316 for( PNS::ITEM* head : heads )
317 myOwnedItems.emplace_back( head );
318
319 aLog->SetExpectedResult( routerCommitState, std::move( myOwnedItems ) );
320
321 int test = 0;
322 }
323}
324
325
327{
328 auto cstate = GetRouterUpdatedItems();
329
330 printf("Comparing %zu added/%zu removed items\n", cstate.m_addedItems.size(), cstate.m_removedIds.size() );
331 return cstate.Compare( aLog->GetExpectedResult() );
332}
333
334
339
343
345{
346 //printf("DBG hide %p\n", aItem);
347 m_viewTracker->HideItem( aItem );
348}
349
350void PNS_LOG_PLAYER_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit,
351 int aFlags )
352{
353 //printf("DBG disp %p\n", aItem);
354 m_viewTracker->DisplayItem( aItem );
355}
356
357
359{
360 if( aNet )
361 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
362 else
363 return -1;
364}
365
366
368{
369 if( aNet )
370 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
371 else
372 return wxEmptyString;
373}
374
375
379
383
385{
386 m_currentStage = aStage;
388}
389
391{
392 ENTRY ent;
393 ent.m_isHideOp = true;
394 ent.m_item = aItem;
395 ent.m_ownedItem = nullptr; // I don't own it!
396 m_vitems[m_currentStage].push_back( std::move( ent ) );
397}
398
400{
401 ENTRY ent;
402 ent.m_isHideOp = false;
403 ent.m_item = aItem->Clone();
404 ent.m_ownedItem.reset( ent.m_item ); //delete me when ENTRY is deleted
405 m_vitems[m_currentStage].push_back( std::move( ent ) );
406 //printf("DBG disp cur %d cnt %d\n", m_currentStage, m_vitems[m_currentStage].size() );
407}
408
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:54
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:54
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