KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_log_file.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 (C) 2020-2023 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
25// WARNING - this Tom's crappy PNS hack tool code. Please don't complain about its quality
26// (unless you want to improve it).
27
28#include "pns_log_file.h"
29
30#include <router/pns_segment.h>
31
33
36
37#include <project.h>
39
40#include <../../tests/common/console_log.h>
41
43{
44 BOARD_CONNECTED_ITEM* parent = nullptr;
45
46 for( BOARD_CONNECTED_ITEM* item : m_board->AllConnectedItems() )
47 {
48 if( item->m_Uuid == evt.uuid )
49 {
50 parent = item;
51 break;
52 };
53 }
54
55 return parent;
56}
57
58static const wxString readLine( FILE* f )
59{
60 char str[16384];
61 fgets( str, sizeof( str ) - 1, f );
62 return wxString( str );
63}
64
65
67 m_mode( PNS::ROUTER_MODE::PNS_MODE_ROUTE_SINGLE )
68{
69 m_routerSettings.reset( new PNS::ROUTING_SETTINGS( nullptr, "" ) );
70}
71
72std::shared_ptr<SHAPE> parseShape( SHAPE_TYPE expectedType, wxStringTokenizer& aTokens )
73{
74 SHAPE_TYPE type = static_cast<SHAPE_TYPE> ( wxAtoi( aTokens.GetNextToken() ) );
75
76 if( type == SHAPE_TYPE::SH_SEGMENT )
77 {
78 std::shared_ptr<SHAPE_SEGMENT> sh( new SHAPE_SEGMENT );
79 VECTOR2I a, b;
80 a.x = wxAtoi( aTokens.GetNextToken() );
81 a.y = wxAtoi( aTokens.GetNextToken() );
82 b.x = wxAtoi( aTokens.GetNextToken() );
83 b.y = wxAtoi( aTokens.GetNextToken() );
84 int width = wxAtoi( aTokens.GetNextToken() );
85 sh->SetSeg( SEG( a, b ));
86 sh->SetWidth( width );
87 return sh;
88 }
89 else if( type == SHAPE_TYPE::SH_CIRCLE )
90 {
91 std::shared_ptr<SHAPE_CIRCLE> sh( new SHAPE_CIRCLE );
92 VECTOR2I a;
93 a.x = wxAtoi( aTokens.GetNextToken() );
94 a.y = wxAtoi( aTokens.GetNextToken() );
95 int radius = wxAtoi( aTokens.GetNextToken() );
96 sh->SetCenter( a );
97 sh->SetRadius( radius );
98 return sh;
99 }
100
101 return nullptr;
102}
103
104bool PNS_LOG_FILE::parseCommonPnsProps( PNS::ITEM* aItem, const wxString& cmd,
105 wxStringTokenizer& aTokens )
106{
107 if( cmd == wxS( "net" ) )
108 {
109 aItem->SetNet( m_board->FindNet( wxAtoi( aTokens.GetNextToken() ) ) );
110 return true;
111 }
112 else if( cmd == wxS( "layers" ) )
113 {
114 int start = wxAtoi( aTokens.GetNextToken() );
115 int end = wxAtoi( aTokens.GetNextToken() );
116 aItem->SetLayers( LAYER_RANGE( start, end ) );
117 return true;
118 }
119 return false;
120}
121
123{
124 PNS::SEGMENT* seg = new PNS::SEGMENT();
125
126 while( aTokens.CountTokens() )
127 {
128 wxString cmd = aTokens.GetNextToken();
129
130 if( !parseCommonPnsProps( seg, cmd, aTokens ) )
131 {
132 if( cmd == wxS( "shape" ) )
133 {
134 std::shared_ptr<SHAPE> sh = parseShape( SH_SEGMENT, aTokens );
135
136 if( !sh )
137 return nullptr;
138
139 seg->SetShape( *static_cast<SHAPE_SEGMENT*>( sh.get() ) );
140
141 }
142 }
143 }
144
145 return seg;
146}
147
148PNS::VIA* PNS_LOG_FILE::parsePnsViaFromString( wxStringTokenizer& aTokens )
149{
150 PNS::VIA* via = new PNS::VIA();
151
152 while( aTokens.CountTokens() )
153 {
154 wxString cmd = aTokens.GetNextToken();
155
156 if( !parseCommonPnsProps( via, cmd, aTokens ) )
157 {
158 if( cmd == wxS( "shape" ) )
159 {
160 std::shared_ptr<SHAPE> sh = parseShape( SH_CIRCLE, aTokens );
161
162 if( !sh )
163 return nullptr;
164
165 SHAPE_CIRCLE* sc = static_cast<SHAPE_CIRCLE*>( sh.get() );
166
167 via->SetPos( sc->GetCenter() );
168 via->SetDiameter( 2 * sc->GetRadius() );
169 }
170 else if( cmd == wxS( "drill" ) )
171 {
172 via->SetDrill( wxAtoi( aTokens.GetNextToken() ) );
173 }
174 }
175 }
176
177 return via;
178}
179
180
181PNS::ITEM* PNS_LOG_FILE::parseItemFromString( wxStringTokenizer& aTokens )
182{
183 wxString type = aTokens.GetNextToken();
184
185 if( type == wxS( "segment" ) )
186 return parsePnsSegmentFromString( aTokens );
187 else if( type == wxS( "via" ) )
188 return parsePnsViaFromString( aTokens );
189
190 return nullptr;
191}
192
193bool comparePnsItems( const PNS::ITEM* a , const PNS::ITEM* b )
194{
195 if( a->Kind() != b->Kind() )
196 return false;
197
198 if( a->Net() != b->Net() )
199 return false;
200
201 if( a->Layers() != b->Layers() )
202 return false;
203
204 if( a->Kind() == PNS::ITEM::VIA_T )
205 {
206 const PNS::VIA* va = static_cast<const PNS::VIA*>(a);
207 const PNS::VIA* vb = static_cast<const PNS::VIA*>(b);
208
209 if( va->Diameter() != vb->Diameter() )
210 return false;
211
212 if( va->Drill() != vb->Drill() )
213 return false;
214
215 if( va->Pos() != vb->Pos() )
216 return false;
217
218 }
219 else if ( a->Kind() == PNS::ITEM::SEGMENT_T )
220 {
221 const PNS::SEGMENT* sa = static_cast<const PNS::SEGMENT*>(a);
222 const PNS::SEGMENT* sb = static_cast<const PNS::SEGMENT*>(b);
223
224 if( sa->Seg() != sb->Seg() )
225 return false;
226
227 if( sa->Width() != sb->Width() )
228 return false;
229 }
230
231 return true;
232}
233
234
235const std::set<PNS::ITEM*> deduplicate( const std::vector<PNS::ITEM*>& items )
236{
237 std::set<PNS::ITEM*> rv;
238
239 for( PNS::ITEM* item : items )
240 {
241 bool isDuplicate = false;
242
243 for( PNS::ITEM* ritem : rv )
244 {
245 if( comparePnsItems( ritem, item) )
246 {
247 isDuplicate = true;
248 break;
249 }
250
251 if( !isDuplicate )
252 rv.insert( item );
253 }
254 }
255
256 return rv;
257}
258
259
261{
262 COMMIT_STATE check( aOther );
263
264 //printf("pre-compare: %d/%d\n", check.m_addedItems.size(), check.m_removedIds.size() );
265 //printf("pre-compare (log): %d/%d\n", m_addedItems.size(), m_removedIds.size() );
266
267 for( const KIID& uuid : m_removedIds )
268 {
269 if( check.m_removedIds.find( uuid ) != check.m_removedIds.end() )
270 check.m_removedIds.erase( uuid );
271 else
272 return false; // removed twice? wtf
273 }
274
275 std::set<PNS::ITEM*> addedItems = deduplicate( m_addedItems );
276 std::set<PNS::ITEM*> chkAddedItems = deduplicate( check.m_addedItems );
277
278 for( PNS::ITEM* item : addedItems )
279 {
280 for( PNS::ITEM* chk : chkAddedItems )
281 {
282 if( comparePnsItems( item, chk ) )
283 {
284 chkAddedItems.erase( chk );
285 break;
286 }
287 }
288 }
289
290 //printf("post-compare: %d/%d\n", chkAddedItems.size(), check.m_removedIds.size() );
291
292 if( chkAddedItems.empty() && check.m_removedIds.empty() )
293 return true;
294 else
295 return false; // Set breakpoint here to trap failing tests
296}
297
298
299bool PNS_LOG_FILE::SaveLog( const wxFileName& logFileName, REPORTER* aRpt )
300{
301 std::vector<PNS::ITEM*> dummyHeads; // todo - save heads when we support it in QA
302
303 FILE* log_f = wxFopen( logFileName.GetFullPath(), "wb" );
305 m_commitState.m_removedIds, dummyHeads,
306 m_events );
307 fprintf( log_f, "%s\n", logString.c_str().AsChar() );
308 fclose( log_f );
309
310 return true;
311}
312
313
314bool PNS_LOG_FILE::Load( const wxFileName& logFileName, REPORTER* aRpt )
315{
316 wxFileName fname_log( logFileName );
317 fname_log.SetExt( wxT( "log" ) );
318
319 wxFileName fname_dump( logFileName );
320 fname_dump.SetExt( wxT( "dump" ) );
321
322 wxFileName fname_project( logFileName );
323 fname_project.SetExt( wxT( "kicad_pro" ) );
324 fname_project.MakeAbsolute();
325
326 wxFileName fname_settings( logFileName );
327 fname_settings.SetExt( wxT( "settings" ) );
328
329 aRpt->Report( wxString::Format( wxT( "Loading router settings from '%s'" ),
330 fname_settings.GetFullPath() ) );
331
332 bool ok = m_routerSettings->LoadFromRawFile( fname_settings.GetFullPath() );
333
334 if( !ok )
335 {
336 aRpt->Report( wxT( "Failed to load routing settings. Using defaults." ),
338 }
339
340 aRpt->Report( wxString::Format( wxT( "Loading project settings from '%s'" ),
341 fname_settings.GetFullPath() ) );
342
343 m_settingsMgr.reset( new SETTINGS_MANAGER ( true ) );
344 m_settingsMgr->LoadProject( fname_project.GetFullPath() );
345 PROJECT* project = m_settingsMgr->GetProject( fname_project.GetFullPath() );
346 project->SetReadOnly();
347
348 try
349 {
350 PCB_PLUGIN io;
351 aRpt->Report( wxString::Format( wxT("Loading board snapshot from '%s'"),
352 fname_dump.GetFullPath() ) );
353
354 m_board.reset( io.LoadBoard( fname_dump.GetFullPath(), nullptr, nullptr ) );
355 m_board->SetProject( project );
356
357 std::shared_ptr<DRC_ENGINE> drcEngine( new DRC_ENGINE );
358
359 CONSOLE_LOG consoleLog;
360 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
361
362 bds.m_DRCEngine = drcEngine;
363 bds.m_UseConnectedTrackWidth = project->GetLocalSettings().m_AutoTrackWidth;
364
365 m_board->SynchronizeNetsAndNetClasses( true );
366
367 drcEngine->SetBoard( m_board.get() );
368 drcEngine->SetDesignSettings( &bds );
369 drcEngine->SetLogReporter( new CONSOLE_MSG_REPORTER( &consoleLog ) );
370 drcEngine->InitEngine( wxFileName() );
371 }
372 catch( const PARSE_ERROR& parse_error )
373 {
374 aRpt->Report( wxString::Format( "parse error : %s (%s)\n",
375 parse_error.Problem(),
376 parse_error.What() ),
378
379 return false;
380 }
381
382 FILE* f = fopen( fname_log.GetFullPath().c_str(), "rb" );
383
384 aRpt->Report( wxString::Format( "Loading log from '%s'", fname_log.GetFullPath() ) );
385
386 if( !f )
387 {
388 aRpt->Report( wxT( "Failed to load log" ), RPT_SEVERITY_ERROR );
389 return false;
390 }
391
392 while( !feof( f ) )
393 {
394 wxString line = readLine( f );
395 wxStringTokenizer tokens( line );
396
397 if( !tokens.CountTokens() )
398 continue;
399
400 wxString cmd = tokens.GetNextToken();
401
402 if( cmd == wxT( "mode" ) )
403 {
404 m_mode = static_cast<PNS::ROUTER_MODE>( wxAtoi( tokens.GetNextToken() ) );
405 }
406 else if( cmd == wxT( "event" ) )
407 {
408 m_events.push_back( PNS::LOGGER::ParseEvent( line ) );
409 }
410 else if ( cmd == wxT( "added" ) )
411 {
412 PNS::ITEM* item = parseItemFromString( tokens );
413 m_commitState.m_addedItems.push_back( item );
414 }
415 else if ( cmd == wxT( "removed" ) )
416 {
417 m_commitState.m_removedIds.insert( KIID( tokens.GetNextToken() ) );
418 }
419 }
420
421 fclose( f );
422
423 return true;
424}
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
Design Rule Checker object that performs all the DRC tests.
Definition: drc_engine.h:83
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:46
Definition: kiid.h:49
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
A PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
Definition: pcb_plugin.h:271
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const STRING_UTF8_MAP *aProperties=nullptr, PROJECT *aProject=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr) override
Load information from some input file format that this PLUGIN implementation knows about into either ...
Base class for PNS router board items.
Definition: pns_item.h:97
void SetLayers(const LAYER_RANGE &aLayers)
Definition: pns_item.h:196
virtual NET_HANDLE Net() const
Definition: pns_item.h:193
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:166
void SetNet(NET_HANDLE aNet)
Definition: pns_item.h:192
@ SEGMENT_T
Definition: pns_item.h:105
const LAYER_RANGE & Layers() const
Definition: pns_item.h:195
static wxString FormatLogFileAsString(int aMode, const std::vector< ITEM * > &aAddedItems, const std::set< KIID > &aRemovedItems, const std::vector< ITEM * > &aHeads, const std::vector< EVENT_ENTRY > &aEvents)
Definition: pns_logger.cpp:67
static EVENT_ENTRY ParseEvent(const wxString &aLine)
Definition: pns_logger.cpp:103
Contain all persistent settings of the router, such as the mode, optimization effort,...
const SEG & Seg() const
Definition: pns_segment.h:84
void SetShape(const SHAPE_SEGMENT &aShape)
Definition: pns_segment.h:122
int Width() const override
Definition: pns_segment.h:79
const VECTOR2I & Pos() const
Definition: pns_via.h:128
int Diameter() const
Definition: pns_via.h:142
int Drill() const
Definition: pns_via.h:150
BOARD_CONNECTED_ITEM * ItemById(const PNS::LOGGER::EVENT_ENTRY &evt)
PNS::ITEM * parseItemFromString(wxStringTokenizer &aTokens)
bool Load(const wxFileName &logFileName, REPORTER *aRpt)
bool SaveLog(const wxFileName &logFileName, REPORTER *aRpt)
PNS::SEGMENT * parsePnsSegmentFromString(wxStringTokenizer &aTokens)
PNS::ROUTER_MODE m_mode
Definition: pns_log_file.h:106
std::shared_ptr< BOARD > m_board
Definition: pns_log_file.h:104
std::shared_ptr< SETTINGS_MANAGER > m_settingsMgr
Definition: pns_log_file.h:101
PNS::VIA * parsePnsViaFromString(wxStringTokenizer &aTokens)
bool parseCommonPnsProps(PNS::ITEM *aItem, const wxString &cmd, wxStringTokenizer &aTokens)
COMMIT_STATE m_commitState
Definition: pns_log_file.h:105
std::vector< PNS::LOGGER::EVENT_ENTRY > m_events
Definition: pns_log_file.h:103
std::unique_ptr< PNS::ROUTING_SETTINGS > m_routerSettings
Definition: pns_log_file.h:102
Container for project specific data.
Definition: project.h:62
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
Definition: seg.h:42
int GetRadius() const
Definition: shape_circle.h:108
const VECTOR2I GetCenter() const
Definition: shape_circle.h:113
Push and Shove diff pair dimensions (gap) settings dialog.
ROUTER_MODE
Definition: pns_router.h:62
std::shared_ptr< SHAPE > parseShape(SHAPE_TYPE expectedType, wxStringTokenizer &aTokens)
bool comparePnsItems(const PNS::ITEM *a, const PNS::ITEM *b)
static const wxString readLine(FILE *f)
const std::set< PNS::ITEM * > deduplicate(const std::vector< PNS::ITEM * > &items)
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
SHAPE_TYPE
Lists all supported shapes.
Definition: shape.h:46
@ SH_CIRCLE
circle
Definition: shape.h:50
@ SH_SEGMENT
line segment
Definition: shape.h:48
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:119
Definition: pns_logger.h:56
KIID uuid
Definition: pns_logger.h:59
std::set< KIID > m_removedIds
Definition: pns_log_file.h:66
bool Compare(const COMMIT_STATE &aOther)
std::vector< PNS::ITEM * > m_addedItems
Definition: pns_log_file.h:67