KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_logger.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2014 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include "pns_logger.h"
23#include "pns_hole.h"
24
25#include <json_common.h>
26
27#include <wx/log.h>
28#include <wx/tokenzr.h>
29#include <locale_io.h>
30
31#include <board_item.h>
32
33#include "pns_item.h"
34#include "pns_via.h"
35#include "pns_segment.h"
36#include "pns_line.h"
37#include "pns_router.h"
38
39
40void to_json( nlohmann::json& aJson, const VECTOR2I& aPoint )
41{
42 aJson = nlohmann::json
43 {
44 { "x", aPoint.x },
45 { "y", aPoint.y }
46 };
47}
48
49
50void from_json( const nlohmann::json& aJson, VECTOR2I& aPoint )
51{
52 aPoint.x = aJson.at( "x" ).get<int>();
53 aPoint.y = aJson.at( "y" ).get<int>();
54}
55
56
57namespace PNS {
58
60{
61}
62
63
67
68
70{
71 m_events.clear();
72}
73
74
75void LOGGER::LogM( LOGGER::EVENT_TYPE evt, const VECTOR2I& pos, std::vector<ITEM*> items,
76 const SIZES_SETTINGS* sizes, int aLayer )
77{
79
80 ent.type = evt;
81 ent.p = pos;
82 ent.layer = aLayer;
83
84 if( sizes )
85 {
86 ent.sizes = *sizes;
87 }
88
89 for( auto& item : items )
90 {
91 if( item && item->Parent() )
92 ent.uuids.push_back( item->Parent()->m_Uuid );
93 }
94
95 m_events.push_back( ent );
96}
97
98
99void LOGGER::Log( LOGGER::EVENT_TYPE evt, const VECTOR2I& pos, const ITEM* item,
100 const SIZES_SETTINGS* sizes, int aLayer )
101{
102 std::vector<ITEM*> items;
103 items.push_back( const_cast<ITEM*>( item ) );
104 LogM( evt, pos, items, sizes, aLayer );
105}
106
107wxString LOGGER::FormatLogFileAsJSON( const LOG_DATA& aLogData )
108{
109 nlohmann::json json;
110
111
112 json["mode"] = aLogData.m_Mode;
113
114 if( aLogData.m_TestCaseType.has_value() )
115 {
116 json["test_case_type"] = static_cast<int>( aLogData.m_TestCaseType.value() );
117 }
118
119 if( aLogData.m_BoardHash.has_value() )
120 {
121 json["board_hash"] = aLogData.m_BoardHash.value();
122 }
123
124 nlohmann::json events = nlohmann::json::array();
125 for( const EVENT_ENTRY& evt : aLogData.m_Events )
126 events.push_back ( LOGGER::FormatEventAsJSON( evt ) );
127 json["events"] = events;
128
129 nlohmann::json removed = nlohmann::json::array();
130 for( const KIID& uuid : aLogData.m_RemovedItems )
131 removed.push_back( uuid );
132 json["removedItems"] = removed;
133
134 nlohmann::json added = nlohmann::json::array();
135 for( ITEM* item : aLogData.m_AddedItems )
136 added.push_back( formatRouterItemAsJSON( item ) );
137 json["addedItems"] = added;
138
139 nlohmann::json headItems = nlohmann::json::array();
140 for( ITEM* item : aLogData.m_Heads )
141 headItems.push_back( formatRouterItemAsJSON( item ) );
142 json["headItems"] = headItems;
143
145
146 std::stringstream buffer;
147 buffer << std::setw( 2 ) << json << std::endl;
148
149 return buffer.str();
150}
151
152
153nlohmann::json LOGGER::FormatEventAsJSON( const LOGGER::EVENT_ENTRY& aEvent )
154{
155 nlohmann::json ret;
156
157 ret["position"] = aEvent.p;
158 ret["type"] = aEvent.type;
159 ret["layer"] = aEvent.layer;
160 // this is the only relevant setting for the runtime behaviour of the router
161 // we store it straight in the event instead of saving the entire kicad settings
162 ret["useConnectedTrackWidth"] = aEvent.useConnectedTrackWidth;
163
164 nlohmann::json uuids = nlohmann::json::array();
165
166 for( int i = 0; i < (int) aEvent.uuids.size(); i++ )
167 uuids.push_back( aEvent.uuids[i].AsString() );
168
169 ret["uuids"] = uuids;
170 ret["sizes"] = LOGGER::formatSizesAsJSON( aEvent.sizes );
171
172 return ret;
173}
174
175
176nlohmann::json LOGGER::formatRouterItemAsJSON( const PNS::ITEM* aItem )
177 {
178 ROUTER* router = ROUTER::GetInstance();
179 ROUTER_IFACE* iface = router ? router->GetInterface() : nullptr;
180
181 nlohmann::json ret;
182
183 ret ["kind"] = aItem->KindStr();
184
185 if( iface )
186 {
187 ret ["net"] = iface->GetNetName( aItem->Net() );
188 }
189
190 ret ["layers"] = nlohmann::json{ aItem->Layers().Start(), aItem->Layers().End() };
191
192 switch( aItem->Kind() )
193 {
194 case ITEM::SEGMENT_T:
195 case ITEM::ARC_T:
196 ret["shape"] = formatShapeAsJSON( aItem->Shape( aItem->Layer() ) );
197 break;
198
199 case ITEM::LINE_T:
200 {
201 auto line = static_cast<const LINE*>( aItem );
202 ret["width"] = line->Width();
203 ret["shape"] = formatShapeAsJSON( aItem->Shape( aItem->Layer() ) );
204 if( line->EndsWithVia() )
205 ret["via"] = formatRouterItemAsJSON( &line->Via() );
206 break;
207 }
208
209 case ITEM::VIA_T:
210 {
211 auto via = static_cast<const VIA*>( aItem );
212 ret["shape"] = formatShapeAsJSON( aItem->Shape( aItem->Layers().Start() ) ); // JE: pad stacks
213 ret["drill"] = via->Drill();
214 break;
215 }
216 case ITEM::HOLE_T:
217 {
218 auto hole = static_cast<const HOLE*>( aItem );
219 ret["shape"] = formatShapeAsJSON( hole->Shape( -1 ) );
220 break;
221 }
222 default:
223 break; // currently we don't need to log anything else
224 }
225
226 return ret;
227}
228
229
230nlohmann::json LOGGER::formatSizesAsJSON( const SIZES_SETTINGS& aSizes )
231{
232 return nlohmann::json( {
233
234 { "trackWidth", aSizes.TrackWidth() },
235 { "viaDiameter", aSizes.ViaDiameter() },
236 { "viaDrill", aSizes.ViaDrill() },
237 { "trackWidthIsExplicit", aSizes.TrackWidthIsExplicit() },
238 { "layerBottom", aSizes.GetLayerBottom() },
239 { "layerTop", aSizes.GetLayerTop() },
240 { "viaType", aSizes.ViaType() },
241 { "diffPairWidth", aSizes.DiffPairWidth() },
242 { "diffPairGap", aSizes.DiffPairGap() },
243 { "diffPairViaGap", aSizes.DiffPairViaGap() }
244 } );
245}
246
247
248nlohmann::json LOGGER::formatShapeAsJSON( const SHAPE* aShape )
249{
250 switch( aShape->Type() )
251 {
252 case SH_SEGMENT:
253 {
254 auto seg = static_cast<const SHAPE_SEGMENT*>( aShape );
255 return nlohmann::json( {
256 { "type", "segment" },
257 { "width", seg->GetWidth() },
258 { "start", seg->GetStart() },
259 { "end", seg->GetEnd() }
260 } );
261 }
262 case SH_ARC:
263 {
264 auto arc = static_cast<const SHAPE_ARC*>( aShape );
265 return nlohmann::json( {
266 { "type", "arc" },
267 { "width", arc->GetWidth() },
268 { "start", arc->GetStart() },
269 { "end", arc->GetEnd() },
270 { "mid", arc->GetArcMid() }
271 } );
272 }
273 case SH_CIRCLE:
274 {
275 auto circle = static_cast<const SHAPE_CIRCLE*>( aShape );
276 return nlohmann::json( {
277 { "type", "circle" },
278 { "radius", circle->GetRadius() },
279 { "center", circle->GetCenter() },
280 } );
281 }
282 case SH_LINE_CHAIN:
283 {
284 auto schain = static_cast<const SHAPE_LINE_CHAIN*>( aShape );
285 auto points = nlohmann::json::array();
286 for( int i = 0; i < schain->PointCount(); i++ )
287 points.push_back( schain->CPoint( i ) );
288
289 return nlohmann::json( { { "type", "line_chain" }, { "points", points } } );
290 }
291
292 default:
293 break;
294 }
295
296 return nlohmann::json();
297}
298
299
301{
302 wxStringTokenizer tokens( aLine );
303 wxString cmd = tokens.GetNextToken();
304
305 int n_uuids = 0;
306
307 wxCHECK_MSG( cmd == wxT( "event" ), EVENT_ENTRY(), "Line doesn't contain an event!" );
308
309 EVENT_ENTRY evt;
310 evt.p.x = wxAtoi( tokens.GetNextToken() );
311 evt.p.y = wxAtoi( tokens.GetNextToken() );
312 evt.type = (PNS::LOGGER::EVENT_TYPE) wxAtoi( tokens.GetNextToken() );
313 evt.layer = wxAtoi( tokens.GetNextToken() );
314 n_uuids = wxAtoi( tokens.GetNextToken() );
315
316 for( int i = 0; i < n_uuids; i++)
317 evt.uuids.push_back( KIID( tokens.GetNextToken() ) );
318
319 return evt;
320}
321
322
324{
325 EVENT_ENTRY evt;
326
327 auto useConnProp = aJSON.at("useConnectedTrackWidth");
328
329 if( !useConnProp.empty() )
330 evt.useConnectedTrackWidth = useConnProp.get<bool>();
331
332 evt.sizes = parseSizesFromJSON( aJSON.at("sizes") );
333 evt.p = aJSON.at("position").get<VECTOR2I>();
334 evt.type = static_cast<EVENT_TYPE>( aJSON.at("type").get<int>() );
335 evt.layer = aJSON.at("layer").get<int>();
336
337 for( auto &uuid : aJSON.at("uuids") )
338 evt.uuids.push_back( uuid.get<KIID>() );
339
340 return evt;
341}
342
343
344SIZES_SETTINGS LOGGER::parseSizesFromJSON( const nlohmann::json& aJSON )
345{
346 SIZES_SETTINGS sizes;
347
348 try {
349 sizes.SetTrackWidth( aJSON.at("trackWidth").get<int>() );
350 sizes.SetViaDiameter( aJSON.at("viaDiameter").get<int>() );
351 sizes.SetViaDrill( aJSON.at("viaDrill").get<int>() );
352 sizes.SetTrackWidthIsExplicit( aJSON.at("trackWidthIsExplicit").get<bool>() );
353 sizes.SetDiffPairViaGap( aJSON.at("diffPairViaGap").get<int>() );
354 sizes.SetDiffPairGap( aJSON.at("diffPairGap").get<int>() );
355 sizes.SetDiffPairWidth( aJSON.at("diffPairWidth").get<int>() );
356 }
357 catch ( nlohmann::json::exception& )
358 {
359 // be lenient when something is wrong with these settings, they're not critical
360 }
361
362 return sizes;
363}
364
365
366}
367
Definition kiid.h:46
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
Base class for PNS router board items.
Definition pns_item.h:98
virtual const SHAPE * Shape(int aLayer) const
Return the geometrical shape of the item.
Definition pns_item.h:242
const PNS_LAYER_RANGE & Layers() const
Definition pns_item.h:212
virtual NET_HANDLE Net() const
Definition pns_item.h:210
PnsKind Kind() const
Return the type (kind) of the item.
Definition pns_item.h:173
virtual int Layer() const
Definition pns_item.h:216
std::string KindStr() const
Definition pns_item.cpp:315
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition pns_line.h:62
static wxString FormatLogFileAsJSON(const LOG_DATA &aLogData)
void Log(EVENT_TYPE evt, const VECTOR2I &pos=VECTOR2I(), const ITEM *item=nullptr, const SIZES_SETTINGS *sizes=nullptr, int aLayer=0)
static nlohmann::json formatShapeAsJSON(const SHAPE *aShape)
static EVENT_ENTRY ParseEventFromJSON(const nlohmann::json &aJSON)
static SIZES_SETTINGS parseSizesFromJSON(const nlohmann::json &aJSON)
static nlohmann::json FormatEventAsJSON(const EVENT_ENTRY &aEvent)
void LogM(EVENT_TYPE evt, const VECTOR2I &pos=VECTOR2I(), std::vector< ITEM * > items={}, const SIZES_SETTINGS *sizes=nullptr, int aLayer=0)
std::vector< EVENT_ENTRY > m_events
Definition pns_logger.h:139
static nlohmann::json formatRouterItemAsJSON(const PNS::ITEM *aItem)
static EVENT_ENTRY ParseEvent(const wxString &aLine)
static nlohmann::json formatSizesAsJSON(const SIZES_SETTINGS &aEvent)
virtual wxString GetNetName(PNS::NET_HANDLE aNet) const =0
ROUTER_IFACE * GetInterface() const
Definition pns_router.h:254
static ROUTER * GetInstance()
void SetTrackWidth(int aWidth)
void SetDiffPairWidth(int aWidth)
void SetDiffPairGap(int aGap)
void SetViaDrill(int aDrill)
void SetDiffPairViaGap(int aGap)
bool TrackWidthIsExplicit() const
void SetViaDiameter(int aDiameter)
void SetTrackWidthIsExplicit(bool aIsExplicit)
int Start() const
int End() const
SHAPE_TYPE Type() const
Return the type of the shape.
Definition shape.h:96
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
An abstract shape on 2D plane.
Definition shape.h:124
nlohmann::json json
Definition gerbview.cpp:50
Push and Shove diff pair dimensions (gap) settings dialog.
void from_json(const nlohmann::json &aJson, VECTOR2I &aPoint)
void to_json(nlohmann::json &aJson, const VECTOR2I &aPoint)
@ SH_CIRCLE
circle
Definition shape.h:46
@ SH_SEGMENT
line segment
Definition shape.h:44
@ SH_ARC
circular arc
Definition shape.h:50
@ SH_LINE_CHAIN
line chain (polyline)
Definition shape.h:45
std::vector< FAB_LAYER_COLOR > dummy
Definition pns_logger.h:71
int layer
Definition pns_logger.h:76
SIZES_SETTINGS sizes
Definition pns_logger.h:75
std::vector< KIID > uuids
Definition pns_logger.h:74
EVENT_TYPE type
Definition pns_logger.h:73
VECTOR2I p
Definition pns_logger.h:72
bool useConnectedTrackWidth
Definition pns_logger.h:77
std::optional< wxString > m_BoardHash
Definition pns_logger.h:101
std::optional< TEST_CASE_TYPE > m_TestCaseType
Definition pns_logger.h:106
std::vector< ITEM * > m_AddedItems
Definition pns_logger.h:102
std::vector< EVENT_ENTRY > m_Events
Definition pns_logger.h:105
std::set< KIID > m_RemovedItems
Definition pns_logger.h:103
std::vector< ITEM * > m_Heads
Definition pns_logger.h:104
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683