Browse Source
fix for issue 17429 - DRC exclusion instability
fix for issue 17429 - DRC exclusion instability
- backported from master
- fix for issue-17429 - DRC unnconnected items exclusion instability
- new serialization format for unconnected items (MainID and AuxID
last)
- RunOnUnconnectedItems sorts RN_NET edges for stability
- ResolveDRCExclusions now matches unconnected items by not matching on
MainID and AuxID
9.0
10 changed files with 9534 additions and 9 deletions
-
72pcbnew/board.cpp
-
36pcbnew/connectivity/connectivity_algo.h
-
1pcbnew/dialogs/dialog_drc.cpp
-
28pcbnew/pcb_marker.cpp
-
25pcbnew/ratsnest/ratsnest_data.h
-
8082qa/data/pcbnew/issue17429.kicad_pcb
-
960qa/data/pcbnew/issue17429.kicad_pro
-
8qa/pcbnew_utils/board_test_utils.cpp
-
1qa/tests/pcbnew/CMakeLists.txt
-
330qa/tests/pcbnew/drc/test_drc_unconnected_items_exclusion_loss.cpp
8082
qa/data/pcbnew/issue17429.kicad_pcb
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,960 @@ |
|||
{ |
|||
"board": { |
|||
"3dviewports": [], |
|||
"design_settings": { |
|||
"defaults": { |
|||
"apply_defaults_to_fp_fields": false, |
|||
"apply_defaults_to_fp_shapes": false, |
|||
"apply_defaults_to_fp_text": false, |
|||
"board_outline_line_width": 0.05, |
|||
"copper_line_width": 0.2, |
|||
"copper_text_italic": false, |
|||
"copper_text_size_h": 1.5, |
|||
"copper_text_size_v": 1.5, |
|||
"copper_text_thickness": 0.3, |
|||
"copper_text_upright": false, |
|||
"courtyard_line_width": 0.05, |
|||
"dimension_precision": 4, |
|||
"dimension_units": 3, |
|||
"dimensions": { |
|||
"arrow_length": 1270000, |
|||
"extension_offset": 500000, |
|||
"keep_text_aligned": true, |
|||
"suppress_zeroes": false, |
|||
"text_position": 0, |
|||
"units_format": 1 |
|||
}, |
|||
"fab_line_width": 0.1, |
|||
"fab_text_italic": false, |
|||
"fab_text_size_h": 1.0, |
|||
"fab_text_size_v": 1.0, |
|||
"fab_text_thickness": 0.15, |
|||
"fab_text_upright": false, |
|||
"other_line_width": 0.1, |
|||
"other_text_italic": false, |
|||
"other_text_size_h": 1.0, |
|||
"other_text_size_v": 1.0, |
|||
"other_text_thickness": 0.15, |
|||
"other_text_upright": false, |
|||
"pads": { |
|||
"drill": 0.0, |
|||
"height": 1.8, |
|||
"width": 1.2 |
|||
}, |
|||
"silk_line_width": 0.12, |
|||
"silk_text_italic": false, |
|||
"silk_text_size_h": 1.0, |
|||
"silk_text_size_v": 1.0, |
|||
"silk_text_thickness": 0.15, |
|||
"silk_text_upright": false, |
|||
"zones": { |
|||
"45_degree_only": false, |
|||
"min_clearance": 0.508 |
|||
} |
|||
}, |
|||
"diff_pair_dimensions": [ |
|||
{ |
|||
"gap": 0.0, |
|||
"via_gap": 0.0, |
|||
"width": 0.0 |
|||
}, |
|||
{ |
|||
"gap": 0.127, |
|||
"via_gap": 0.127, |
|||
"width": 0.154 |
|||
} |
|||
], |
|||
"drc_exclusions": [ |
|||
[ |
|||
"unconnected_items|115460000|155800000|F.Cu|4|221e4293-1dad-4f91-a869-d39634ca7647|74f57098-b83f-40bf-9a16-2adad8dcb50b", |
|||
"" |
|||
], |
|||
[ |
|||
"unconnected_items|115460000|159000000|F.Cu|4|e5b239f2-afe1-4783-8a0b-bf234fea22df|113054e2-9827-4c9f-a8ee-9dead8ac7000", |
|||
"" |
|||
], |
|||
[ |
|||
"unconnected_items|115460000|161400000|F.Cu|4|cff4aed3-271d-45c0-a3c4-046e16b7f260|d384076d-8217-4237-8a13-86ece3667b99", |
|||
"" |
|||
], |
|||
[ |
|||
"unconnected_items|115460000|165400000|F.Cu|4|74da9126-9d2f-4c1d-b8a1-021e27bcafbe|519972f5-567a-42f1-a038-c4960d508559", |
|||
"" |
|||
], |
|||
[ |
|||
"unconnected_items|115460000|166200000|F.Cu|4|3f4da512-b026-405d-a045-87c506a3ef63|87b98e0c-3614-42af-8982-59c036259cc8", |
|||
"" |
|||
], |
|||
[ |
|||
"unconnected_items|115460000|168600000|F.Cu|4|742ed10c-8c85-48f3-b92b-a749b92a3c8c|c7b6b524-0fb3-41c8-9654-229fe7bd19e7", |
|||
"" |
|||
], |
|||
[ |
|||
"unconnected_items|118540000|154600000|F.Cu|4|69b8910c-2ead-48f4-9358-4be4a4a0663e|539d8a1e-5e53-4252-9a33-1eb2c9717a4b", |
|||
"" |
|||
], |
|||
[ |
|||
"unconnected_items|118540000|155000000|F.Cu|4|d3546ca6-3035-4598-a37d-c76932d318fd|3eab64eb-a1f0-434d-968b-cd0f04f08b5b", |
|||
"" |
|||
], |
|||
[ |
|||
"unconnected_items|118540000|158200000|F.Cu|4|e3fa1053-01eb-44fc-ac99-4eb5213cc1c6|ef60360a-a7b4-4448-90c3-e2532f9767b4", |
|||
"" |
|||
], |
|||
[ |
|||
"unconnected_items|118540000|167800000|F.Cu|4|18383a8f-1c88-4048-a569-5b451205ef1b|c717c398-f57e-451d-8ffd-3863c703056a", |
|||
"" |
|||
] |
|||
], |
|||
"meta": { |
|||
"filename": "board_design_settings.json", |
|||
"version": 2 |
|||
}, |
|||
"rule_severities": { |
|||
"annular_width": "error", |
|||
"clearance": "error", |
|||
"connection_width": "warning", |
|||
"copper_edge_clearance": "error", |
|||
"copper_sliver": "warning", |
|||
"courtyards_overlap": "error", |
|||
"creepage": "error", |
|||
"diff_pair_gap_out_of_range": "error", |
|||
"diff_pair_uncoupled_length_too_long": "error", |
|||
"drill_out_of_range": "error", |
|||
"duplicate_footprints": "warning", |
|||
"extra_footprint": "warning", |
|||
"footprint": "error", |
|||
"footprint_filters_mismatch": "ignore", |
|||
"footprint_symbol_mismatch": "warning", |
|||
"footprint_type_mismatch": "error", |
|||
"hole_clearance": "error", |
|||
"hole_near_hole": "error", |
|||
"hole_to_hole": "error", |
|||
"holes_co_located": "warning", |
|||
"invalid_outline": "error", |
|||
"isolated_copper": "warning", |
|||
"item_on_disabled_layer": "error", |
|||
"items_not_allowed": "error", |
|||
"length_out_of_range": "error", |
|||
"lib_footprint_issues": "warning", |
|||
"lib_footprint_mismatch": "warning", |
|||
"malformed_courtyard": "error", |
|||
"microvia_drill_out_of_range": "error", |
|||
"mirrored_text_on_front_layer": "warning", |
|||
"missing_courtyard": "ignore", |
|||
"missing_footprint": "warning", |
|||
"net_conflict": "warning", |
|||
"nonmirrored_text_on_back_layer": "warning", |
|||
"npth_inside_courtyard": "ignore", |
|||
"padstack": "error", |
|||
"pth_inside_courtyard": "ignore", |
|||
"shorting_items": "error", |
|||
"silk_edge_clearance": "warning", |
|||
"silk_over_copper": "warning", |
|||
"silk_overlap": "warning", |
|||
"skew_out_of_range": "error", |
|||
"solder_mask_bridge": "error", |
|||
"starved_thermal": "error", |
|||
"text_height": "warning", |
|||
"text_on_edge_cuts": "error", |
|||
"text_thickness": "warning", |
|||
"through_hole_pad_without_hole": "error", |
|||
"too_many_vias": "error", |
|||
"track_angle": "error", |
|||
"track_dangling": "warning", |
|||
"track_segment_length": "error", |
|||
"track_width": "error", |
|||
"tracks_crossing": "error", |
|||
"unconnected_items": "error", |
|||
"unresolved_variable": "error", |
|||
"via_dangling": "warning", |
|||
"zones_intersect": "error" |
|||
}, |
|||
"rules": { |
|||
"allow_blind_buried_vias": true, |
|||
"allow_microvias": true, |
|||
"max_error": 0.005, |
|||
"min_clearance": 0.127, |
|||
"min_connection": 0.0, |
|||
"min_copper_edge_clearance": 0.254, |
|||
"min_groove_width": 0.0, |
|||
"min_hole_clearance": 0.127, |
|||
"min_hole_to_hole": 0.254, |
|||
"min_microvia_diameter": 0.2, |
|||
"min_microvia_drill": 0.1, |
|||
"min_resolved_spokes": 2, |
|||
"min_silk_clearance": 0.0, |
|||
"min_text_height": 0.8, |
|||
"min_text_thickness": 0.08, |
|||
"min_through_hole_diameter": 0.254, |
|||
"min_track_width": 0.15, |
|||
"min_via_annular_width": 0.1016, |
|||
"min_via_diameter": 0.254, |
|||
"solder_mask_to_copper_clearance": 0.0, |
|||
"use_height_for_length_calcs": true |
|||
}, |
|||
"teardrop_options": [ |
|||
{ |
|||
"td_onpthpad": true, |
|||
"td_onroundshapesonly": false, |
|||
"td_onsmdpad": true, |
|||
"td_ontrackend": false, |
|||
"td_onvia": true |
|||
} |
|||
], |
|||
"teardrop_parameters": [ |
|||
{ |
|||
"td_allow_use_two_tracks": true, |
|||
"td_curve_segcount": 0, |
|||
"td_height_ratio": 1.0, |
|||
"td_length_ratio": 0.5, |
|||
"td_maxheight": 2.0, |
|||
"td_maxlen": 1.0, |
|||
"td_on_pad_in_zone": false, |
|||
"td_target_name": "td_round_shape", |
|||
"td_width_to_size_filter_ratio": 0.9 |
|||
}, |
|||
{ |
|||
"td_allow_use_two_tracks": true, |
|||
"td_curve_segcount": 0, |
|||
"td_height_ratio": 1.0, |
|||
"td_length_ratio": 0.5, |
|||
"td_maxheight": 2.0, |
|||
"td_maxlen": 1.0, |
|||
"td_on_pad_in_zone": false, |
|||
"td_target_name": "td_rect_shape", |
|||
"td_width_to_size_filter_ratio": 0.9 |
|||
}, |
|||
{ |
|||
"td_allow_use_two_tracks": true, |
|||
"td_curve_segcount": 0, |
|||
"td_height_ratio": 1.0, |
|||
"td_length_ratio": 0.5, |
|||
"td_maxheight": 2.0, |
|||
"td_maxlen": 1.0, |
|||
"td_on_pad_in_zone": false, |
|||
"td_target_name": "td_track_end", |
|||
"td_width_to_size_filter_ratio": 0.9 |
|||
} |
|||
], |
|||
"track_widths": [ |
|||
0.0, |
|||
0.127, |
|||
0.154, |
|||
0.254, |
|||
0.4, |
|||
0.5 |
|||
], |
|||
"tuning_pattern_settings": { |
|||
"diff_pair_defaults": { |
|||
"corner_radius_percentage": 80, |
|||
"corner_style": 1, |
|||
"max_amplitude": 1.0, |
|||
"min_amplitude": 0.2, |
|||
"single_sided": false, |
|||
"spacing": 1.0 |
|||
}, |
|||
"diff_pair_skew_defaults": { |
|||
"corner_radius_percentage": 80, |
|||
"corner_style": 1, |
|||
"max_amplitude": 1.0, |
|||
"min_amplitude": 0.2, |
|||
"single_sided": false, |
|||
"spacing": 0.6 |
|||
}, |
|||
"single_track_defaults": { |
|||
"corner_radius_percentage": 80, |
|||
"corner_style": 1, |
|||
"max_amplitude": 1.0, |
|||
"min_amplitude": 0.2, |
|||
"single_sided": false, |
|||
"spacing": 0.6 |
|||
} |
|||
}, |
|||
"via_dimensions": [ |
|||
{ |
|||
"diameter": 0.0, |
|||
"drill": 0.0 |
|||
}, |
|||
{ |
|||
"diameter": 0.3483, |
|||
"drill": 0.2467 |
|||
}, |
|||
{ |
|||
"diameter": 0.3556, |
|||
"drill": 0.254 |
|||
}, |
|||
{ |
|||
"diameter": 0.4572, |
|||
"drill": 0.254 |
|||
}, |
|||
{ |
|||
"diameter": 0.5, |
|||
"drill": 0.375 |
|||
} |
|||
], |
|||
"zones_allow_external_fillets": false, |
|||
"zones_use_no_outline": true |
|||
}, |
|||
"ipc2581": { |
|||
"dist": "", |
|||
"distpn": "", |
|||
"internal_id": "", |
|||
"mfg": "", |
|||
"mpn": "" |
|||
}, |
|||
"layer_pairs": [], |
|||
"layer_presets": [ |
|||
{ |
|||
"activeLayer": -2, |
|||
"flipBoard": false, |
|||
"layers": [ |
|||
4, |
|||
8, |
|||
10, |
|||
12, |
|||
14, |
|||
16, |
|||
18, |
|||
20, |
|||
22, |
|||
24, |
|||
25, |
|||
26, |
|||
28, |
|||
30, |
|||
32, |
|||
34, |
|||
36, |
|||
38, |
|||
40, |
|||
42, |
|||
44, |
|||
46, |
|||
48, |
|||
50, |
|||
52, |
|||
54, |
|||
56, |
|||
58, |
|||
60, |
|||
62 |
|||
], |
|||
"name": "In.1 Cu - AGND", |
|||
"renderLayers": [ |
|||
"vias", |
|||
"footprint_text", |
|||
"footprint_anchors", |
|||
"ratsnest", |
|||
"grid", |
|||
"footprints_front", |
|||
"footprints_back", |
|||
"footprint_values", |
|||
"footprint_references", |
|||
"tracks", |
|||
"drc_errors", |
|||
"drawing_sheet", |
|||
"bitmaps", |
|||
"pads", |
|||
"zones", |
|||
"drc_warnings" |
|||
] |
|||
}, |
|||
{ |
|||
"activeLayer": -2, |
|||
"flipBoard": false, |
|||
"layers": [ |
|||
6, |
|||
8, |
|||
10, |
|||
12, |
|||
14, |
|||
16, |
|||
18, |
|||
20, |
|||
22, |
|||
24, |
|||
25, |
|||
26, |
|||
28, |
|||
30, |
|||
32, |
|||
34, |
|||
36, |
|||
38, |
|||
40, |
|||
42, |
|||
44, |
|||
46, |
|||
48, |
|||
50, |
|||
52, |
|||
54, |
|||
56, |
|||
58, |
|||
60, |
|||
62 |
|||
], |
|||
"name": "In.2 Cu - DVDD / AVDD / AVSS", |
|||
"renderLayers": [ |
|||
"vias", |
|||
"footprint_text", |
|||
"footprint_anchors", |
|||
"ratsnest", |
|||
"grid", |
|||
"footprints_front", |
|||
"footprints_back", |
|||
"footprint_values", |
|||
"footprint_references", |
|||
"tracks", |
|||
"drc_errors", |
|||
"drawing_sheet", |
|||
"bitmaps", |
|||
"pads", |
|||
"zones", |
|||
"drc_warnings" |
|||
] |
|||
}, |
|||
{ |
|||
"activeLayer": -2, |
|||
"flipBoard": false, |
|||
"layers": [ |
|||
14, |
|||
16, |
|||
18, |
|||
20, |
|||
22, |
|||
24, |
|||
25, |
|||
26, |
|||
28, |
|||
30, |
|||
32, |
|||
34, |
|||
36, |
|||
37, |
|||
38, |
|||
40, |
|||
42, |
|||
44, |
|||
46, |
|||
48, |
|||
49, |
|||
50, |
|||
51, |
|||
52, |
|||
53, |
|||
54, |
|||
55, |
|||
56, |
|||
58, |
|||
60, |
|||
62 |
|||
], |
|||
"name": "Layer 6 - x signal", |
|||
"renderLayers": [ |
|||
"vias", |
|||
"footprint_text", |
|||
"footprint_anchors", |
|||
"footprints_front", |
|||
"footprints_back", |
|||
"footprint_values", |
|||
"footprint_references", |
|||
"tracks", |
|||
"drc_errors", |
|||
"drawing_sheet", |
|||
"bitmaps", |
|||
"pads", |
|||
"zones", |
|||
"drc_warnings" |
|||
] |
|||
}, |
|||
{ |
|||
"activeLayer": -2, |
|||
"flipBoard": false, |
|||
"layers": [ |
|||
8, |
|||
10, |
|||
16, |
|||
18, |
|||
20, |
|||
22, |
|||
24, |
|||
25, |
|||
26, |
|||
27, |
|||
28, |
|||
29, |
|||
30, |
|||
31, |
|||
32, |
|||
33, |
|||
34, |
|||
35, |
|||
36, |
|||
37, |
|||
38, |
|||
40, |
|||
42, |
|||
44, |
|||
46, |
|||
48, |
|||
50, |
|||
52, |
|||
54, |
|||
56, |
|||
58, |
|||
60, |
|||
62 |
|||
], |
|||
"name": "horiz-vert inner", |
|||
"renderLayers": [ |
|||
"vias", |
|||
"footprint_text", |
|||
"footprint_anchors", |
|||
"footprints_front", |
|||
"footprints_back", |
|||
"footprint_values", |
|||
"footprint_references", |
|||
"tracks", |
|||
"drc_errors", |
|||
"drawing_sheet", |
|||
"bitmaps", |
|||
"pads", |
|||
"zones", |
|||
"drc_warnings" |
|||
] |
|||
} |
|||
], |
|||
"viewports": [] |
|||
}, |
|||
"boards": [], |
|||
"cvpcb": { |
|||
"equivalence_files": [] |
|||
}, |
|||
"erc": { |
|||
"erc_exclusions": [], |
|||
"meta": { |
|||
"version": 0 |
|||
}, |
|||
"pin_map": [ |
|||
[ |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
1, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
2 |
|||
], |
|||
[ |
|||
0, |
|||
2, |
|||
0, |
|||
1, |
|||
0, |
|||
0, |
|||
1, |
|||
0, |
|||
2, |
|||
2, |
|||
2, |
|||
2 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
1, |
|||
0, |
|||
1, |
|||
0, |
|||
1, |
|||
2 |
|||
], |
|||
[ |
|||
0, |
|||
1, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
1, |
|||
1, |
|||
2, |
|||
1, |
|||
1, |
|||
2 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
1, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
2 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
2 |
|||
], |
|||
[ |
|||
1, |
|||
1, |
|||
1, |
|||
1, |
|||
1, |
|||
0, |
|||
1, |
|||
1, |
|||
1, |
|||
1, |
|||
1, |
|||
2 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0, |
|||
1, |
|||
0, |
|||
0, |
|||
1, |
|||
0, |
|||
0, |
|||
0, |
|||
0, |
|||
2 |
|||
], |
|||
[ |
|||
0, |
|||
2, |
|||
1, |
|||
2, |
|||
0, |
|||
0, |
|||
1, |
|||
0, |
|||
2, |
|||
2, |
|||
2, |
|||
2 |
|||
], |
|||
[ |
|||
0, |
|||
2, |
|||
0, |
|||
1, |
|||
0, |
|||
0, |
|||
1, |
|||
0, |
|||
2, |
|||
0, |
|||
0, |
|||
2 |
|||
], |
|||
[ |
|||
0, |
|||
2, |
|||
1, |
|||
1, |
|||
0, |
|||
0, |
|||
1, |
|||
0, |
|||
2, |
|||
0, |
|||
0, |
|||
2 |
|||
], |
|||
[ |
|||
2, |
|||
2, |
|||
2, |
|||
2, |
|||
2, |
|||
2, |
|||
2, |
|||
2, |
|||
2, |
|||
2, |
|||
2, |
|||
2 |
|||
] |
|||
], |
|||
"rule_severities": { |
|||
"bus_definition_conflict": "error", |
|||
"bus_entry_needed": "error", |
|||
"bus_to_bus_conflict": "error", |
|||
"bus_to_net_conflict": "error", |
|||
"conflicting_netclasses": "error", |
|||
"different_unit_footprint": "error", |
|||
"different_unit_net": "error", |
|||
"duplicate_reference": "error", |
|||
"duplicate_sheet_names": "error", |
|||
"endpoint_off_grid": "warning", |
|||
"extra_units": "error", |
|||
"footprint_filter": "ignore", |
|||
"footprint_link_issues": "warning", |
|||
"four_way_junction": "ignore", |
|||
"global_label_dangling": "warning", |
|||
"hier_label_mismatch": "error", |
|||
"label_dangling": "error", |
|||
"label_multiple_wires": "warning", |
|||
"lib_symbol_issues": "warning", |
|||
"lib_symbol_mismatch": "warning", |
|||
"missing_bidi_pin": "warning", |
|||
"missing_input_pin": "warning", |
|||
"missing_power_pin": "error", |
|||
"missing_unit": "warning", |
|||
"multiple_net_names": "warning", |
|||
"net_not_bus_member": "warning", |
|||
"no_connect_connected": "warning", |
|||
"no_connect_dangling": "warning", |
|||
"pin_not_connected": "error", |
|||
"pin_not_driven": "error", |
|||
"pin_to_pin": "warning", |
|||
"power_pin_not_driven": "error", |
|||
"same_local_global_label": "warning", |
|||
"similar_label_and_power": "warning", |
|||
"similar_labels": "warning", |
|||
"similar_power": "warning", |
|||
"simulation_model_issue": "ignore", |
|||
"single_global_label": "ignore", |
|||
"unannotated": "error", |
|||
"unconnected_wire_endpoint": "warning", |
|||
"unit_value_mismatch": "error", |
|||
"unresolved_variable": "error", |
|||
"wire_dangling": "error" |
|||
} |
|||
}, |
|||
"libraries": { |
|||
"pinned_footprint_libs": [], |
|||
"pinned_symbol_libs": [] |
|||
}, |
|||
"meta": { |
|||
"filename": "issue17429-9.0.kicad_pro", |
|||
"version": 3 |
|||
}, |
|||
"net_settings": { |
|||
"classes": [ |
|||
{ |
|||
"bus_width": 12, |
|||
"clearance": 0.127, |
|||
"diff_pair_gap": 0.127, |
|||
"diff_pair_via_gap": 0.25, |
|||
"diff_pair_width": 0.154, |
|||
"line_style": 0, |
|||
"microvia_diameter": 0.254, |
|||
"microvia_drill": 0.4572, |
|||
"name": "Default", |
|||
"pcb_color": "rgba(0, 0, 0, 0.000)", |
|||
"priority": 2147483647, |
|||
"schematic_color": "rgba(0, 0, 0, 0.000)", |
|||
"track_width": 0.154, |
|||
"via_diameter": 0.4572, |
|||
"via_drill": 0.254, |
|||
"wire_width": 6 |
|||
} |
|||
], |
|||
"meta": { |
|||
"version": 4 |
|||
}, |
|||
"net_colors": null, |
|||
"netclass_assignments": null, |
|||
"netclass_patterns": [] |
|||
}, |
|||
"pcbnew": { |
|||
"last_paths": { |
|||
"gencad": "", |
|||
"idf": "", |
|||
"netlist": "", |
|||
"plot": "", |
|||
"pos_files": "", |
|||
"specctra_dsn": "", |
|||
"step": "", |
|||
"svg": "", |
|||
"vrml": "" |
|||
}, |
|||
"page_layout_descr_file": "" |
|||
}, |
|||
"schematic": { |
|||
"annotate_start_num": 0, |
|||
"bom_export_filename": "", |
|||
"bom_fmt_presets": [], |
|||
"bom_fmt_settings": { |
|||
"field_delimiter": ",", |
|||
"keep_line_breaks": false, |
|||
"keep_tabs": false, |
|||
"name": "CSV", |
|||
"ref_delimiter": ",", |
|||
"ref_range_delimiter": "", |
|||
"string_delimiter": "\"" |
|||
}, |
|||
"bom_presets": [], |
|||
"bom_settings": { |
|||
"exclude_dnp": false, |
|||
"fields_ordered": [ |
|||
{ |
|||
"group_by": false, |
|||
"label": "Reference", |
|||
"name": "Reference", |
|||
"show": true |
|||
}, |
|||
{ |
|||
"group_by": true, |
|||
"label": "Value", |
|||
"name": "Value", |
|||
"show": true |
|||
}, |
|||
{ |
|||
"group_by": false, |
|||
"label": "Datasheet", |
|||
"name": "Datasheet", |
|||
"show": true |
|||
}, |
|||
{ |
|||
"group_by": false, |
|||
"label": "Footprint", |
|||
"name": "Footprint", |
|||
"show": true |
|||
}, |
|||
{ |
|||
"group_by": false, |
|||
"label": "Qty", |
|||
"name": "${QUANTITY}", |
|||
"show": true |
|||
}, |
|||
{ |
|||
"group_by": true, |
|||
"label": "DNP", |
|||
"name": "${DNP}", |
|||
"show": true |
|||
} |
|||
], |
|||
"filter_string": "", |
|||
"group_symbols": true, |
|||
"include_excluded_from_bom": false, |
|||
"name": "Grouped By Value", |
|||
"sort_asc": true, |
|||
"sort_field": "Reference" |
|||
}, |
|||
"connection_grid_size": 50.0, |
|||
"drawing": { |
|||
"dashed_lines_dash_length_ratio": 12.0, |
|||
"dashed_lines_gap_length_ratio": 3.0, |
|||
"default_line_thickness": 6.0, |
|||
"default_text_size": 50.0, |
|||
"field_names": [], |
|||
"intersheets_ref_own_page": false, |
|||
"intersheets_ref_prefix": "", |
|||
"intersheets_ref_short": false, |
|||
"intersheets_ref_show": false, |
|||
"intersheets_ref_suffix": "", |
|||
"junction_size_choice": 3, |
|||
"label_size_ratio": 0.375, |
|||
"operating_point_overlay_i_precision": 3, |
|||
"operating_point_overlay_i_range": "~A", |
|||
"operating_point_overlay_v_precision": 3, |
|||
"operating_point_overlay_v_range": "~V", |
|||
"overbar_offset_ratio": 1.23, |
|||
"pin_symbol_size": 25.0, |
|||
"text_offset_ratio": 0.15 |
|||
}, |
|||
"legacy_lib_dir": "", |
|||
"legacy_lib_list": [], |
|||
"meta": { |
|||
"version": 1 |
|||
}, |
|||
"net_format_name": "", |
|||
"ngspice": { |
|||
"fix_include_paths": true, |
|||
"fix_passive_vals": false, |
|||
"meta": { |
|||
"version": 0 |
|||
}, |
|||
"model_mode": 0, |
|||
"workbook_filename": "" |
|||
}, |
|||
"page_layout_descr_file": "empty.kicad_wks", |
|||
"plot_directory": "", |
|||
"space_save_all_events": true, |
|||
"spice_adjust_passive_values": false, |
|||
"spice_current_sheet_as_root": false, |
|||
"spice_external_command": "spice \"%I\"", |
|||
"spice_model_current_sheet_as_root": true, |
|||
"spice_save_all_currents": false, |
|||
"spice_save_all_dissipations": false, |
|||
"spice_save_all_voltages": false, |
|||
"subpart_first_id": 65, |
|||
"subpart_id_separator": 0 |
|||
}, |
|||
"sheets": [ |
|||
[ |
|||
"9e566840-a51e-4471-a3e7-2b665aaf43dc", |
|||
"Root" |
|||
], |
|||
[ |
|||
"3f8adf54-3826-4b3b-9b7c-b7e31dd15219", |
|||
"MIM 1 Connectors" |
|||
], |
|||
[ |
|||
"959ea2eb-ede7-4845-a5e0-f5d704ded284", |
|||
"USB C Power Delivery and USB connectors" |
|||
], |
|||
[ |
|||
"876907c5-4303-4331-b98b-edb1b9148224", |
|||
"Jupiter CM1 Connectors" |
|||
], |
|||
[ |
|||
"b65d545f-09b3-49cc-ba93-08687c0e9554", |
|||
"SD Card , JTAG Connectors, UUID EEPROM" |
|||
], |
|||
[ |
|||
"0836bfb4-6518-4cf8-bc77-6e6f74f1461f", |
|||
"Electrode Connector" |
|||
], |
|||
[ |
|||
"7178ddd0-9526-4df3-bf3a-3aae1a195dc4", |
|||
"System LED and Accelerometer" |
|||
], |
|||
[ |
|||
"f74cc5db-afe7-427c-9803-d67b8c3889e9", |
|||
"Battery Charger, Fuel Gauge, Regulators" |
|||
], |
|||
[ |
|||
"b57c4078-aa32-4f39-b920-da21bd34b003", |
|||
"User Connectors and Optoisolation" |
|||
], |
|||
[ |
|||
"1c95cdbc-eb19-4e2d-a613-dc22a92780a9", |
|||
"MIM 0 Connectors" |
|||
] |
|||
], |
|||
"text_variables": {} |
|||
} |
|||
@ -0,0 +1,330 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <filesystem>
|
|||
#include <iostream>
|
|||
#include <string>
|
|||
|
|||
#include <board_design_settings.h>
|
|||
#include <board.h>
|
|||
#include <boost/test/unit_test.hpp>
|
|||
#include <boost/uuid/uuid_generators.hpp>
|
|||
#include <boost/uuid/uuid_io.hpp>
|
|||
#include <boost/uuid/uuid.hpp>
|
|||
#include <drc/drc_item.h>
|
|||
#include <footprint.h>
|
|||
#include <pad.h>
|
|||
#include <pcb_edit_frame.h>
|
|||
#include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>
|
|||
#include <pcb_io/pcb_io_mgr.h>
|
|||
#include <pcb_io/pcb_io.h>
|
|||
#include <pcb_marker.h>
|
|||
#include <pcb_track.h>
|
|||
#include <pcbnew_utils/board_file_utils.h>
|
|||
#include <pcbnew_utils/board_test_utils.h>
|
|||
#include <project.h>
|
|||
#include <project/project_file.h>
|
|||
#include <qa_utils/wx_utils/unit_test_utils.h>
|
|||
#include <settings/settings_manager.h>
|
|||
#include <tool/tool_manager.h>
|
|||
#include <wx/string.h>
|
|||
|
|||
struct FileCleaner |
|||
{ |
|||
std::vector<wxString> m_files_to_delete; |
|||
|
|||
FileCleaner() = default; |
|||
~FileCleaner() |
|||
{ |
|||
for( const auto& f_path : m_files_to_delete ) |
|||
{ |
|||
if( wxFileName::Exists( f_path ) ) |
|||
{ |
|||
if( !wxRemoveFile( f_path ) ) |
|||
{ |
|||
BOOST_TEST_MESSAGE( "Warning: Failed to delete temporary file " << f_path ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void AddFile( const wxString& f_path ) { m_files_to_delete.push_back( f_path ); } |
|||
}; |
|||
|
|||
struct DRC_BASE_FIXTURE |
|||
{ |
|||
DRC_BASE_FIXTURE() : |
|||
m_settingsManager( true /* headless */ ) |
|||
{ |
|||
} |
|||
|
|||
std::string generate_uuid(); |
|||
bool SaveBoardToFile( BOARD* board, const wxString& filename ); |
|||
void loadBoardAndVerifyInitialExclusions( const wxString& aBoardNameStem, int aExpectedInitialExclusions ); |
|||
void createAndVerifyInitialExclusionMarkers(); |
|||
int createAndVerifyAdditionalUnconnectedExclusions( int aAdditionalExclusions, int aInitialExclusions ); |
|||
void runDrcOnBoard(); |
|||
void saveBoardAndProjectToTempFiles( const wxString& aBoardNameStem, FileCleaner& aCleaner, |
|||
wxString& aTempBoardFullPath, wxString& aTempProjectFullPath, |
|||
wxString& aTempBoardStemName ); |
|||
void reloadBoardAndVerifyExclusions( const wxString& aTempBoardStemName, int aExpectedExclusions ); |
|||
|
|||
|
|||
SETTINGS_MANAGER m_settingsManager; |
|||
std::unique_ptr<BOARD> m_board; |
|||
}; |
|||
|
|||
struct DRC_REGRESSION_TEST_FIXTURE : public DRC_BASE_FIXTURE |
|||
{ |
|||
DRC_REGRESSION_TEST_FIXTURE() : |
|||
DRC_BASE_FIXTURE() |
|||
{ |
|||
} |
|||
}; |
|||
|
|||
|
|||
struct DRC_UNCONNECTED_SAVE_FIXTURE : public DRC_BASE_FIXTURE |
|||
{ |
|||
DRC_UNCONNECTED_SAVE_FIXTURE() : |
|||
DRC_BASE_FIXTURE() |
|||
{ |
|||
m_board = std::make_unique<BOARD>(); |
|||
} |
|||
}; |
|||
|
|||
std::string DRC_BASE_FIXTURE::generate_uuid() |
|||
{ |
|||
boost::uuids::uuid uuid = boost::uuids::random_generator()(); |
|||
return boost::uuids::to_string( uuid ); |
|||
} |
|||
|
|||
void DRC_BASE_FIXTURE::loadBoardAndVerifyInitialExclusions( const wxString& aBoardNameStem, |
|||
int aExpectedInitialExclusions ) |
|||
{ |
|||
KI_TEST::LoadBoard( m_settingsManager, aBoardNameStem, m_board ); |
|||
BOOST_REQUIRE_MESSAGE( m_board, |
|||
"Could not load board " + aBoardNameStem ); // Ensure board loaded from test data directory
|
|||
PROJECT* pcb_project = m_board->GetProject(); |
|||
BOOST_REQUIRE_MESSAGE( pcb_project, "Get project pointer after initial loading." ); |
|||
|
|||
// Board test file comes with initial exclusions, check if they are preserved after loading
|
|||
const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); |
|||
size_t initialExclusionsCount = bds.m_DrcExclusions.size(); |
|||
size_t initialExclusionsCommentsCount = bds.m_DrcExclusionComments.size(); |
|||
BOOST_TEST_MESSAGE( "Initial DRC exclusions count: " << initialExclusionsCount ); |
|||
BOOST_CHECK_EQUAL( initialExclusionsCount, (size_t) aExpectedInitialExclusions ); |
|||
BOOST_TEST_MESSAGE( "Initial DRC exclusion comments count: " << initialExclusionsCommentsCount ); |
|||
BOOST_CHECK_EQUAL( initialExclusionsCommentsCount, (size_t) aExpectedInitialExclusions ); |
|||
} |
|||
|
|||
void DRC_BASE_FIXTURE::createAndVerifyInitialExclusionMarkers() |
|||
{ |
|||
const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); |
|||
std::vector<PCB_MARKER*> markers; |
|||
for( const wxString exclusion : bds.m_DrcExclusions ) |
|||
{ |
|||
PCB_MARKER* marker = PCB_MARKER::DeserializeFromString( exclusion ); |
|||
if( marker ) |
|||
{ |
|||
wxString comment = bds.m_DrcExclusionComments.at( exclusion ); |
|||
marker->SetExcluded( true, comment ); |
|||
markers.push_back( marker ); |
|||
m_board->Add( marker ); |
|||
} |
|||
} |
|||
size_t actualExclusionsCount = bds.m_DrcExclusions.size(); |
|||
size_t initialExclusionsCount = markers.size(); |
|||
BOOST_CHECK_EQUAL( actualExclusionsCount, initialExclusionsCount ); |
|||
BOOST_TEST_MESSAGE( std::string( "Actual DRC exclusions count: " ) + std::to_string( actualExclusionsCount ) |
|||
+ " after adding initial markers." ); |
|||
} |
|||
|
|||
int DRC_BASE_FIXTURE::createAndVerifyAdditionalUnconnectedExclusions( int aAdditionalExclusions, |
|||
int aInitialExclusions ) |
|||
{ |
|||
for( int i = 0; i < aAdditionalExclusions; ++i ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS ); |
|||
wxString id1 = wxString::Format( "12345678-1234-1234-1234-12345678%04d", i ); |
|||
wxString id2 = wxString::Format( "87654321-4321-4321-4321-87654321%04d", i ); |
|||
drcItem->SetItems( KIID( id1 ), KIID( id2 ) ); |
|||
|
|||
PCB_MARKER* marker = new PCB_MARKER( drcItem, VECTOR2I( 1000 * i, 1000 * i ) ); |
|||
m_board->Add( marker ); |
|||
|
|||
// Exclude odd-numbered markers
|
|||
if( i % 2 == 1 ) |
|||
{ |
|||
marker->SetExcluded( true, wxString::Format( "Exclusion %d", i ) ); |
|||
} |
|||
} |
|||
|
|||
// Store the new exclusion markers in the board
|
|||
m_board->RecordDRCExclusions(); |
|||
|
|||
// Verify the number of exclusions after adding unconnected items
|
|||
const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); |
|||
const int expectedExclusions = |
|||
aInitialExclusions + aAdditionalExclusions / 2; // Only odd-numbered markers are excluded
|
|||
size_t newActualExclusionsCount = bds.m_DrcExclusions.size(); |
|||
BOOST_TEST_MESSAGE( std::string( "New actual DRC exclusions count: " ) + std::to_string( newActualExclusionsCount ) |
|||
+ " after adding unconnected items." ); |
|||
BOOST_CHECK_EQUAL( newActualExclusionsCount, (size_t) expectedExclusions ); |
|||
return expectedExclusions; |
|||
} |
|||
|
|||
void DRC_BASE_FIXTURE::runDrcOnBoard() |
|||
{ |
|||
BOOST_TEST_MESSAGE( "Running DRC on board." ); |
|||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); |
|||
bds.m_DRCEngine->InitEngine( wxFileName() ); |
|||
bool runDRC = true; |
|||
bool runDRCOnAllLayers = true; |
|||
bds.m_DRCEngine->RunTests( EDA_UNITS::MM, runDRC, runDRCOnAllLayers ); |
|||
m_board->RecordDRCExclusions(); |
|||
m_board->ResolveDRCExclusions( false ); |
|||
BOOST_TEST_MESSAGE( "DRC done." ); |
|||
} |
|||
|
|||
void DRC_BASE_FIXTURE::saveBoardAndProjectToTempFiles( const wxString& aBoardNameStem, FileCleaner& aCleaner, |
|||
wxString& aTempBoardFullPath, wxString& aTempProjectFullPath, |
|||
wxString& aTempBoardStemName ) |
|||
{ |
|||
wxString tempPrefix = "tmp_test_drc_"; |
|||
aTempBoardStemName = tempPrefix + aBoardNameStem.ToStdString(); |
|||
aTempBoardFullPath = KI_TEST::GetPcbnewTestDataDir() + aTempBoardStemName + ".kicad_pcb"; |
|||
aCleaner.AddFile( aTempBoardFullPath ); |
|||
wxString tempProjectStemName = tempPrefix + aBoardNameStem.ToStdString(); |
|||
aTempProjectFullPath = KI_TEST::GetPcbnewTestDataDir() + aTempBoardStemName + ".kicad_pro"; |
|||
aCleaner.AddFile( aTempProjectFullPath ); |
|||
|
|||
bool boardSaved = SaveBoardToFile( m_board->GetBoard(), aTempBoardFullPath ); |
|||
BOOST_REQUIRE_MESSAGE( boardSaved, "Save board to temporary file: " << aTempBoardFullPath ); |
|||
|
|||
m_settingsManager.SaveProjectAs( aTempProjectFullPath, m_board->GetProject() ); |
|||
BOOST_REQUIRE_MESSAGE( wxFileName::Exists( aTempProjectFullPath ), |
|||
"Save project to temporary file: " << aTempProjectFullPath ); |
|||
} |
|||
|
|||
void DRC_BASE_FIXTURE::reloadBoardAndVerifyExclusions( const wxString& aTempBoardStemName, int aExpectedExclusions ) |
|||
{ |
|||
// clear the current board to ensure a fresh load
|
|||
m_board.reset(); |
|||
|
|||
KI_TEST::LoadBoard( m_settingsManager, aTempBoardStemName, m_board ); |
|||
BOOST_REQUIRE_MESSAGE( m_board, "Could not load board from tempfile:" |
|||
+ aTempBoardStemName ); // Ensure board loaded from test data directory
|
|||
PROJECT* pcb_project = m_board->GetProject(); |
|||
BOOST_REQUIRE_MESSAGE( pcb_project, "Get project pointer after initial loading." ); |
|||
|
|||
BOARD_DESIGN_SETTINGS& reloaded_bds = m_board->GetDesignSettings(); |
|||
size_t reloadedExclusionsCount = reloaded_bds.m_DrcExclusions.size(); |
|||
BOOST_TEST_MESSAGE( "Reloaded DRC exclusions count: " << reloadedExclusionsCount ); |
|||
BOOST_CHECK_EQUAL( reloadedExclusionsCount, aExpectedExclusions ); |
|||
} |
|||
|
|||
bool DRC_BASE_FIXTURE::SaveBoardToFile( BOARD* board, const wxString& filename ) |
|||
{ |
|||
try |
|||
{ |
|||
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) ); |
|||
pi->SaveBoard( filename, board, nullptr ); |
|||
return true; |
|||
} |
|||
catch( const IO_ERROR& error ) |
|||
{ |
|||
BOOST_TEST_MESSAGE( wxString::Format( "Save board to %s: %s", filename, error.What() ) ); |
|||
return false; |
|||
} |
|||
} |
|||
BOOST_FIXTURE_TEST_CASE( DRCUnconnectedExclusionsLoss, DRC_UNCONNECTED_SAVE_FIXTURE ) |
|||
{ |
|||
// Test that unconnected item exclusions are not lost after multiple DRC runs.
|
|||
// This test is expected to fail if the bug (issue17429) is present.
|
|||
|
|||
std::vector<std::pair<wxString, int>> tests = { |
|||
{ "issue17429", 10 }, // board name stem, expected initial exclusions
|
|||
}; |
|||
|
|||
const int NUM_DRC_RUNS = 2; |
|||
|
|||
for( const std::pair<wxString, int>& test_params : tests ) |
|||
{ |
|||
wxString boardNameStem = test_params.first; |
|||
int expectedInitialExclusions = test_params.second; |
|||
|
|||
loadBoardAndVerifyInitialExclusions( boardNameStem, expectedInitialExclusions ); |
|||
createAndVerifyInitialExclusionMarkers(); |
|||
const int additionalExclusions = 5; |
|||
int expectedExclusions = |
|||
createAndVerifyAdditionalUnconnectedExclusions( additionalExclusions, expectedInitialExclusions ); |
|||
|
|||
runDrcOnBoard(); |
|||
|
|||
const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); |
|||
BOOST_TEST_MESSAGE( std::string( "DRC exclusions count after DRC run: " ) + std::to_string( expectedExclusions ) |
|||
+ " after adding unconnected items." ); |
|||
BOOST_CHECK_EQUAL( bds.m_DrcExclusions.size(), expectedExclusions ); |
|||
} |
|||
} |
|||
|
|||
BOOST_FIXTURE_TEST_CASE( DRCUnconnectedItemsExclusionsSaveLoad, DRC_REGRESSION_TEST_FIXTURE ) |
|||
{ |
|||
namespace fs = std::filesystem; |
|||
|
|||
// Test that unconnected item exclusions are not lost during save/load.
|
|||
// This test is expected to fail if the bug (issue17429) is present.
|
|||
|
|||
std::vector<std::pair<wxString, int>> tests = { |
|||
{ "issue17429", 10 }, // board name stem, expected initial exclusions
|
|||
}; |
|||
|
|||
|
|||
for( const std::pair<wxString, int>& test_params : tests ) |
|||
{ |
|||
FileCleaner tempFileCleaner; |
|||
wxString boardNameStem = test_params.first; |
|||
int expectedInitialExclusions = test_params.second; |
|||
|
|||
loadBoardAndVerifyInitialExclusions( boardNameStem, expectedInitialExclusions ); |
|||
|
|||
wxString tempBoardFullPath, tempProjectFullPath, tempBoardStemName; |
|||
saveBoardAndProjectToTempFiles( boardNameStem, tempFileCleaner, tempBoardFullPath, tempProjectFullPath, |
|||
tempBoardStemName ); |
|||
|
|||
createAndVerifyInitialExclusionMarkers(); |
|||
|
|||
const int additionalExclusions = 5; |
|||
int expectedExclusions = |
|||
createAndVerifyAdditionalUnconnectedExclusions( additionalExclusions, expectedInitialExclusions ); |
|||
|
|||
bool boardSaved = SaveBoardToFile( m_board->GetBoard(), tempBoardFullPath ); |
|||
BOOST_REQUIRE_MESSAGE( boardSaved, "Save board to temporary file: " << tempBoardFullPath ); |
|||
|
|||
m_settingsManager.SaveProjectAs( tempProjectFullPath, m_board->GetProject() ); |
|||
BOOST_REQUIRE_MESSAGE( wxFileName::Exists( tempProjectFullPath ), |
|||
"Save project to temporary file: " << tempProjectFullPath ); |
|||
|
|||
reloadBoardAndVerifyExclusions( tempBoardStemName, expectedExclusions ); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue