Add hasExactNetclass function to DRC condition language

Following changes to the `A.NetClass == '<netclass>'` semantics to
match on exact netclass name OR any constituent netclass names, we
can have conditions where constituent netclass constraints match
before the composite netclass constraints in the DRC engine. This
adds the functionality to match on the exact full netclass name, and
modifies the implicit netclass DRC rules to use this function in
their rule condition.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20797
This commit is contained in:
JamesJCode 2025-04-27 22:38:29 +01:00
parent e5e4d9b814
commit c25264528c
2 changed files with 42 additions and 1 deletions

View File

@ -255,7 +255,7 @@ void DRC_ENGINE::loadImplicitRules()
_( "netclass '%s'" ), nc->GetClearanceParent()->GetHumanReadableName() ); _( "netclass '%s'" ), nc->GetClearanceParent()->GetHumanReadableName() );
netclassRule->m_Implicit = true; netclassRule->m_Implicit = true;
expr = wxString::Format( wxT( "A.NetClass == '%s'" ), ncName ); expr = wxString::Format( wxT( "A.hasExactNetclass('%s')" ), ncName );
netclassRule->m_Condition = new DRC_RULE_CONDITION( expr ); netclassRule->m_Condition = new DRC_RULE_CONDITION( expr );
netclassClearanceRules.push_back( netclassRule ); netclassClearanceRules.push_back( netclassRule );

View File

@ -1300,6 +1300,46 @@ static void hasNetclassFunc( LIBEVAL::CONTEXT* aCtx, void* self )
} ); } );
} }
static void hasExactNetclassFunc( LIBEVAL::CONTEXT* aCtx, void* self )
{
LIBEVAL::VALUE* arg = aCtx->Pop();
LIBEVAL::VALUE* result = aCtx->AllocValue();
result->Set( 0.0 );
aCtx->Push( result );
if( !arg || arg->AsString().IsEmpty() )
{
if( aCtx->HasErrorCallback() )
aCtx->ReportError( _( "Missing netclass name argument to hasExactNetclass()" ) );
return;
}
PCBEXPR_VAR_REF* vref = static_cast<PCBEXPR_VAR_REF*>( self );
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
if( !item )
return;
result->SetDeferredEval(
[item, arg]() -> double
{
if( !item->IsConnected() )
return 0.0;
BOARD_CONNECTED_ITEM* bcItem = static_cast<BOARD_CONNECTED_ITEM*>( item );
NETCLASS* netclass = bcItem->GetEffectiveNetClass();
if( netclass->GetName() == arg->AsString() )
return 1.0;
return 0.0;
} );
}
static void hasComponentClassFunc( LIBEVAL::CONTEXT* aCtx, void* self ) static void hasComponentClassFunc( LIBEVAL::CONTEXT* aCtx, void* self )
{ {
LIBEVAL::VALUE* arg = aCtx->Pop(); LIBEVAL::VALUE* arg = aCtx->Pop();
@ -1387,5 +1427,6 @@ void PCBEXPR_BUILTIN_FUNCTIONS::RegisterAllFunctions()
RegisterFunc( wxT( "getField('x')" ), getFieldFunc ); RegisterFunc( wxT( "getField('x')" ), getFieldFunc );
RegisterFunc( wxT( "hasNetclass('x')" ), hasNetclassFunc ); RegisterFunc( wxT( "hasNetclass('x')" ), hasNetclassFunc );
RegisterFunc( wxT( "hasExactNetclass('x')" ), hasExactNetclassFunc );
RegisterFunc( wxT( "hasComponentClass('x')" ), hasComponentClassFunc ); RegisterFunc( wxT( "hasComponentClass('x')" ), hasComponentClassFunc );
} }