Add a bunch more inspections for rule resolution.

This commit is contained in:
Jeff Young 2022-04-15 22:09:35 +01:00
parent 4a63614a4a
commit 7f3a75bccd
3 changed files with 273 additions and 41 deletions

View File

@ -543,10 +543,17 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
} }
if( rcItem->GetErrorCode() == DRCE_CLEARANCE if( rcItem->GetErrorCode() == DRCE_CLEARANCE
|| rcItem->GetErrorCode() == DRCE_EDGE_CLEARANCE ) || rcItem->GetErrorCode() == DRCE_EDGE_CLEARANCE
|| rcItem->GetErrorCode() == DRCE_HOLE_CLEARANCE )
{ {
menu.Append( 3, _( "Run clearance resolution tool..." ) ); menu.Append( 3, _( "Run clearance resolution tool..." ) );
} }
else if( rcItem->GetErrorCode() == DRCE_TEXT_HEIGHT
|| rcItem->GetErrorCode() == DRCE_TEXT_THICKNESS
|| rcItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG )
{
menu.Append( 3, _( "Run constraints resolution tool..." ) );
}
menu.AppendSeparator(); menu.AppendSeparator();

View File

@ -186,15 +186,18 @@ void DRC_ENGINE::loadImplicitRules()
rule = createImplicitRule( _( "board setup constraints silk" ) ); rule = createImplicitRule( _( "board setup constraints silk" ) );
rule->m_LayerCondition = LSET( 2, F_SilkS, B_SilkS ); rule->m_LayerCondition = LSET( 2, F_SilkS, B_SilkS );
DRC_CONSTRAINT silkClearanceConstraint( SILK_CLEARANCE_CONSTRAINT ); DRC_CONSTRAINT silkClearanceConstraint( SILK_CLEARANCE_CONSTRAINT );
silkClearanceConstraint.Value().SetMin( bds.m_SilkClearance ); silkClearanceConstraint.Value().SetMin( bds.m_SilkClearance );
rule->AddConstraint( silkClearanceConstraint ); rule->AddConstraint( silkClearanceConstraint );
rule = createImplicitRule( _( "board setup constraints silk text height" ) );
rule->m_LayerCondition = LSET( 2, F_SilkS, B_SilkS );
DRC_CONSTRAINT silkTextHeightConstraint( TEXT_HEIGHT_CONSTRAINT ); DRC_CONSTRAINT silkTextHeightConstraint( TEXT_HEIGHT_CONSTRAINT );
silkTextHeightConstraint.Value().SetMin( bds.m_MinSilkTextHeight ); silkTextHeightConstraint.Value().SetMin( bds.m_MinSilkTextHeight );
rule->AddConstraint( silkTextHeightConstraint ); rule->AddConstraint( silkTextHeightConstraint );
rule = createImplicitRule( _( "board setup constraints silk text thickness" ) );
rule->m_LayerCondition = LSET( 2, F_SilkS, B_SilkS );
DRC_CONSTRAINT silkTextThicknessConstraint( TEXT_THICKNESS_CONSTRAINT ); DRC_CONSTRAINT silkTextThicknessConstraint( TEXT_THICKNESS_CONSTRAINT );
silkTextThicknessConstraint.Value().SetMin( bds.m_MinSilkTextThickness ); silkTextThicknessConstraint.Value().SetMin( bds.m_MinSilkTextThickness );
rule->AddConstraint( silkTextThicknessConstraint ); rule->AddConstraint( silkTextThicknessConstraint );
@ -920,6 +923,8 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
case SILK_CLEARANCE_CONSTRAINT: case SILK_CLEARANCE_CONSTRAINT:
case HOLE_CLEARANCE_CONSTRAINT: case HOLE_CLEARANCE_CONSTRAINT:
case EDGE_CLEARANCE_CONSTRAINT: case EDGE_CLEARANCE_CONSTRAINT:
case MECHANICAL_CLEARANCE_CONSTRAINT:
case MECHANICAL_HOLE_CLEARANCE_CONSTRAINT:
{ {
int val = c->constraint.m_Value.Min(); int val = c->constraint.m_Value.Min();
REPORT( wxString::Format( _( "Checking %s clearance: %s." ), REPORT( wxString::Format( _( "Checking %s clearance: %s." ),
@ -928,11 +933,22 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
break; break;
} }
case DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT:
{
int val = c->constraint.m_Value.Max();
REPORT( wxString::Format( _( "Checking %s max uncoupled length: %s." ),
EscapeHTML( c->constraint.GetName() ),
REPORT_VALUE( val ) ) )
break;
}
case TRACK_WIDTH_CONSTRAINT: case TRACK_WIDTH_CONSTRAINT:
case ANNULAR_WIDTH_CONSTRAINT: case ANNULAR_WIDTH_CONSTRAINT:
case VIA_DIAMETER_CONSTRAINT: case VIA_DIAMETER_CONSTRAINT:
case TEXT_HEIGHT_CONSTRAINT: case TEXT_HEIGHT_CONSTRAINT:
case TEXT_THICKNESS_CONSTRAINT: case TEXT_THICKNESS_CONSTRAINT:
case DIFF_PAIR_GAP_CONSTRAINT:
{ {
if( aReporter ) if( aReporter )
{ {
@ -950,10 +966,11 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
case TRACK_WIDTH_CONSTRAINT: msg = _( "track width" ); break; case TRACK_WIDTH_CONSTRAINT: msg = _( "track width" ); break;
case ANNULAR_WIDTH_CONSTRAINT: msg = _( "annular width" ); break; case ANNULAR_WIDTH_CONSTRAINT: msg = _( "annular width" ); break;
case VIA_DIAMETER_CONSTRAINT: msg = _( "via diameter" ); break; case VIA_DIAMETER_CONSTRAINT: msg = _( "via diameter" ); break;
case DIFF_PAIR_GAP_CONSTRAINT: msg = _( "diff pair gap" ); break;
default: msg = _( "constraint" ); break; default: msg = _( "constraint" ); break;
} }
REPORT( wxString::Format( _( "Checking %s %s: %s." ), REPORT( wxString::Format( _( "Checking %s %s: opt %s." ),
EscapeHTML( c->constraint.GetName() ), EscapeHTML( c->constraint.GetName() ),
EscapeHTML( msg ), EscapeHTML( msg ),
opt ) ) opt ) )

View File

@ -194,19 +194,45 @@ void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a,
} }
wxString reportMin( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint )
{
if( aConstraint.m_Value.HasMin() )
return StringFromValue( aUnits, aConstraint.m_Value.Min(), true );
else
return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
}
wxString reportOpt( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint )
{
if( aConstraint.m_Value.HasOpt() )
return StringFromValue( aUnits, aConstraint.m_Value.Opt(), true );
else
return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
}
wxString reportMax( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint )
{
if( aConstraint.m_Value.HasMax() )
return StringFromValue( aUnits, aConstraint.m_Value.Max(), true );
else
return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
}
void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDRCItem ) void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDRCItem )
{ {
BOARD_ITEM* a = m_frame->GetBoard()->GetItem( aDRCItem->GetMainItemID() ); BOARD_ITEM* a = m_frame->GetBoard()->GetItem( aDRCItem->GetMainItemID() );
BOARD_ITEM* b = m_frame->GetBoard()->GetItem( aDRCItem->GetAuxItemID() ); BOARD_ITEM* b = m_frame->GetBoard()->GetItem( aDRCItem->GetAuxItemID() );
BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );
PCB_LAYER_ID layer = m_frame->GetActiveLayer(); PCB_LAYER_ID layer = m_frame->GetActiveLayer();
if( !a || !b )
return;
if( m_inspectClearanceDialog == nullptr ) if( m_inspectClearanceDialog == nullptr )
{ {
m_inspectClearanceDialog = std::make_unique<DIALOG_CONSTRAINTS_REPORTER>( m_frame ); m_inspectClearanceDialog = std::make_unique<DIALOG_CONSTRAINTS_REPORTER>( m_frame );
m_inspectClearanceDialog->SetTitle( _( "Clearance Report" ) ); m_inspectClearanceDialog->SetTitle( _( "Violation Report" ) );
m_inspectClearanceDialog->Connect( wxEVT_CLOSE_WINDOW, m_inspectClearanceDialog->Connect( wxEVT_CLOSE_WINDOW,
wxCommandEventHandler( BOARD_INSPECTION_TOOL::onInspectClearanceDialogClosed ), wxCommandEventHandler( BOARD_INSPECTION_TOOL::onInspectClearanceDialogClosed ),
@ -222,8 +248,108 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
switch( aDRCItem->GetErrorCode() ) switch( aDRCItem->GetErrorCode() )
{ {
case DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG:
{
for( KIID id : aDRCItem->GetIDs() )
{
bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( m_frame->GetBoard()->GetItem( id ) );
if( ac && bc && ac->GetNetCode() != bc->GetNetCode() )
break;
}
r = m_inspectClearanceDialog->AddPage( _( "Uncoupled Length" ) );
reportHeader( _( "Diff pair uncoupled length resolution for:" ), ac, bc, r );
if( compileError )
reportCompileError( r );
constraint = drcEngine.EvalRules( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT, a, b, layer, r );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
reportMax( r->GetUnits(), constraint ) ) );
break;
}
case DRCE_TEXT_HEIGHT:
r = m_inspectClearanceDialog->AddPage( _( "Text Height" ) );
reportHeader( _( "Text height resolution for:" ), a, r );
if( compileError )
reportCompileError( r );
constraint = drcEngine.EvalRules( TEXT_HEIGHT_CONSTRAINT, a, b, layer, r );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved text height constraints: min %s; opt %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
break;
case DRCE_TEXT_THICKNESS:
r = m_inspectClearanceDialog->AddPage( _( "Text Thickness" ) );
reportHeader( _( "Text thickness resolution for:" ), a, r );
if( compileError )
reportCompileError( r );
constraint = drcEngine.EvalRules( TEXT_THICKNESS_CONSTRAINT, a, b, layer, r );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved text thickness constraints: min %s; opt %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
break;
case DRCE_HOLE_CLEARANCE:
r = m_inspectClearanceDialog->AddPage( _( "Hole Clearance" ) );
reportHeader( _( "Hole clearance resolution for:" ), a, b, r );
if( compileError )
reportCompileError( r );
if( ac && bc && ac->GetNetCode() == bc->GetNetCode() )
{
r->Report( "" );
r->Report( _( "Items belong to the same net. Clearance is 0." ) );
}
else
{
constraint = drcEngine.EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
clearance = constraint.m_Value.Min();
clearanceStr = StringFromValue( r->GetUnits(), clearance, true );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
}
r->Report( "" );
r->Report( "" );
r->Report( "" );
reportHeader( _( "Mechanical hole clearance resolution for:" ), a, b, layer, r );
constraint = drcEngine.EvalRules( MECHANICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r );
clearance = constraint.m_Value.Min();
clearanceStr = StringFromValue( r->GetUnits(), clearance, true );
if( !drcEngine.HasRulesForConstraintType( MECHANICAL_HOLE_CLEARANCE_CONSTRAINT ) )
{
r->Report( "" );
r->Report( _( "No 'mechanical_hole_clearance' constraints defined." ) );
}
else
{
r->Report( "" );
r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
}
break;
case DRCE_EDGE_CLEARANCE: case DRCE_EDGE_CLEARANCE:
r = m_inspectClearanceDialog->AddPage( _( "Clearance" ) ); r = m_inspectClearanceDialog->AddPage( _( "Edge Clearance" ) );
reportHeader( _( "Edge clearance resolution for:" ), a, b, r ); reportHeader( _( "Edge clearance resolution for:" ), a, b, r );
if( compileError ) if( compileError )
@ -271,12 +397,41 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
if( compileError ) if( compileError )
reportCompileError( r ); reportCompileError( r );
if( ac && bc && ac->GetNetCode() == bc->GetNetCode() )
{
r->Report( "" );
r->Report( _( "Items belong to the same net. Clearance is 0." ) );
}
else
{
constraint = drcEngine.EvalRules( CLEARANCE_CONSTRAINT, a, a, layer, r ); constraint = drcEngine.EvalRules( CLEARANCE_CONSTRAINT, a, a, layer, r );
clearance = constraint.m_Value.Min(); clearance = constraint.m_Value.Min();
clearanceStr = StringFromValue( r->GetUnits(), clearance, true ); clearanceStr = StringFromValue( r->GetUnits(), clearance, true );
r->Report( "" ); r->Report( "" );
r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) ); r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
}
r->Report( "" );
r->Report( "" );
r->Report( "" );
reportHeader( _( "Mechanical clearance resolution for:" ), a, b, layer, r );
constraint = drcEngine.EvalRules( MECHANICAL_CLEARANCE_CONSTRAINT, a, b, layer, r );
clearance = constraint.m_Value.Min();
clearanceStr = StringFromValue( r->GetUnits(), clearance, true );
if( !drcEngine.HasRulesForConstraintType( MECHANICAL_CLEARANCE_CONSTRAINT ) )
{
r->Report( "" );
r->Report( _( "No 'mechanical_clearance' constraints defined." ) );
}
else
{
r->Report( "" );
r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
}
break; break;
default: default:
@ -499,6 +654,49 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
r->Flush(); r->Flush();
} }
if( ac && bc )
{
NETINFO_ITEM* refNet = ac->GetNet();
wxString coupledNet;
wxString dummy;
if( DRC_ENGINE::MatchDpSuffix( refNet->GetNetname(), coupledNet, dummy )
&& bc->GetNetname() == coupledNet )
{
r = m_inspectClearanceDialog->AddPage( _( "Diff Pair" ) );
reportHeader( _( "Diff pair gap resolution for:" ), ac, bc, active, r );
constraint = drcEngine.EvalRules( DIFF_PAIR_GAP_CONSTRAINT, ac, bc, active, r );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved gap constraints: min %s; opt %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
r->Report( "" );
r->Report( "" );
r->Report( "" );
reportHeader( _( "Diff pair max uncoupled length resolution for:" ), ac, bc, active, r );
if( !drcEngine.HasRulesForConstraintType( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT ) )
{
r->Report( "" );
r->Report( _( "No 'diff_pair_uncoupled' constraints defined." ) );
}
else
{
constraint = drcEngine.EvalRules( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT, ac, bc,
active, r );
r->Report( "" );
r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
reportMax( r->GetUnits(), constraint ) ) );
}
r->Flush();
}
}
for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } ) for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } )
{ {
PCB_LAYER_ID correspondingMask = IsFrontLayer( layer ) ? F_Mask : B_Mask; PCB_LAYER_ID correspondingMask = IsFrontLayer( layer ) ? F_Mask : B_Mask;
@ -691,33 +889,6 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
} }
wxString reportMin( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint )
{
if( aConstraint.m_Value.HasMin() )
return StringFromValue( aUnits, aConstraint.m_Value.Min(), true );
else
return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
}
wxString reportOpt( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint )
{
if( aConstraint.m_Value.HasOpt() )
return StringFromValue( aUnits, aConstraint.m_Value.Opt(), true );
else
return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
}
wxString reportMax( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint )
{
if( aConstraint.m_Value.HasMax() )
return StringFromValue( aUnits, aConstraint.m_Value.Max(), true );
else
return wxT( "<i>" ) + _( "undefined" ) + wxT( "</i>" );
}
int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent ) int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
{ {
#define EVAL_RULES( constraint, a, b, layer, r ) drcEngine.EvalRules( constraint, a, b, layer, r ) #define EVAL_RULES( constraint, a, b, layer, r ) drcEngine.EvalRules( constraint, a, b, layer, r )
@ -830,6 +1001,43 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
r->Flush(); r->Flush();
} }
if( item->Type() == PCB_TEXT_T
|| item->Type() == PCB_TEXTBOX_T
|| item->Type() == PCB_FP_TEXT_T )
{
r = m_inspectConstraintsDialog->AddPage( _( "Text Size" ) );
reportHeader( _( "Text height resolution for:" ), item, r );
constraint = EVAL_RULES( TEXT_HEIGHT_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
if( compileError )
reportCompileError( r );
r->Report( "" );
r->Report( wxString::Format( _( "Text height constraints: min %s; opt %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
r->Report( "" );
r->Report( "" );
r->Report( "" );
reportHeader( _( "Text thickness resolution for:" ), item, r );
constraint = EVAL_RULES( TEXT_THICKNESS_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r );
if( compileError )
reportCompileError( r );
r->Report( "" );
r->Report( wxString::Format( _( "Text thickness constraints: min %s; opt %s; max %s." ),
reportMin( r->GetUnits(), constraint ),
reportOpt( r->GetUnits(), constraint ),
reportMax( r->GetUnits(), constraint ) ) );
r->Flush();
}
r = m_inspectConstraintsDialog->AddPage( _( "Keepouts" ) ); r = m_inspectConstraintsDialog->AddPage( _( "Keepouts" ) );
reportHeader( _( "Keepout resolution for:" ), item, r ); reportHeader( _( "Keepout resolution for:" ), item, r );