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:
parent
38cef95da9
commit
6550e01318
|
@ -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 )
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
Loading…
Reference in New Issue