24#include <boost/test/unit_test.hpp>
63 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
64 auto parsed = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( parsedRules[0] );
69 BOOST_CHECK_CLOSE( parsed->GetMinViaDiameter(), original.
GetMinViaDiameter(), 0.0001 );
70 BOOST_CHECK_CLOSE( parsed->GetMaxViaDiameter(), original.
GetMaxViaDiameter(), 0.0001 );
72 BOOST_CHECK_CLOSE( parsed->GetMinViaHoleSize(), original.
GetMinViaHoleSize(), 0.0001 );
73 BOOST_CHECK_CLOSE( parsed->GetMaxViaHoleSize(), original.
GetMaxViaHoleSize(), 0.0001 );
92 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
93 auto parsed = std::dynamic_pointer_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( parsedRules[0] );
98 BOOST_CHECK_CLOSE( parsed->GetMinRoutingWidth(), original.
GetMinRoutingWidth(), 0.0001 );
99 BOOST_CHECK_CLOSE( parsed->GetMaxRoutingWidth(), original.
GetMaxRoutingWidth(), 0.0001 );
105 std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>> rules;
107 auto rule1 = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( 0, 0,
"ViaRule", 0.5, 0.8, 0.6, 0.2, 0.4, 0.3 );
108 rule1->SetConstraintCode(
"via_style" );
109 rule1->SetRuleCondition(
"A.NetClass == 'Power'" );
110 rules.push_back( rule1 );
112 auto rule2 = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( 0, 0,
"TrackRule", 0.2, 0.3, 0.5 );
113 rule2->SetConstraintCode(
"track_width" );
114 rule2->SetRuleCondition(
"A.NetClass == 'Signal'" );
115 rules.push_back( rule2 );
117 wxString filename =
"test_rules.dru";
123 wxFFile file( filename );
126 file.ReadAll( &content );
129 BOOST_CHECK( content.Contains(
"(version 1)" ) );
130 BOOST_CHECK( content.Contains(
"(rule ViaRule" ) );
131 BOOST_CHECK( content.Contains(
"(constraint via_diameter" ) );
132 BOOST_CHECK( content.Contains(
"(constraint hole_size" ) );
133 BOOST_CHECK( content.Contains(
"(rule TrackRule" ) );
134 BOOST_CHECK( content.Contains(
"(constraint track_width" ) );
137 wxRemoveFile( filename );
143 std::vector<RULE_TREE_NODE> ruleTreeNodeDatas;
151 auto data = std::make_shared<DRC_RE_BASE_CONSTRAINT_DATA>( 1, 0,
"TestRule" );
152 data->SetConstraintCode(
"clearance" );
155 ruleTreeNodeDatas.push_back( node );
158 std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>> rules;
162 if( n.m_nodeType !=
RULE )
165 auto d = std::dynamic_pointer_cast<DRC_RE_BASE_CONSTRAINT_DATA>( n.m_nodeData );
168 rules.push_back( d );
176 auto rule = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, 0.2,
"ClearanceRule" );
177 rule->SetConstraintCode(
"clearance" );
183 wxString ruleText = rule->GenerateRule( ctx );
185 BOOST_CHECK( ruleText.Contains(
"(constraint clearance (min 0.2mm))" ) );
188 auto rule2 = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, 10,
"ViaCountRule" );
189 rule2->SetConstraintCode(
"via_count" );
190 ctx.
ruleName = rule2->GetRuleName();
193 ruleText = rule2->GenerateRule( ctx );
194 BOOST_CHECK( ruleText.Contains(
"(constraint via_count (max 10))" ) );
197 auto rule3 = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, 45,
"AngleRule" );
198 rule3->SetConstraintCode(
"track_angle" );
199 ctx.
ruleName = rule3->GetRuleName();
202 ruleText = rule3->GenerateRule( ctx );
203 BOOST_CHECK( ruleText.Contains(
"(constraint track_angle (min 45deg))" ) );
208 auto rule = std::make_shared<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( 0, 0,
true,
"DisallowTestRule" );
209 rule->SetConstraintCode(
"disallow" );
215 wxString ruleText = rule->GenerateRule( ctx );
217 BOOST_CHECK( ruleText.Contains(
"(constraint disallow)" ) );
220 auto rule2 = std::make_shared<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( 0, 0,
false,
"NoDisallowTestRule" );
221 rule2->SetConstraintCode(
"disallow" );
222 ctx.
ruleName = rule2->GetRuleName();
225 ruleText = rule2->GenerateRule( ctx );
226 BOOST_CHECK( ruleText.IsEmpty() );
233 "(rule \"Clearance Rule\"\n"
234 "\t(constraint clearance (min 0.2mm))\n"
235 "\t(condition \"A.NetClass == 'Power'\"))\n"
236 "(rule \"Via Style Rule\"\n"
237 "\t(constraint via_diameter (min 0.5mm))\n"
238 "\t(constraint hole_size (min 0.3mm))\n"
239 "\t(condition \"A.NetClass == 'Power'\"))\n";
243 BOOST_REQUIRE_EQUAL( parsedRules.size(), 2 );
246 auto clearanceRule = parsedRules[0];
251 auto numericData = std::dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( clearanceRule );
253 BOOST_CHECK_CLOSE( numericData->GetNumericInputValue(), 0.2, 0.0001 );
256 auto viaStyleRule = parsedRules[1];
260 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( viaStyleRule );
262 BOOST_CHECK_CLOSE( viaData->GetMinViaDiameter(), 0.5, 0.0001 );
263 BOOST_CHECK_CLOSE( viaData->GetMinViaHoleSize(), 0.3, 0.0001 );
269 bool parserCalled =
false;
271 [&](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>
276 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name );
277 data->SetConstraintCode(
"custom_clearance" );
283 wxString ruleText =
"(version 1) (rule \"Test Rule\" (constraint clearance (min 1.0mm)) (condition \"A.Type == 'Pad'\"))";
286 BOOST_CHECK( parserCalled );
287 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
297 BOOST_CHECK(
result.isValid );
298 BOOST_CHECK(
result.errors.empty() );
308 BOOST_CHECK( !
result.isValid );
309 BOOST_CHECK( !
result.errors.empty() );
312 bool foundMinMaxError =
false;
313 for(
const auto& error :
result.errors )
315 if( error.find(
"Minimum Via Diameter cannot be greater than Maximum Via Diameter" ) != std::string::npos )
316 foundMinMaxError =
true;
318 BOOST_CHECK( foundMinMaxError );
328 BOOST_CHECK( !
result.isValid );
329 BOOST_CHECK( !
result.errors.empty() );
332 bool foundNegativeError =
false;
333 for(
const auto& error :
result.errors )
335 if( error.find(
"must be greater than 0" ) != std::string::npos )
336 foundNegativeError =
true;
338 BOOST_CHECK( foundNegativeError );
345 [](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA> {
346 if( aRule->m_Name ==
"Test" )
347 return std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name +
"_1" );
353 [](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA> {
354 if( aRule->m_Name ==
"Test" )
355 return std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name +
"_2" );
359 wxString ruleText =
"(version 1) (rule \"Test\" (constraint clearance (min 1.0mm)))";
362 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
373 BOOST_CHECK(
result.isValid );
374 BOOST_CHECK(
result.errors.empty() );
384 BOOST_CHECK( !result1.
isValid );
385 BOOST_CHECK( !result1.
errors.empty() );
387 bool foundMinMaxError =
false;
389 for(
const auto& error : result1.
errors )
391 if( error.find(
"Minimum Length cannot be greater than Maximum Length" ) != std::string::npos )
392 foundMinMaxError =
true;
395 BOOST_CHECK( foundMinMaxError );
402 BOOST_CHECK( !result2.
isValid );
404 bool foundNegativeError =
false;
406 for(
const auto& error : result2.
errors )
408 if( error.find(
"must be greater than 0" ) != std::string::npos )
409 foundNegativeError =
true;
412 BOOST_CHECK( foundNegativeError );
423 BOOST_CHECK(
result.isValid );
424 BOOST_CHECK(
result.errors.empty() );
434 BOOST_CHECK( !result1.
isValid );
435 BOOST_CHECK( !result1.
errors.empty() );
437 bool foundWidthError =
false;
438 for(
const auto& error : result1.
errors )
440 if( error.find(
"Minimum Width cannot be greater than Maximum Width" ) != std::string::npos )
441 foundWidthError =
true;
443 BOOST_CHECK( foundWidthError );
450 BOOST_CHECK( !result2.
isValid );
452 bool foundNegativeError =
false;
453 for(
const auto& error : result2.
errors )
455 if( error.find(
"must be greater than 0" ) != std::string::npos )
456 foundNegativeError =
true;
458 BOOST_CHECK( foundNegativeError );
468 BOOST_CHECK( result1.
isValid );
469 BOOST_CHECK( result1.
errors.empty() );
476 BOOST_CHECK( result2.
isValid );
477 BOOST_CHECK( result2.
errors.empty() );
484 BOOST_CHECK( result3.
isValid );
485 BOOST_CHECK( result3.
errors.empty() );
495 BOOST_CHECK( !
result.isValid );
496 BOOST_CHECK( !
result.errors.empty() );
498 bool foundLayerError =
false;
499 for(
const auto& error :
result.errors )
501 if( error.find(
"At least one layer must be selected" ) != std::string::npos )
502 foundLayerError =
true;
504 BOOST_CHECK( foundLayerError );
513 BOOST_CHECK(
result.isValid );
514 BOOST_CHECK(
result.errors.empty() );
523 BOOST_CHECK( !
result.isValid );
524 BOOST_CHECK( !
result.errors.empty() );
527 bool foundError =
false;
528 for(
const auto& error :
result.errors )
530 if( error.find(
"must be greater than 0" ) != std::string::npos )
533 BOOST_CHECK( foundError );
542 BOOST_CHECK(
result.isValid );
543 BOOST_CHECK(
result.errors.empty() );
553 BOOST_CHECK( !
result.isValid );
554 BOOST_CHECK( !
result.errors.empty() );
557 bool foundMinMaxError =
false;
558 for(
const auto& error :
result.errors )
560 if( error.find(
"Minimum Routing Width cannot be greater than Maximum Routing Width" ) != std::string::npos )
561 foundMinMaxError =
true;
563 BOOST_CHECK( foundMinMaxError );
573 BOOST_CHECK( result1.
isValid );
574 BOOST_CHECK( result1.
errors.empty() );
581 BOOST_CHECK( result2.
isValid );
582 BOOST_CHECK( result2.
errors.empty() );
589 BOOST_CHECK( result3.
isValid );
590 BOOST_CHECK( result3.
errors.empty() );
597 BOOST_CHECK( result4.
isValid );
598 BOOST_CHECK( result4.
errors.empty() );
608 BOOST_CHECK( !
result.isValid );
609 BOOST_CHECK( !
result.errors.empty() );
611 bool foundOrientationError =
false;
612 for(
const auto& error :
result.errors )
614 if( error.find(
"At least one orientation must be selected" ) != std::string::npos )
615 foundOrientationError =
true;
617 BOOST_CHECK( foundOrientationError );
627 BOOST_CHECK( resultTrue.
isValid );
628 BOOST_CHECK( resultTrue.
errors.empty() );
635 BOOST_CHECK( resultFalse.
isValid );
636 BOOST_CHECK( resultFalse.
errors.empty() );
646 BOOST_CHECK(
result.isValid );
647 BOOST_CHECK(
result.errors.empty() );
657 BOOST_CHECK( !result1.
isValid );
658 BOOST_CHECK( !result1.
errors.empty() );
660 bool foundHeightError =
false;
661 for(
const auto& error : result1.
errors )
663 if( error.find(
"Minimum Text Height must be greater than 0" ) != std::string::npos )
664 foundHeightError =
true;
666 BOOST_CHECK( foundHeightError );
673 BOOST_CHECK( !result2.
isValid );
675 bool foundThicknessError =
false;
676 for(
const auto& error : result2.
errors )
678 if( error.find(
"Minimum Text Thickness must be greater than 0" ) != std::string::npos )
679 foundThicknessError =
true;
681 BOOST_CHECK( foundThicknessError );
688 BOOST_CHECK( !result3.
isValid );
695 data.
SetRuleText(
"(constraint clearance (min 0.2mm))" );
699 BOOST_CHECK(
result.isValid );
700 BOOST_CHECK(
result.errors.empty() );
710 BOOST_CHECK( !
result.isValid );
711 BOOST_CHECK( !
result.errors.empty() );
714 bool foundEmptyError =
false;
715 for(
const auto& error :
result.errors )
717 if( error.find(
"Rule text cannot be empty" ) != std::string::npos )
718 foundEmptyError =
true;
720 BOOST_CHECK( foundEmptyError );
746 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
748 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
758 DRC_RULE rule(
"ViaDiameterOnlyRule" );
765 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
767 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
791 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
793 BOOST_REQUIRE_EQUAL( matches.size(), 2 );
823 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
825 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
834 DRC_RULE rule(
"DiffPairWithUncoupledRule" );
849 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
851 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
862 DRC_RULE rule(
"TrackWidthOnlyRule" );
871 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
873 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
892 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
894 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
911 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
913 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
921 DRC_RULE rule(
"MatchedLengthRule" );
934 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
936 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
939 BOOST_CHECK( matches[0].claimedConstraints.count(
SKEW_CONSTRAINT ) > 0 );
948 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
993 "(rule \"Via Test\"\n"
994 " (constraint via_diameter (min 0.5mm) (opt 0.6mm) (max 0.8mm))\n"
995 " (constraint hole_size (min 0.2mm) (opt 0.3mm) (max 0.4mm)))";
998 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1000 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1004 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( entries[0].constraintData );
1007 BOOST_CHECK_CLOSE( viaData->GetMinViaDiameter(), 0.5, 0.0001 );
1008 BOOST_CHECK_CLOSE( viaData->GetPreferredViaDiameter(), 0.6, 0.0001 );
1009 BOOST_CHECK_CLOSE( viaData->GetMaxViaDiameter(), 0.8, 0.0001 );
1010 BOOST_CHECK_CLOSE( viaData->GetMinViaHoleSize(), 0.2, 0.0001 );
1011 BOOST_CHECK_CLOSE( viaData->GetPreferredViaHoleSize(), 0.3, 0.0001 );
1012 BOOST_CHECK_CLOSE( viaData->GetMaxViaHoleSize(), 0.4, 0.0001 );
1020 "(rule \"Track Test\"\n"
1021 " (constraint track_width (min 0.2mm) (opt 0.25mm) (max 0.3mm)))";
1024 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1026 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1030 auto trackData = std::dynamic_pointer_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( entries[0].constraintData );
1033 BOOST_CHECK_CLOSE( trackData->GetMinRoutingWidth(), 0.2, 0.0001 );
1034 BOOST_CHECK_CLOSE( trackData->GetPreferredRoutingWidth(), 0.25, 0.0001 );
1035 BOOST_CHECK_CLOSE( trackData->GetMaxRoutingWidth(), 0.3, 0.0001 );
1043 "(rule \"Diff Pair Test\"\n"
1044 " (constraint track_width (min 0.2mm) (opt 0.25mm) (max 0.3mm))\n"
1045 " (constraint diff_pair_gap (min 0.1mm) (opt 0.15mm) (max 0.2mm))\n"
1046 " (constraint diff_pair_uncoupled (max 5mm)))";
1049 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1051 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1054 auto dpData = std::dynamic_pointer_cast<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1057 BOOST_CHECK_CLOSE( dpData->GetMinWidth(), 0.2, 0.0001 );
1058 BOOST_CHECK_CLOSE( dpData->GetPreferredWidth(), 0.25, 0.0001 );
1059 BOOST_CHECK_CLOSE( dpData->GetMaxWidth(), 0.3, 0.0001 );
1060 BOOST_CHECK_CLOSE( dpData->GetMinGap(), 0.1, 0.0001 );
1061 BOOST_CHECK_CLOSE( dpData->GetPreferredGap(), 0.15, 0.0001 );
1062 BOOST_CHECK_CLOSE( dpData->GetMaxGap(), 0.2, 0.0001 );
1063 BOOST_CHECK_CLOSE( dpData->GetMaxUncoupledLength(), 5.0, 0.0001 );
1071 "(rule \"Split Test\"\n"
1072 " (constraint via_diameter (min 0.5mm))\n"
1073 " (constraint hole_size (min 0.2mm))\n"
1074 " (constraint clearance (min 0.15mm)))";
1077 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1079 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1089 auto numericData = std::dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( entries[1].constraintData );
1091 BOOST_CHECK_CLOSE( numericData->GetNumericInputValue(), 0.15, 0.0001 );
1101 "(rule \"clearance_under_fpga\"\n"
1102 " (constraint clearance (min 0.1mm))\n"
1103 " (constraint hole_size (min 0.2mm))\n"
1104 " (constraint via_diameter (min 0.4mm))\n"
1105 " (condition \"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')\"))";
1108 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1111 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1116 BOOST_CHECK_EQUAL( entries[0].condition,
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')" );
1121 BOOST_CHECK_EQUAL( entries[1].condition,
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')" );
1124 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( entries[0].constraintData );
1126 BOOST_CHECK_CLOSE( viaData->GetMinViaDiameter(), 0.4, 0.0001 );
1127 BOOST_CHECK_CLOSE( viaData->GetMinViaHoleSize(), 0.2, 0.0001 );
1130 auto clearanceData = std::dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( entries[1].constraintData );
1132 BOOST_CHECK_CLOSE( clearanceData->GetNumericInputValue(), 0.1, 0.0001 );
1140 "(rule \"Text Test\"\n"
1141 " (constraint text_height (min 1mm))\n"
1142 " (constraint text_thickness (min 0.15mm)))";
1145 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1147 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1150 auto textData = std::dynamic_pointer_cast<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>( entries[0].constraintData );
1153 BOOST_CHECK_CLOSE( textData->GetMinTextHeight(), 1.0, 0.0001 );
1154 BOOST_CHECK_CLOSE( textData->GetMinTextThickness(), 0.15, 0.0001 );
1162 "(rule \"Length Test\"\n"
1163 " (constraint length (min 10mm) (opt 30mm) (max 50mm)))";
1166 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1168 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1172 auto lengthData = dynamic_pointer_cast<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>( entries[0].constraintData );
1174 BOOST_CHECK_CLOSE( lengthData->GetMinimumLength(), 10.0, 0.0001 );
1175 BOOST_CHECK_CLOSE( lengthData->GetOptimumLength(), 30.0, 0.0001 );
1176 BOOST_CHECK_CLOSE( lengthData->GetMaximumLength(), 50.0, 0.0001 );
1184 "(rule \"DP Length Match\"\n"
1185 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1186 " (constraint skew (max 1mm)))";
1189 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1191 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1196 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1199 BOOST_CHECK_CLOSE( matchedData->GetMinimumLength(), 10.0, 0.0001 );
1200 BOOST_CHECK_CLOSE( matchedData->GetOptimumLength(), 30.0, 0.0001 );
1201 BOOST_CHECK_CLOSE( matchedData->GetMaximumLength(), 50.0, 0.0001 );
1202 BOOST_CHECK_CLOSE( matchedData->GetMaxSkew(), 1.0, 0.0001 );
1210 "(rule \"DP Match RT\"\n"
1211 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1212 " (constraint skew (max 2.5mm)))";
1215 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1217 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1218 entries[0].wasEdited =
true;
1223 BOOST_CHECK( savedText.Contains(
"length" ) );
1224 BOOST_CHECK( savedText.Contains(
"skew" ) );
1225 BOOST_CHECK( savedText.Contains(
"2.5mm" ) );
1227 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloaded = loader.
LoadFromString( savedText );
1229 BOOST_REQUIRE_EQUAL( reloaded.size(), 1 );
1233 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( reloaded[0].constraintData );
1236 BOOST_CHECK_CLOSE( reloadedData->GetMaxSkew(), 2.5, 0.0001 );
1237 BOOST_CHECK_CLOSE( reloadedData->GetMinimumLength(), 10.0, 0.0001 );
1238 BOOST_CHECK_CLOSE( reloadedData->GetOptimumLength(), 30.0, 0.0001 );
1239 BOOST_CHECK_CLOSE( reloadedData->GetMaximumLength(), 50.0, 0.0001 );
1247 "(rule \"Conditional Test\"\n"
1248 " (condition \"A.NetClass == 'Power'\")\n"
1249 " (constraint clearance (min 0.3mm)))";
1252 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1254 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1257 BOOST_CHECK_EQUAL( entries[0].constraintData->GetRuleCondition(),
"A.NetClass == 'Power'" );
1265 "(rule \"Rule A\"\n"
1266 " (constraint clearance (min 0.2mm)))\n"
1267 "(rule \"Rule B\"\n"
1268 " (constraint track_width (min 0.15mm)))\n"
1269 "(rule \"Rule C\"\n"
1270 " (constraint via_diameter (min 0.5mm))\n"
1271 " (constraint hole_size (min 0.3mm)))";
1274 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1276 BOOST_REQUIRE_EQUAL( entries.size(), 3 );
1293 "(rule \"Empty Rule\")";
1296 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1298 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1306 wxString ruleText =
"not valid rule text at all";
1309 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1319 "(rule \"Edge Clearance\"\n"
1320 " (constraint edge_clearance (min 0.5mm)))\n"
1321 "(rule \"Hole Clearance\"\n"
1322 " (constraint hole_clearance (min 0.3mm)))\n"
1323 "(rule \"Courtyard\"\n"
1324 " (constraint courtyard_clearance (min 0.25mm)))";
1327 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1329 BOOST_REQUIRE_EQUAL( entries.size(), 3 );
1349 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1350 numericData->SetRuleName(
"TestClearance" );
1351 numericData->SetConstraintCode(
"clearance" );
1352 numericData->SetNumericInputValue( 0.2 );
1356 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1359 BOOST_CHECK(
result.Contains(
"(version 1)" ) );
1360 BOOST_CHECK(
result.Contains(
"TestClearance" ) );
1361 BOOST_CHECK(
result.Contains(
"clearance" ) );
1370 entry.
originalRuleText =
"(rule \"Preserved Rule\"\n\t(constraint clearance (min 0.5mm)))";
1373 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1374 numericData->SetRuleName(
"Preserved Rule" );
1375 numericData->SetConstraintCode(
"clearance" );
1376 numericData->SetNumericInputValue( 0.5 );
1380 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1392 entry.
originalRuleText =
"(rule \"EditedRule\"\n\t(constraint clearance (min 0.5mm)))";
1395 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1396 numericData->SetRuleName(
"EditedRule" );
1397 numericData->SetConstraintCode(
"clearance" );
1398 numericData->SetNumericInputValue( 0.3 );
1402 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1406 BOOST_CHECK( !
result.Contains(
"0.5mm" ) );
1407 BOOST_CHECK(
result.Contains(
"EditedRule" ) );
1417 auto viaData = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>();
1418 viaData->SetRuleName(
"ViaTest" );
1419 viaData->SetMinViaDiameter( 0.5 );
1420 viaData->SetPreferredViaDiameter( 0.6 );
1421 viaData->SetMaxViaDiameter( 0.8 );
1422 viaData->SetMinViaHoleSize( 0.2 );
1423 viaData->SetPreferredViaHoleSize( 0.3 );
1424 viaData->SetMaxViaHoleSize( 0.4 );
1429 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1432 BOOST_CHECK(
result.Contains(
"ViaTest" ) );
1433 BOOST_CHECK(
result.Contains(
"via_diameter" ) );
1434 BOOST_CHECK(
result.Contains(
"hole_size" ) );
1440 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
1445 auto data1 = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1446 data1->SetRuleName(
"RuleA" );
1447 data1->SetConstraintCode(
"clearance" );
1448 data1->SetNumericInputValue( 0.2 );
1451 entries.push_back( entry1 );
1456 auto data2 = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>();
1457 data2->SetRuleName(
"RuleB" );
1458 data2->SetMinRoutingWidth( 0.15 );
1459 data2->SetPreferredRoutingWidth( 0.2 );
1460 data2->SetMaxRoutingWidth( 0.3 );
1463 entries.push_back( entry2 );
1469 BOOST_CHECK(
result.Contains(
"RuleA" ) );
1470 BOOST_CHECK(
result.Contains(
"RuleB" ) );
1473 size_t posA =
result.Find(
"RuleA" );
1474 size_t posB =
result.Find(
"RuleB" );
1475 BOOST_CHECK( posA < posB );
1483 entry.
ruleName =
"ConditionalRule";
1484 entry.
condition =
"A.NetClass == 'Power'";
1486 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1487 numericData->SetRuleName(
"ConditionalRule" );
1488 numericData->SetConstraintCode(
"clearance" );
1489 numericData->SetRuleCondition(
"A.NetClass == 'Power'" );
1490 numericData->SetNumericInputValue( 0.3 );
1495 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1498 BOOST_CHECK(
result.Contains(
"ConditionalRule" ) );
1499 BOOST_CHECK(
result.Contains(
"condition" ) );
1500 BOOST_CHECK(
result.Contains(
"Power" ) );
1507 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
1510 BOOST_CHECK(
result.Contains(
"(version 1)" ) );
1525 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1529 BOOST_CHECK(
result.Contains(
"(version 1)" ) );
1530 BOOST_CHECK( !
result.Contains(
"Null Data Rule" ) );
1536 wxString originalText =
1538 "(rule \"RoundTripTest\"\n"
1539 " (constraint clearance (min 0.25mm)))";
1542 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
1544 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1548 entries[0].wasEdited =
true;
1555 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
1557 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 1 );
1569 auto dpData = std::make_shared<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>();
1570 dpData->SetRuleName(
"DiffPairTest" );
1571 dpData->SetMinWidth( 0.2 );
1572 dpData->SetPreferredWidth( 0.25 );
1573 dpData->SetMaxWidth( 0.3 );
1574 dpData->SetMinGap( 0.1 );
1575 dpData->SetPreferredGap( 0.15 );
1576 dpData->SetMaxGap( 0.2 );
1577 dpData->SetMaxUncoupledLength( 5.0 );
1582 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1585 BOOST_CHECK(
result.Contains(
"DiffPairTest" ) );
1586 BOOST_CHECK(
result.Contains(
"track_width" ) );
1587 BOOST_CHECK(
result.Contains(
"diff_pair_gap" ) );
1600 "(rule \"PTH to Track Clearance\"\n"
1601 " (constraint hole_clearance (min 1.0mm))\n"
1602 " (condition \"A.Type == 'Pad' && A.Pad_Type == 'Through-hole' && B.Type =='Track'\"))\n"
1603 "(rule \"Max Drill Hole Size Mechanical\"\n"
1604 " (constraint hole (max 2.0mm))\n"
1605 " (condition \"A.Type == 'Pad'\"))";
1608 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1610 BOOST_REQUIRE_GE( entries.size(), 2 );
1615 BOOST_CHECK( !entries[0].condition.IsEmpty() );
1627 "(rule board_edge\n"
1628 " (constraint edge_clearance (min 1mm))\n"
1629 " (condition \"A.memberOf('board_edge')\")\n"
1630 " (severity ignore))";
1633 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1635 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1646 "(rule high_current_netclass\n"
1647 " (constraint connection_width (min 0.16mm))\n"
1648 " (condition \"A.NetClass == 'High_current'\"))\n"
1649 "(rule high_current_area\n"
1650 " (constraint connection_width (min 0.16mm))\n"
1651 " (condition \"A.insideArea('high_current')\"))";
1654 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1656 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1663 BOOST_CHECK( !entries[0].condition.IsEmpty() );
1664 BOOST_CHECK( !entries[1].condition.IsEmpty() );
1671 wxString originalText =
1673 "(rule ClearanceRule\n"
1674 " (constraint clearance (min 0.2mm))\n"
1675 " (condition \"A.NetClass == 'Power'\"))\n"
1676 "(rule TrackWidthRule\n"
1677 " (constraint track_width (min 0.15mm) (opt 0.2mm) (max 0.3mm)))";
1680 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
1682 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1685 for(
auto& entry : entries )
1686 entry.wasEdited =
true;
1693 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
1695 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 2 );
1709 wxString originalText =
1711 "(rule \"Via Style\"\n"
1712 " (constraint via_diameter (min 0.5mm) (opt 0.6mm) (max 0.8mm))\n"
1713 " (constraint hole_size (min 0.2mm) (opt 0.3mm) (max 0.4mm)))";
1716 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
1718 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1721 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( entries[0].constraintData );
1724 double originalMinDia = viaData->GetMinViaDiameter();
1725 double originalMinHole = viaData->GetMinViaHoleSize();
1728 entries[0].wasEdited =
true;
1733 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
1735 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 1 );
1738 auto reloadedViaData =
1739 std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( reloadedEntries[0].constraintData );
1742 BOOST_CHECK_CLOSE( reloadedViaData->GetMinViaDiameter(), originalMinDia, 0.0001 );
1743 BOOST_CHECK_CLOSE( reloadedViaData->GetMinViaHoleSize(), originalMinHole, 0.0001 );
1751 "(rule \"Rule A\"\n"
1752 " (constraint clearance (min 0.2mm)))\n"
1753 "(rule \"Rule B\"\n"
1754 " (constraint via_diameter (min 0.5mm))\n"
1755 " (constraint hole_size (min 0.2mm))\n"
1756 " (constraint track_width (min 0.15mm)))\n"
1757 "(rule \"Rule C\"\n"
1758 " (constraint edge_clearance (min 0.3mm)))";
1761 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1764 BOOST_REQUIRE_GE( entries.size(), 4 );
1767 int ruleACount = 0, ruleBCount = 0, ruleCCount = 0;
1769 for(
const auto& entry : entries )
1771 if( entry.ruleName ==
"Rule A" )
1773 else if( entry.ruleName ==
"Rule B" )
1775 else if( entry.ruleName ==
"Rule C" )
1780 BOOST_CHECK_GE( ruleBCount, 2 );
1784 int lastAIndex = -1, firstBIndex = entries.size(), lastBIndex = -1, firstCIndex = entries.size();
1786 for(
size_t i = 0; i < entries.size(); i++ )
1788 if( entries[i].ruleName ==
"Rule A" )
1790 else if( entries[i].ruleName ==
"Rule B" )
1792 if( (
int)i < firstBIndex )
1797 else if( entries[i].ruleName ==
"Rule C" )
1799 if( (
int)i < firstCIndex )
1804 BOOST_CHECK( lastAIndex < firstBIndex );
1805 BOOST_CHECK( lastBIndex < firstCIndex );
1817 wxString expr =
"A.NetName == 'VCC'";
1820 BOOST_CHECK( !expr.IsEmpty() );
1821 BOOST_CHECK( expr.Contains(
"NetName" ) );
1822 BOOST_CHECK( expr.Contains(
"VCC" ) );
1828 wxString expr =
"A.NetName == 'VCC' && B.NetClass == 'Power'";
1831 BOOST_CHECK( expr.Contains(
"&&" ) );
1832 BOOST_CHECK( expr.Contains(
"NetName" ) );
1833 BOOST_CHECK( expr.Contains(
"NetClass" ) );
1839 wxString expr =
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')";
1842 BOOST_CHECK( expr.Contains(
"||" ) );
1843 BOOST_CHECK( expr.Contains(
"intersectsArea" ) );
1849 wxString expr =
"A.NetClass == 'Power' && !A.intersectsArea('NoRouting')";
1852 BOOST_CHECK( expr.Contains(
"&&" ) );
1853 BOOST_CHECK( expr.Contains(
"!" ) );
1859 wxString expr =
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')";
1862 BOOST_CHECK( expr.Contains(
"||" ) );
1863 BOOST_CHECK( expr.Contains(
"underFPGA" ) );
1864 BOOST_CHECK( expr.Contains(
"underDDR" ) );
1870 while( ( pos = expr.find(
"||", pos ) ) != wxString::npos )
1893 for(
KICAD_T type : excludedTypes )
1900 BOOST_CHECK(
true );
1904 BOOST_FAIL(
"Excluded type not handled in filter" );
1909 for(
KICAD_T type : includedTypes )
1916 BOOST_FAIL(
"Included type incorrectly matched by filter" );
1920 BOOST_CHECK(
true );
MINOPTMAX< int > & Value()
Maps DRC rule constraints to appropriate editor panels.
DRC_RULE_EDITOR_CONSTRAINT_NAME GetPanelForConstraint(DRC_CONSTRAINT_T aConstraintType)
Get the panel type for a single constraint.
bool CanPanelLoad(DRC_RULE_EDITOR_CONSTRAINT_NAME aPanel, const std::set< DRC_CONSTRAINT_T > &aConstraints)
Check if a specific panel type can load a set of constraints.
std::vector< DRC_PANEL_MATCH > MatchRule(const DRC_RULE &aRule)
Match a DRC rule to one or more panel types.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
wxString GetConstraintCode() const
void SetConstraintCode(wxString aCode)
wxString GetRuleCondition()
void SetRuleCondition(wxString aRuleCondition)
Simple constraint data object used by custom rules.
void SetRuleText(const wxString &aText)
VALIDATION_RESULT Validate() const override
Validates the constraint data.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
double GetMinRoutingWidth()
wxString GenerateRule(const RULE_GENERATION_CONTEXT &aContext) override
double GetMaxRoutingWidth()
VALIDATION_RESULT Validate() const override
Validates the constraint data.
double GetPreferredRoutingWidth()
double GetPreferredViaDiameter()
double GetMaxViaDiameter()
double GetMinViaHoleSize()
double GetMinViaDiameter()
double GetPreferredViaHoleSize()
double GetMaxViaHoleSize()
VALIDATION_RESULT Validate() const override
Validates the constraint data.
wxString GenerateRule(const RULE_GENERATION_CONTEXT &aContext) override
static bool SaveRules(const wxString &aFilename, const std::vector< std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > > &aRules, const BOARD *aBoard)
static void RegisterRuleConverter(RuleConverter aConverter)
static std::vector< std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > > ParseRules(const wxString &aRules)
Loads DRC rules from .kicad_dru files and converts them to panel entries.
std::vector< DRC_RE_LOADED_PANEL_ENTRY > LoadFromString(const wxString &aRulesText)
Load rules from a text string.
Saves DRC panel entries back to .kicad_dru files.
wxString GenerateRulesText(const std::vector< DRC_RE_LOADED_PANEL_ENTRY > &aEntries, const BOARD *aBoard=nullptr)
Generate rule text from panel entries.
void AddConstraint(DRC_CONSTRAINT &aConstraint)
wxString GetRuleName()
Get the name of the rule.
@ VIA_DIAMETER_CONSTRAINT
@ DIFF_PAIR_GAP_CONSTRAINT
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ TEXT_THICKNESS_CONSTRAINT
@ MAX_UNCOUPLED_CONSTRAINT
@ HOLE_CLEARANCE_CONSTRAINT
@ HOLE_TO_HOLE_CONSTRAINT
@ MINIMUM_CONNECTION_WIDTH
@ MINIMUM_TEXT_HEIGHT_AND_THICKNESS
@ COPPER_TO_HOLE_CLEARANCE
@ MATCHED_LENGTH_DIFF_PAIR
@ COPPER_TO_EDGE_CLEARANCE
Represents a rule loaded from a .kicad_dru file and mapped to a panel.
wxString originalRuleText
std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > constraintData
DRC_RULE_EDITOR_CONSTRAINT_NAME panelType
wxString conditionExpression
Structure representing a node in a rule tree, collection of this used for building the rule tree.
std::shared_ptr< RULE_EDITOR_DATA_BASE > m_nodeData
Result of a validation operation.
std::vector< wxString > errors
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_CASE(RoundTripViaStyle)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)