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-2022 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 <../../tests/common/console_log.h>
38
40{
41 BOARD_CONNECTED_ITEM* parent = nullptr;
42
43 for( auto item : m_board->AllConnectedItems() )
44 {
45 if( item->m_Uuid == evt.uuid )
46 {
47 parent = item;
48 break;
49 };
50 }
51
52 return parent;
53}
54
55static const wxString readLine( FILE* f )
56{
57 char str[16384];
58 fgets( str, sizeof( str ) - 1, f );
59 return wxString( str );
60}
61
62
64 m_mode( PNS::ROUTER_MODE::PNS_MODE_ROUTE_SINGLE )
65{
66 m_routerSettings.reset( new PNS::ROUTING_SETTINGS( nullptr, "" ) );
67}
68
69static std::shared_ptr<SHAPE> parseShape( SHAPE_TYPE expectedType, wxStringTokenizer& aTokens )
70{
71 SHAPE_TYPE type = static_cast<SHAPE_TYPE> ( wxAtoi( aTokens.GetNextToken() ) );
72
73 if( type == SHAPE_TYPE::SH_SEGMENT )
74 {
75 std::shared_ptr<SHAPE_SEGMENT> sh( new SHAPE_SEGMENT );
76 VECTOR2I a,b;
77 a.x = wxAtoi( aTokens.GetNextToken() );
78 a.y = wxAtoi( aTokens.GetNextToken() );
79 b.x = wxAtoi( aTokens.GetNextToken() );
80 b.y = wxAtoi( aTokens.GetNextToken() );
81 int width = wxAtoi( aTokens.GetNextToken() );
82 sh->SetSeg( SEG( a, b ));
83 sh->SetWidth( width );
84 return sh;
85 }
86 else if ( type == SHAPE_TYPE::SH_CIRCLE )
87 {
88
89 std::shared_ptr<SHAPE_CIRCLE> sh( new SHAPE_CIRCLE );
90 VECTOR2I a;
91 a.x = wxAtoi( aTokens.GetNextToken() );
92 a.y = wxAtoi( aTokens.GetNextToken() );
93 int radius = wxAtoi( aTokens.GetNextToken() );
94 sh->SetCenter( a );
95 sh->SetRadius( radius );
96 return sh;
97 }
98
99 return nullptr;
100}
101
102bool parseCommonPnsProps( PNS::ITEM* aItem, const wxString& cmd, wxStringTokenizer& aTokens )
103{
104 if( cmd == "net" )
105 {
106 aItem->SetNet( wxAtoi( aTokens.GetNextToken() ) );
107 return true;
108 } else if ( cmd == "layers" )
109 {
110 int start = wxAtoi( aTokens.GetNextToken() );
111 int end = wxAtoi( aTokens.GetNextToken() );
112 aItem->SetLayers( LAYER_RANGE( start, end ));
113 return true;
114 }
115 return false;
116
117}
118
119static PNS::SEGMENT* parsePnsSegmentFromString( PNS::SEGMENT* aSeg, wxStringTokenizer& aTokens )
120{
121 PNS::SEGMENT* seg = new ( PNS::SEGMENT );
122
123 while( aTokens.CountTokens() )
124 {
125 wxString cmd = aTokens.GetNextToken();
126 if( !parseCommonPnsProps( seg, cmd, aTokens ) )
127 {
128 if ( cmd == "shape" )
129 {
130 auto sh = parseShape( SH_SEGMENT, aTokens );
131
132 if(!sh)
133 return nullptr;
134
135 seg->SetShape( *static_cast<SHAPE_SEGMENT*>(sh.get()) );
136
137 }
138 }
139 }
140
141 return seg;
142}
143
144static PNS::VIA* parsePnsViaFromString( PNS::VIA* aSeg, wxStringTokenizer& aTokens )
145{
146 PNS::VIA* via = new ( PNS::VIA );
147
148 while( aTokens.CountTokens() )
149 {
150 wxString cmd = aTokens.GetNextToken();
151 if( !parseCommonPnsProps( via, cmd, aTokens ) )
152 {
153 if ( cmd == "shape" )
154 {
155 auto sh = parseShape( SH_CIRCLE, aTokens );
156
157 if(!sh)
158 return nullptr;
159
160 auto *sc = static_cast<SHAPE_CIRCLE*>( sh.get() );
161
162 via->SetPos( sc->GetCenter() );
163 via->SetDiameter( 2 * sc->GetRadius() );
164 }
165 else if ( cmd == "drill" )
166 {
167 via->SetDrill( wxAtoi( aTokens.GetNextToken() ) );
168 }
169 }
170 }
171
172 return via;
173}
174
175
176static PNS::ITEM* parseItemFromString( wxStringTokenizer& aTokens )
177{
178 wxString type = aTokens.GetNextToken();
179
180 if( type == "segment" )
181 {
182 auto seg = new PNS::SEGMENT();
183 return parsePnsSegmentFromString( seg, aTokens );
184 }
185 else if( type == "via" )
186 {
187 auto seg = new PNS::VIA();
188 return parsePnsViaFromString( seg, aTokens );
189 }
190
191 return nullptr;
192}
193
194bool comparePnsItems( const PNS::ITEM*a , const PNS::ITEM* b )
195{
196 if( a->Kind() != b->Kind() )
197 return false;
198
199 if( a->Net() != b->Net() )
200 return false;
201
202 if( a->Layers() != b->Layers() )
203 return false;
204
205 if( a->Kind() == PNS::ITEM::VIA_T )
206 {
207 auto va = static_cast<const PNS::VIA*>(a);
208 auto vb = static_cast<const PNS::VIA*>(b);
209
210 if( va->Diameter() != vb->Diameter() )
211 return false;
212
213 if( va->Drill() != vb->Drill() )
214 return false;
215
216 if( va->Pos() != vb->Pos() )
217 return false;
218
219 }
220 else if ( a->Kind() == PNS::ITEM::SEGMENT_T )
221 {
222 auto sa = static_cast<const PNS::SEGMENT*>(a);
223 auto sb = static_cast<const PNS::SEGMENT*>(b);
224
225 if( sa->Seg() != sb->Seg() )
226 return false;
227
228 if( sa->Width() != sb->Width() )
229 return false;
230 }
231
232 return true;
233}
234
235
236const std::set<PNS::ITEM*> deduplicate( const std::set<PNS::ITEM*>& items )
237{
238 std::set<PNS::ITEM*> rv;
239
240 for( auto item : items )
241 {
242 bool isDuplicate = false;
243 for (auto 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( auto uuid : m_removedIds )
268 {
269 if( check.m_removedIds.find( uuid ) != check.m_removedIds.end() )
270 {
271 check.m_removedIds.erase( uuid );
272 }
273 else
274 {
275 return false; // removed twice? wtf
276 }
277 }
278
279 auto addedItems = deduplicate( m_addedItems );
280 auto chkAddedItems = deduplicate( check.m_addedItems );
281
282 for( auto item : addedItems )
283 {
284 for( auto chk : chkAddedItems )
285 {
286 if( comparePnsItems( item, chk ) )
287 {
288 chkAddedItems.erase( chk );
289 break;
290 }
291 }
292 }
293
294 //printf("post-compare: %d/%d\n", chkAddedItems.size(), check.m_removedIds.size() );
295
296 return chkAddedItems.empty() && check.m_removedIds.empty();
297}
298
299
300bool PNS_LOG_FILE::Load( const wxFileName& logFileName, REPORTER* aRpt )
301{
302 wxFileName fname_log( logFileName );
303 fname_log.SetExt( wxT( "log" ) );
304
305 wxFileName fname_dump( logFileName );
306 fname_dump.SetExt( wxT( "dump" ) );
307
308 wxFileName fname_project( logFileName );
309 fname_project.SetExt( wxT( "kicad_pro" ) );
310 fname_project.MakeAbsolute();
311
312 wxFileName fname_settings( logFileName );
313 fname_settings.SetExt( wxT( "settings" ) );
314
315
316 FILE* f = fopen( fname_log.GetFullPath().c_str(), "rb" );
317
318 aRpt->Report( wxString::Format( "Loading log from '%s'", fname_log.GetFullPath() ) );
319
320 if( !f )
321 return false;
322
323 while( !feof( f ) )
324 {
325 wxStringTokenizer tokens( readLine( f ) );
326
327 if( !tokens.CountTokens() )
328 continue;
329
330 wxString cmd = tokens.GetNextToken();
331
332 if( cmd == wxT("mode") )
333 {
334 m_mode = static_cast<PNS::ROUTER_MODE>( wxAtoi( tokens.GetNextToken() ) );
335 }
336 else if( cmd == wxT("event") )
337 {
338 EVENT_ENTRY evt;
339 evt.p.x = wxAtoi( tokens.GetNextToken() );
340 evt.p.y = wxAtoi( tokens.GetNextToken() );
341 evt.type = (PNS::LOGGER::EVENT_TYPE) wxAtoi( tokens.GetNextToken() );
342 evt.uuid = KIID( tokens.GetNextToken() );
343 m_events.push_back( evt );
344 }
345 else if ( cmd == wxT("added") )
346 {
347 auto item = parseItemFromString( tokens );
348 m_commitState.m_addedItems.insert( item );
349 }
350 else if ( cmd == wxT("removed") )
351 {
352 m_commitState.m_removedIds.insert( KIID( tokens.GetNextToken() ) );
353 }
354 }
355
356 fclose( f );
357
358 aRpt->Report( wxString::Format( wxT("Loading router settings from '%s'"), fname_settings.GetFullPath() ) );
359
360 bool ok = m_routerSettings->LoadFromRawFile( fname_settings.GetFullPath() );
361
362 if( !ok )
363 {
364 aRpt->Report( wxString::Format( wxT("Failed to load routing settings. Usign defaults.")) , RPT_SEVERITY_WARNING );
365 }
366
367 aRpt->Report( wxString::Format( wxT("Loading project settings from '%s'"), fname_settings.GetFullPath() ) );
368
369 m_settingsMgr.reset( new SETTINGS_MANAGER ( true ) );
370 m_settingsMgr->LoadProject( fname_project.GetFullPath() );
371
372 try
373 {
374 PCB_PLUGIN io;
375 aRpt->Report( wxString::Format( wxT("Loading board snapshot from '%s'"), fname_dump.GetFullPath() ) );
376
377 m_board.reset( io.Load( fname_dump.GetFullPath(), nullptr, nullptr ) );
378 m_board->SetProject( m_settingsMgr->GetProject( fname_project.GetFullPath() ) );
379
380 std::shared_ptr<DRC_ENGINE> drcEngine( new DRC_ENGINE );
381
382 CONSOLE_LOG consoleLog;
383 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
384
385 bds.m_DRCEngine = drcEngine;
386
387 m_board->SynchronizeNetsAndNetClasses( true );
388
389 drcEngine->SetBoard( m_board.get() );
390 drcEngine->SetDesignSettings( &bds );
391 drcEngine->SetLogReporter( new CONSOLE_MSG_REPORTER( &consoleLog ) );
392 drcEngine->InitEngine( wxFileName() );
393 }
394 catch( const PARSE_ERROR& parse_error )
395 {
396 aRpt->Report( wxString::Format( "parse error : %s (%s)\n", parse_error.Problem(),
397 parse_error.What() ), RPT_SEVERITY_ERROR );
398
399 return false;
400 }
401
402 return true;
403}
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:48
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:261
BOARD * Load(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:91
void SetLayers(const LAYER_RANGE &aLayers)
Definition: pns_item.h:192
void SetNet(int aNet)
Definition: pns_item.h:188
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:162
virtual int Net() const
Definition: pns_item.h:189
@ SEGMENT_T
Definition: pns_item.h:101
const LAYER_RANGE & Layers() const
Definition: pns_item.h:191
Contain all persistent settings of the router, such as the mode, optimization effort,...
void SetShape(const SHAPE_SEGMENT &aShape)
Definition: pns_segment.h:122
bool Load(const wxFileName &logFileName, REPORTER *aRpt)
PNS::ROUTER_MODE m_mode
Definition: pns_log_file.h:102
std::shared_ptr< BOARD > m_board
Definition: pns_log_file.h:100
std::shared_ptr< SETTINGS_MANAGER > m_settingsMgr
Definition: pns_log_file.h:97
BOARD_CONNECTED_ITEM * ItemById(const EVENT_ENTRY &evt)
COMMIT_STATE m_commitState
Definition: pns_log_file.h:101
std::vector< EVENT_ENTRY > m_events
Definition: pns_log_file.h:99
std::unique_ptr< PNS::ROUTING_SETTINGS > m_routerSettings
Definition: pns_log_file.h:98
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
Push and Shove diff pair dimensions (gap) settings dialog.
ROUTER_MODE
Definition: pns_router.h:62
static PNS::VIA * parsePnsViaFromString(PNS::VIA *aSeg, wxStringTokenizer &aTokens)
static std::shared_ptr< SHAPE > parseShape(SHAPE_TYPE expectedType, wxStringTokenizer &aTokens)
const std::set< PNS::ITEM * > deduplicate(const std::set< PNS::ITEM * > &items)
bool parseCommonPnsProps(PNS::ITEM *aItem, const wxString &cmd, wxStringTokenizer &aTokens)
static PNS::ITEM * parseItemFromString(wxStringTokenizer &aTokens)
bool comparePnsItems(const PNS::ITEM *a, const PNS::ITEM *b)
static const wxString readLine(FILE *f)
static PNS::SEGMENT * parsePnsSegmentFromString(PNS::SEGMENT *aSeg, wxStringTokenizer &aTokens)
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
SHAPE_TYPE
Lists all supported shapes.
Definition: shape.h:44
@ SH_CIRCLE
circle
Definition: shape.h:48
@ SH_SEGMENT
line segment
Definition: shape.h:46
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:119
std::set< KIID > m_removedIds
Definition: pns_log_file.h:74
std::set< PNS::ITEM * > m_addedItems
Definition: pns_log_file.h:75
bool Compare(const COMMIT_STATE &aOther)
Definition: pns_log_file.h:57
KIID uuid
Definition: pns_log_file.h:61
VECTOR2I p
Definition: pns_log_file.h:58
PNS::LOGGER::EVENT_TYPE type
Definition: pns_log_file.h:59