Sort synthetic netclass rules by min clearance.

This way when 'A' and 'B' have different netclasses the largest will
fire (rather than just a random one of the two).

Fixes https://gitlab.com/kicad/code/kicad/issues/5926
This commit is contained in:
Jeff Young 2020-10-08 23:40:11 +01:00
parent 38cef95da9
commit 6550e01318
2 changed files with 44 additions and 24 deletions

View File

@ -179,37 +179,32 @@ void DRC_ENGINE::loadImplicitRules()
// 3) per-netclass rules // 3) per-netclass rules
int ruleCount = 0; std::vector<DRC_RULE*> netclassRules;
auto makeNetclassRule = auto makeNetclassRule =
[&]( const NETCLASSPTR& nc, bool isDefault ) [&]( const NETCLASSPTR& netclass, bool isDefault )
{ {
wxString className = nc->GetName(); // Only add rules for netclass clearances which are larger than board minimums.
wxString expr; // That way board minimums will still enforce a global minimum.
if( !isDefault ) if( netclass->GetClearance() > bds.m_MinClearance )
{ {
expr = wxString::Format( "A.NetClass == '%s' || B.NetClass == '%s'", DRC_RULE* rule = new DRC_RULE;
className, className ); wxString name = netclass->GetName();
}
DRC_RULE_CONDITION* inNetclassCondition = new DRC_RULE_CONDITION ( expr ); rule->m_Name = wxString::Format( _( "netclass '%s'" ), name );
DRC_RULE* nc_rule = createImplicitRule( wxString::Format( _( "netclass '%s'" ), rule->m_Implicit = true;
className ));
nc_rule->m_Condition = inNetclassCondition; wxString expr = wxString::Format( "A.NetClass == '%s'", name );
DRC_RULE_CONDITION* condition = new DRC_RULE_CONDITION( expr );
// Only add netclass clearances if they're larger than board minimums. That way rule->m_Condition = condition;
// board minimums will still enforce a global minimum. netclassRules.push_back( rule );
if( nc->GetClearance() > bds.m_MinClearance )
{
DRC_CONSTRAINT ncClearanceConstraint( DRC_CONSTRAINT_TYPE_CLEARANCE ); DRC_CONSTRAINT ncClearanceConstraint( DRC_CONSTRAINT_TYPE_CLEARANCE );
ncClearanceConstraint.Value().SetMin( nc->GetClearance() ); ncClearanceConstraint.Value().SetMin( netclass->GetClearance() );
nc_rule->AddConstraint( ncClearanceConstraint ); rule->AddConstraint( ncClearanceConstraint );
} }
ruleCount++;
}; };
m_board->SynchronizeNetsAndNetClasses(); m_board->SynchronizeNetsAndNetClasses();
@ -218,7 +213,20 @@ void DRC_ENGINE::loadImplicitRules()
for( const std::pair<const wxString, NETCLASSPTR>& netclass : bds.GetNetClasses() ) for( const std::pair<const wxString, NETCLASSPTR>& netclass : bds.GetNetClasses() )
makeNetclassRule( netclass.second, false ); makeNetclassRule( netclass.second, false );
ReportAux( wxString::Format( "Building %d implicit netclass rules", ruleCount ) ); // These have to be sorted by min clearance so the right one fires if 'A' and 'B' belong
// to two different netclasses.
std::sort( netclassRules.begin(), netclassRules.end(),
[]( DRC_RULE* lhs, DRC_RULE* rhs )
{
return lhs->m_Constraints[0].m_Value.Min()
< rhs->m_Constraints[0].m_Value.Min();
} );
for( DRC_RULE* netclassRule : netclassRules )
addRule( netclassRule );
ReportAux( wxString::Format( "Building %d implicit netclass rules", netclassRules.size() ) );
} }
static wxString formatConstraint( const DRC_CONSTRAINT& constraint ) static wxString formatConstraint( const DRC_CONSTRAINT& constraint )

View File

@ -271,12 +271,24 @@ int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
} }
else else
{ {
auto getItemDescription =
[&]( BOARD_ITEM* aItem )
{
wxString s = aItem->GetSelectMenuText( r->GetUnits() );
if( auto* cItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( aItem ) )
s += wxString::Format( _( " [netclass %s]" ), cItem->GetNetClassName() );
return s;
};
r->Report( _( "<h7>Clearance resolution for:</h7>" ) ); r->Report( _( "<h7>Clearance resolution for:</h7>" ) );
r->Report( wxString::Format( _( "<ul><li>Layer %s</li><li>%s</li><li>%s</li></ul>" ), r->Report( wxString::Format( wxT( "<ul><li>%s %s</li><li>%s</li><li>%s</li></ul>" ),
_( "Layer" ),
m_frame->GetBoard()->GetLayerName( layer ), m_frame->GetBoard()->GetLayerName( layer ),
a->GetSelectMenuText( r->GetUnits() ), getItemDescription( a ),
b->GetSelectMenuText( r->GetUnits() ) ) ); getItemDescription( b ) ) );
BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a ); BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b ); BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );