KiCad PCB EDA Suite
Loading...
Searching...
No Matches
corpus.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, see AUTHORS.txt for contributors.
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 "corpus.h"
21
22#include <fstream>
23#include <sstream>
24
25#include <wx/filename.h>
26#include <wx/utils.h>
27
28#include <json_common.h>
29
30
32{
33 wxString root;
34
35 if( !wxGetEnv( wxT( "KICAD_DRC_BENCH_CORPUS" ), &root ) || root.IsEmpty() )
36 return false;
37
38 return wxFileName::DirExists( root );
39}
40
41
42wxString CORPUS::Root()
43{
44 wxString root;
45
46 if( !wxGetEnv( wxT( "KICAD_DRC_BENCH_CORPUS" ), &root ) )
47 return wxEmptyString;
48
49 return root;
50}
51
52
54static wxString resolveAgainstRoot( const wxString& aRoot, const wxString& aRelative )
55{
56 if( aRelative.IsEmpty() )
57 return wxEmptyString;
58
59 wxFileName fn( aRelative );
60
61 if( fn.IsAbsolute() )
62 return fn.GetFullPath();
63
64 wxFileName resolved( aRoot, wxEmptyString );
65 resolved.SetFullName( wxEmptyString );
66
67 wxFileName joined( aRoot + wxFileName::GetPathSeparator() + aRelative );
68 joined.MakeAbsolute();
69
70 return joined.GetFullPath();
71}
72
73
74bool CORPUS::Load( std::vector<CORPUS_ENTRY>& aEntries, wxString& aError )
75{
76 aEntries.clear();
77 aError.clear();
78
79 if( !IsConfigured() )
80 return true;
81
82 wxString root = Root();
83 wxFileName manifest( root, wxT( "corpus.json" ) );
84
85 if( !manifest.Exists() )
86 {
87 aError = wxString::Format( wxT( "corpus.json not found in %s" ), root );
88 return false;
89 }
90
91 std::ifstream in( manifest.GetFullPath().fn_str() );
92
93 if( !in.is_open() )
94 {
95 aError = wxString::Format( wxT( "cannot open %s" ), manifest.GetFullPath() );
96 return false;
97 }
98
99 std::stringstream buffer;
100 buffer << in.rdbuf();
101
102 nlohmann::json doc;
103
104 try
105 {
106 doc = nlohmann::json::parse( buffer.str() );
107 }
108 catch( const std::exception& e )
109 {
110 aError = wxString::Format( wxT( "corpus.json parse error: %s" ), e.what() );
111 return false;
112 }
113
114 if( !doc.is_array() )
115 {
116 aError = wxT( "corpus.json must be a JSON array of entries" );
117 return false;
118 }
119
120 for( const nlohmann::json& node : doc )
121 {
122 if( !node.is_object() || !node.contains( "board" ) )
123 continue;
124
125 CORPUS_ENTRY entry;
126
127 auto getString = [&]( const char* aKey ) -> wxString
128 {
129 if( node.contains( aKey ) && node[aKey].is_string() )
130 return wxString::FromUTF8( node[aKey].get<std::string>().c_str() );
131
132 return wxEmptyString;
133 };
134
135 entry.board = resolveAgainstRoot( root, getString( "board" ) );
136 entry.rules = resolveAgainstRoot( root, getString( "rules" ) );
137 entry.tier = getString( "tier" );
138 entry.source = getString( "source" );
139 entry.notes = getString( "notes" );
140
141 if( node.contains( "quick" ) && node["quick"].is_boolean() )
142 entry.quick = node["quick"].get<bool>();
143
144 aEntries.push_back( entry );
145 }
146
147 return true;
148}
149
150
152{
153 switch( aType )
154 {
155 case NULL_CONSTRAINT: return "null";
156 case CLEARANCE_CONSTRAINT: return "clearance";
157 case CREEPAGE_CONSTRAINT: return "creepage";
158 case HOLE_CLEARANCE_CONSTRAINT: return "hole_clearance";
159 case HOLE_TO_HOLE_CONSTRAINT: return "hole_to_hole";
160 case EDGE_CLEARANCE_CONSTRAINT: return "edge_clearance";
161 case HOLE_SIZE_CONSTRAINT: return "hole_size";
162 case COURTYARD_CLEARANCE_CONSTRAINT: return "courtyard_clearance";
163 case SILK_CLEARANCE_CONSTRAINT: return "silk_clearance";
164 case TEXT_HEIGHT_CONSTRAINT: return "text_height";
165 case TEXT_THICKNESS_CONSTRAINT: return "text_thickness";
166 case TRACK_WIDTH_CONSTRAINT: return "track_width";
167 case TRACK_SEGMENT_LENGTH_CONSTRAINT: return "track_segment_length";
168 case ANNULAR_WIDTH_CONSTRAINT: return "annular_width";
169 case ZONE_CONNECTION_CONSTRAINT: return "zone_connection";
170 case THERMAL_RELIEF_GAP_CONSTRAINT: return "thermal_relief_gap";
171 case THERMAL_SPOKE_WIDTH_CONSTRAINT: return "thermal_spoke_width";
172 case MIN_RESOLVED_SPOKES_CONSTRAINT: return "min_resolved_spokes";
173 case SOLDER_MASK_EXPANSION_CONSTRAINT: return "solder_mask_expansion";
174 case SOLDER_PASTE_ABS_MARGIN_CONSTRAINT: return "solder_paste_abs_margin";
175 case SOLDER_PASTE_REL_MARGIN_CONSTRAINT: return "solder_paste_rel_margin";
176 case DISALLOW_CONSTRAINT: return "disallow";
177 case VIA_DIAMETER_CONSTRAINT: return "via_diameter";
178 case LENGTH_CONSTRAINT: return "length";
179 case NET_CHAIN_LENGTH_CONSTRAINT: return "net_chain_length";
180 case NET_CHAIN_STUB_LENGTH_CONSTRAINT: return "net_chain_stub_length";
181 case NET_CHAIN_RETURN_PATH_CONSTRAINT: return "net_chain_return_path";
182 case SKEW_CONSTRAINT: return "skew";
183 case DIFF_PAIR_GAP_CONSTRAINT: return "diff_pair_gap";
184 case MAX_UNCOUPLED_CONSTRAINT: return "max_uncoupled";
185 case DIFF_PAIR_INTRA_SKEW_CONSTRAINT: return "diff_pair_intra_skew";
186 case VIA_COUNT_CONSTRAINT: return "via_count";
187 case PHYSICAL_CLEARANCE_CONSTRAINT: return "physical_clearance";
188 case PHYSICAL_HOLE_CLEARANCE_CONSTRAINT: return "physical_hole_clearance";
189 case ASSERTION_CONSTRAINT: return "assertion";
190 case CONNECTION_WIDTH_CONSTRAINT: return "connection_width";
191 case TRACK_ANGLE_CONSTRAINT: return "track_angle";
192 case VIA_DANGLING_CONSTRAINT: return "via_dangling";
193 case BRIDGED_MASK_CONSTRAINT: return "bridged_mask";
194 case SOLDER_MASK_SLIVER_CONSTRAINT: return "solder_mask_sliver";
195 }
196
197 return "?";
198}
199
200
228
229
230const std::vector<wxString>& AllPredicateNames()
231{
232 // Mirrors the RegisterFunc entries in pcbexpr_functions.cpp. The expensive geometry and
233 // per-item lookups the optimizer watches are listed first for readability, but the order is
234 // not load-bearing.
235 static const std::vector<wxString> names = {
236 wxT( "intersectsCourtyard" ), wxT( "intersectsFrontCourtyard" ),
237 wxT( "intersectsBackCourtyard" ), wxT( "insideCourtyard" ),
238 wxT( "insideFrontCourtyard" ), wxT( "insideBackCourtyard" ),
239 wxT( "intersectsArea" ), wxT( "enclosedByArea" ),
240 wxT( "insideArea" ), wxT( "getField" ),
241 wxT( "hasNetclass" ), wxT( "hasExactNetclass" ),
242 wxT( "hasComponentClass" ), wxT( "memberOf" ),
243 wxT( "memberOfSheet" ), wxT( "memberOfSheetOrChildren" ),
244 wxT( "memberOfFootprint" ), wxT( "memberOfGroup" ),
245 wxT( "fromTo" ), wxT( "inDiffPair" ),
246 wxT( "isCoupledDiffPair" ), wxT( "inNetChain" ),
247 wxT( "inNetChainClass" ), wxT( "hasNetChain" ),
248 wxT( "existsOnLayer" ), wxT( "isPlated" ),
249 wxT( "isMicroVia" ), wxT( "isBlindVia" ),
250 wxT( "isBuriedVia" ), wxT( "isBlindBuriedVia" )
251 };
252
253 return names;
254}
255
256
257std::vector<wxString> ScanPredicatesInRules( const wxString& aRulesText )
258{
259 std::vector<wxString> found;
260
261 for( const wxString& name : AllPredicateNames() )
262 {
263 // The grammar always invokes a predicate as name( ... ), so anchor on the open paren to
264 // avoid matching a predicate name that only appears inside a comment or a longer token.
265 size_t searchFrom = 0;
266
267 while( true )
268 {
269 size_t pos = aRulesText.find( name, searchFrom );
270
271 if( pos == wxString::npos )
272 break;
273
274 size_t after = pos + name.length();
275
276 while( after < aRulesText.length() && wxIsspace( aRulesText[after] ) )
277 ++after;
278
279 if( after < aRulesText.length() && aRulesText[after] == '(' )
280 {
281 found.push_back( name );
282 break;
283 }
284
285 searchFrom = pos + 1;
286 }
287 }
288
289 return found;
290}
const char * name
static bool Load(std::vector< CORPUS_ENTRY > &aEntries, wxString &aError)
Parse <root>/corpus.json into resolved entries.
Definition corpus.cpp:74
static bool IsConfigured()
True when KICAD_DRC_BENCH_CORPUS is set and names an existing directory.
Definition corpus.cpp:31
static wxString Root()
The resolved corpus root, or an empty string when unconfigured.
Definition corpus.cpp:42
const char * ConstraintTypeName(DRC_CONSTRAINT_T aType)
Human-readable token for a DRC_CONSTRAINT_T, matching the .kicad_dru keyword where one exists.
Definition corpus.cpp:151
std::vector< wxString > ScanPredicatesInRules(const wxString &aRulesText)
Scan raw .kicad_dru text for occurrences of each registered predicate name.
Definition corpus.cpp:257
const std::vector< wxString > & AllPredicateNames()
Every pcbexpr predicate registered in pcbexpr_functions.cpp, used for textual coverage scans.
Definition corpus.cpp:230
static wxString resolveAgainstRoot(const wxString &aRoot, const wxString &aRelative)
Resolve a manifest-relative path against the corpus root and return an absolute path.
Definition corpus.cpp:54
const std::vector< DRC_CONSTRAINT_T > & AllConstraintTypes()
Every DRC_CONSTRAINT_T the engine can carry rules for, in enum order, excluding NULL_CONSTRAINT.
Definition corpus.cpp:201
DRC_CONSTRAINT_T
Definition drc_rule.h:49
@ ANNULAR_WIDTH_CONSTRAINT
Definition drc_rule.h:63
@ BRIDGED_MASK_CONSTRAINT
Definition drc_rule.h:88
@ COURTYARD_CLEARANCE_CONSTRAINT
Definition drc_rule.h:57
@ VIA_DIAMETER_CONSTRAINT
Definition drc_rule.h:72
@ ZONE_CONNECTION_CONSTRAINT
Definition drc_rule.h:64
@ DIFF_PAIR_GAP_CONSTRAINT
Definition drc_rule.h:78
@ NET_CHAIN_LENGTH_CONSTRAINT
Definition drc_rule.h:74
@ VIA_DANGLING_CONSTRAINT
Definition drc_rule.h:87
@ SOLDER_MASK_SLIVER_CONSTRAINT
Definition drc_rule.h:89
@ NET_CHAIN_STUB_LENGTH_CONSTRAINT
Definition drc_rule.h:75
@ DISALLOW_CONSTRAINT
Definition drc_rule.h:71
@ TRACK_WIDTH_CONSTRAINT
Definition drc_rule.h:61
@ SILK_CLEARANCE_CONSTRAINT
Definition drc_rule.h:58
@ EDGE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:55
@ MIN_RESOLVED_SPOKES_CONSTRAINT
Definition drc_rule.h:67
@ TRACK_SEGMENT_LENGTH_CONSTRAINT
Definition drc_rule.h:62
@ TEXT_THICKNESS_CONSTRAINT
Definition drc_rule.h:60
@ LENGTH_CONSTRAINT
Definition drc_rule.h:73
@ VIA_COUNT_CONSTRAINT
Definition drc_rule.h:81
@ NET_CHAIN_RETURN_PATH_CONSTRAINT
Definition drc_rule.h:76
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:83
@ CLEARANCE_CONSTRAINT
Definition drc_rule.h:51
@ NULL_CONSTRAINT
Definition drc_rule.h:50
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
Definition drc_rule.h:66
@ CONNECTION_WIDTH_CONSTRAINT
Definition drc_rule.h:85
@ THERMAL_RELIEF_GAP_CONSTRAINT
Definition drc_rule.h:65
@ MAX_UNCOUPLED_CONSTRAINT
Definition drc_rule.h:79
@ ASSERTION_CONSTRAINT
Definition drc_rule.h:84
@ SKEW_CONSTRAINT
Definition drc_rule.h:77
@ HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:53
@ SOLDER_PASTE_ABS_MARGIN_CONSTRAINT
Definition drc_rule.h:69
@ SOLDER_MASK_EXPANSION_CONSTRAINT
Definition drc_rule.h:68
@ TRACK_ANGLE_CONSTRAINT
Definition drc_rule.h:86
@ HOLE_SIZE_CONSTRAINT
Definition drc_rule.h:56
@ TEXT_HEIGHT_CONSTRAINT
Definition drc_rule.h:59
@ CREEPAGE_CONSTRAINT
Definition drc_rule.h:52
@ DIFF_PAIR_INTRA_SKEW_CONSTRAINT
Definition drc_rule.h:80
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition drc_rule.h:82
@ SOLDER_PASTE_REL_MARGIN_CONSTRAINT
Definition drc_rule.h:70
@ HOLE_TO_HOLE_CONSTRAINT
Definition drc_rule.h:54
One board+rules pairing from the out-of-tree corpus manifest.
Definition corpus.h:36
wxString tier
Free-form tier tag from the manifest (A/B/C).
Definition corpus.h:39
wxString board
Absolute path to the .kicad_pcb.
Definition corpus.h:37
wxString rules
Absolute path to the .kicad_dru, or empty for none.
Definition corpus.h:38
wxString source
Provenance string for traceability.
Definition corpus.h:40
wxString notes
Free-form annotation.
Definition corpus.h:41
bool quick
Part of the fast iteration set selected by –quick.
Definition corpus.h:42