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, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <core/profile.h>
21
23
25#include "pns_log_file.h"
26#include "pns_log_player.h"
27
29
30#define PNSLOGINFO PNS::DEBUG_DECORATOR::SRC_LOCATION_INFO( __FILE__, __FUNCTION__, __LINE__ )
31
32using namespace PNS;
33
38
39
43
44
46{
49 m_router.reset( new ROUTER );
50 m_iface->SetBoard( m_board.get() );
51 m_router->SetInterface( m_iface.get() );
52 m_router->ClearWorld();
53 m_router->SyncWorld();
54
55 m_routingSettings.reset( new PNS::ROUTING_SETTINGS( nullptr, "" ) );
56 m_router->LoadSettings( m_routingSettings.get() );
57 m_router->Settings().SetMode( PNS::RM_Walkaround );
58 m_router->Sizes().SetTrackWidth( 250000 );
59
61 m_debugDecorator->Clear();
62 m_iface->SetDebugDecorator( m_debugDecorator );
63}
64
65
67{
69 std::vector<PNS::ITEM*> added, removed, heads;
70 m_router->GetUpdatedItems( removed, added, heads );
71
72 //printf("a %d r %d\n", added.size(), removed.size() );
73 for( auto item : removed )
74 {
75 if( item->Parent() )
76 {
77 state.m_removedIds.insert( item->Parent()->m_Uuid );
78 }
79 }
80
81 for( auto item : added )
82 {
83 state.m_addedItems.push_back( item );
84 }
85
86 // fixme: update the state with the head trace (not supported in current testsuite)
87 // Note: we own the head items (cloned inside GetUpdatedItems) - we need to delete them!
88 for( auto head : heads )
89 {
90 state.m_heads.push_back( head );
91 }
92
93 return state;
94}
95
96void PNS_LOG_PLAYER::ReplayLog( PNS_LOG_FILE* aLog, int aStartEventIndex, int aFrom, int aTo,
97 bool aUpdateExpectedResult )
98{
99 m_board = aLog->GetBoard();
100
101 CreateRouter();
102
103 m_router->LoadSettings( aLog->GetRoutingSettings() );
104
105 int eventIdx = 0;
106 int totalEvents = aLog->Events().size();
107
108 m_router->SetMode( aLog->GetMode() );
109
110 for( auto evt : aLog->Events() )
111 {
112 if( eventIdx < aFrom || ( aTo >= 0 && eventIdx > aTo ) )
113 continue;
114
115 auto items = aLog->ItemsById( evt );
116 PNS::ITEM_SET ritems;
117
118 ITEM* ritem = nullptr;
119
120 if( items.size() && items[0] )
121 ritem = m_router->GetWorld()->FindItemByParent( items[0] );
122
123 int routingLayer = evt.layer;
124
125 if( ritem )
126 {
127 if( routingLayer < ritem->Layers().Start() )
128 routingLayer = ritem->Layers().Start();
129 if( routingLayer > ritem->Layers().End() )
130 routingLayer = ritem->Layers().End();
131 }
132
133 for( BOARD_CONNECTED_ITEM* item : items )
134 {
135 if( ITEM* routerItem = m_router->GetWorld()->FindItemByParent( item ) )
136 ritems.Add( routerItem );
137 }
138
139 eventIdx++;
140
141 switch( evt.type )
142 {
144 {
145 wxString msg;
146 PNS::SIZES_SETTINGS sizes( evt.sizes );
147 m_board->GetDesignSettings().m_UseConnectedTrackWidth = evt.useConnectedTrackWidth;
148 m_iface->SetStartLayerFromPNS( routingLayer );
149 m_iface->ImportSizes( sizes, ritem, nullptr, evt.p );
150 m_router->UpdateSizes( sizes );
151
152 m_debugDecorator->NewStage( "route-start", 0, PNSLOGINFO );
153 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
154
155 PROF_TIMER tmr("route-start");
156 bool status = m_router->StartRouting( evt.p, ritem, routingLayer );
157 tmr.Stop();
158 double msecs = tmr.msecs();
159
160 msg = wxString::Format( "event [%d/%d]: route-start (%d, %d), layer %d, startitem %p status %d time %.0f ms", eventIdx,
161 totalEvents, evt.p.x, evt.p.y, routingLayer, ritem, status ? 1 : 0, msecs);
162
163 m_debugDecorator->Message( msg );
164 m_reporter->Report( msg );
165
166 break;
167 }
168
171 {
172 PNS::SIZES_SETTINGS sizes( evt.sizes );
173 m_iface->SetStartLayerFromPNS( routingLayer );
174 m_iface->ImportSizes( sizes, ritem, nullptr, evt.p );
175 m_router->UpdateSizes( sizes );
176
177 m_debugDecorator->NewStage( "drag-start", 0, PNSLOGINFO );
178 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
179
180
181
182 PROF_TIMER tmr("drag-start");
183 bool rv = m_router->StartDragging( evt.p, ritems, 0 );
184 tmr.Stop();
185 double msecs = tmr.msecs();
186
187
188
189 auto msg = wxString::Format( "event [%d/%d]: drag-start (%d, %d) time %.0f ms", eventIdx,
190 totalEvents, evt.p.x, evt.p.y, msecs );
191
192 m_debugDecorator->Message( msg );
193 m_reporter->Report( msg );
194
195 break;
196 }
197
198 case LOGGER::EVT_FIX:
199 {
200 m_debugDecorator->NewStage( "fix", 0, PNSLOGINFO );
201 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
202 bool rv = m_router->FixRoute( evt.p, ritem, false, false );
203 m_debugDecorator->Message( wxString::Format( "fix -> (%d, %d) ret %d",
204 evt.p.x, evt.p.y, rv ? 1 : 0 ) );
205 break;
206 }
207
209 {
210 m_debugDecorator->NewStage( "unfix", 0, PNSLOGINFO );
211 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
212 m_debugDecorator->Message( wxString::Format( "unfix (%d, %d)", evt.p.x, evt.p.y ) );
213 m_router->UndoLastSegment();
214 break;
215 }
216
217 case LOGGER::EVT_MOVE:
218 {
219 m_debugDecorator->NewStage( "move", 0, PNSLOGINFO );
220 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
221
222
223 PROF_TIMER tmr("drag-start");
224 bool ret = m_router->Move( evt.p, ritem );
225 tmr.Stop();
226 double msecs = tmr.msecs();
227
228 auto msg = wxString::Format( "event [%d/%d]: move (%d, %d) time %.0f ms", eventIdx, totalEvents, evt.p.x, evt.p.y, msecs );
229
230 m_debugDecorator->Message( msg );
231 m_reporter->Report( msg );
232 m_debugDecorator->SetCurrentStageStatus( ret );
233 break;
234 }
235
237 {
238 m_debugDecorator->NewStage( "toggle-via", 0, PNSLOGINFO );
239
240 auto msg = wxString::Format( "event [%d/%d]: toggle-via", eventIdx, totalEvents );
241
242 m_debugDecorator->Message( msg );
243 m_reporter->Report( msg );
244
245 m_viewTracker->SetStage( m_debugDecorator->GetStageCount() - 1 );
246 m_router->ToggleViaPlacement();
247 break;
248 }
249
250 default: break;
251 }
252
253 PNS::NODE* node = nullptr;
254
255#if 0
256 if( m_router->GetState() == PNS::ROUTER::ROUTE_TRACK )
257 {
258 m_debugDecorator->BeginGroup( "current route", 0 );
259
260 auto traces = m_router->Placer()->Traces();
261
262 for( const auto& t : traces.CItems() )
263 {
264 const LINE *l = static_cast<LINE*>(t.item);
265 const auto& sh = l->CLine();
266
267 m_debugDecorator->AddItem( l, YELLOW, 0, wxT( "line seg" ) );
268 }
269
270 m_debugDecorator->EndGroup( PNSLOGINFO );
271
272 node = m_router->Placer()->CurrentNode( true );
273 }
274 else if( m_router->GetState() == PNS::ROUTER::DRAG_SEGMENT )
275 {
276 node = m_router->GetDragger()->CurrentNode();
277 }
278 if( !node )
279 return;
280
281 NODE::ITEM_VECTOR removed, added;
282
283 node->GetUpdatedItems( removed, added );
284
285 if( ! added.empty() )
286 {
287 bool first = true;
288 m_debugDecorator->BeginGroup( wxT( "node-added-items" ), 0 );
289
290 for( auto t : added )
291 {
292 m_debugDecorator->AddItem( t, MAGENTA, 0, wxT( "seg" ) );
293 }
294
295 m_debugDecorator->EndGroup();
296 }
297#endif
298 }
299
300 wxASSERT_MSG( m_router->Mode() == aLog->GetMode(), "didn't set the router mode correctly?" );
301
302 if( aUpdateExpectedResult )
303 {
304 std::vector<PNS::ITEM*> added, removed, heads;
305 m_router->GetUpdatedItems( removed, added, heads );
306
307 std::set<KIID> removedKIIDs;
308
309 for( auto item : removed )
310 {
311 // fixme: should we check for that?
312 // wxASSERT_MSG( item->Parent() != nullptr, "removed an item with no parent uuid?" );
313
314 if( item->Parent() )
315 removedKIIDs.insert( item->Parent()->m_Uuid );
316 }
317
318 std::vector<std::unique_ptr<PNS::ITEM>> myOwnedItems;
319 PNS_LOG_FILE::COMMIT_STATE routerCommitState;
320 routerCommitState.m_addedItems = added;
321 routerCommitState.m_removedIds = removedKIIDs;
322 routerCommitState.m_heads = heads;
323
324 for( PNS::ITEM* head : heads )
325 myOwnedItems.emplace_back( head );
326
327 aLog->SetExpectedResult( routerCommitState, std::move( myOwnedItems ) );
328
329 int test = 0;
330 }
331}
332
333
334bool PNS_LOG_PLAYER::CompareResults( PNS_LOG_FILE* aLog, bool aSkipHeads )
335{
336 auto cstate = GetRouterUpdatedItems();
337 return cstate.Compare( aLog->GetExpectedResult(), aSkipHeads );
338}
339
340
345
349
351{
352 //printf("DBG hide %p\n", aItem);
353 m_viewTracker->HideItem( aItem );
354}
355
356void PNS_LOG_PLAYER_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit,
357 int aFlags )
358{
359 //printf("DBG disp %p\n", aItem);
360 m_viewTracker->DisplayItem( aItem );
361}
362
363
365{
366 if( aNet )
367 return static_cast<NETINFO_ITEM*>( aNet )->GetNetCode();
368 else
369 return -1;
370}
371
372
374{
375 if( aNet )
376 return static_cast<NETINFO_ITEM*>( aNet )->GetNetname();
377 else
378 return wxEmptyString;
379}
380
381
385
389
391{
392 m_currentStage = aStage;
394}
395
397{
398 ENTRY ent;
399 ent.m_isHideOp = true;
400 ent.m_item = aItem;
401 ent.m_ownedItem = nullptr; // I don't own it!
402 m_vitems[m_currentStage].push_back( std::move( ent ) );
403}
404
406{
407 ENTRY ent;
408 ent.m_isHideOp = false;
409 ent.m_item = aItem->Clone();
410 ent.m_ownedItem.reset( ent.m_item ); //delete me when ENTRY is deleted
411 m_vitems[m_currentStage].push_back( std::move( ent ) );
412 //printf("DBG disp cur %d cnt %d\n", m_currentStage, m_vitems[m_currentStage].size() );
413}
414
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:207
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:146
@ EVT_START_MULTIDRAG
Definition pns_logger.h:68
Keep the router "world" - i.e.
Definition pns_node.h:243
std::vector< ITEM * > ITEM_VECTOR
Definition pns_node.h:254
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
int End() 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
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
bool CompareResults(PNS_LOG_FILE *aLog, bool aSkipHeads=false)
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:46
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition profile.h:86
double msecs(bool aSinceLast=false)
Definition profile.h:147
@ MAGENTA
Definition color4d.h:56
@ YELLOW
Definition color4d.h:63
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