This commit is contained in:
Jeff Young 2020-09-13 00:05:32 +01:00
parent 5d9301d394
commit 8420fcc33b
11 changed files with 267 additions and 262 deletions

View File

@ -511,6 +511,7 @@ set( PCB_COMMON_SRCS
${CMAKE_SOURCE_DIR}/pcbnew/convert_drawsegment_list_to_polygon.cpp
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_item.cpp
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_rule.cpp
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_rule_condition.cpp
${CMAKE_SOURCE_DIR}/pcbnew/eagle_plugin.cpp
${CMAKE_SOURCE_DIR}/pcbnew/footprint_editor_settings.cpp
${CMAKE_SOURCE_DIR}/pcbnew/gpcb_plugin.cpp

View File

@ -111,7 +111,7 @@ int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem,
// LEVEL 2: Rules
//
if( GetRuleClearance( aItem, aLayer, &clearance, aSource, aReporter ) )
if( GetRuleClearance( aItem, aLayer, &clearance, aSource ) )
return clearance;
// LEVEL 3: Accumulated local settings, netclass settings, & board design settings
@ -153,11 +153,10 @@ int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem,
bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer,
int* aClearance, wxString* aSource,
REPORTER* aReporter ) const
int* aClearance, wxString* aSource ) const
{
const DRC_CONSTRAINT* constraint = GetConstraint( this, aItem, DRC_CONSTRAINT_TYPE_CLEARANCE,
aLayer, aSource, aReporter );
aLayer, aSource );
if( constraint )
{
@ -166,12 +165,6 @@ bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLa
*aClearance = constraint->m_Value.Min();
if( aReporter )
{
wxString clearance = StringFromValue( aReporter->GetUnits(), *aClearance, true );
aReporter->Report( wxString::Format( _( "Clearance: %s." ), clearance ) );
}
return true;
}

View File

@ -179,7 +179,7 @@ public:
* @return true if a rule was fired
*/
virtual bool GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int* aClearance,
wxString* aSource, REPORTER* aReporter = nullptr ) const;
wxString* aSource ) const;
/**
* Function GetLocalClearanceOverrides

View File

@ -23,19 +23,15 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
// fixme - way too much includes
#include <fctsys.h>
#include <pcbnew.h>
#include <reporter.h>
#include <widgets/progress_reporter.h>
#include <drc/drc_engine.h>
#include <drc/drc_rule_parser.h>
#include <drc/drc_rule.h>
#include <drc/drc_item.h>
#include <drc/drc_rule_condition.h>
#include <drc/drc_test_provider.h>
#include "drc.h"
#include <drc/drc.h>
void drcPrintDebugMessage( int level, wxString msg, const char *function, int line )
{
@ -297,6 +293,45 @@ static wxString formatConstraint( const DRC_CONSTRAINT& constraint )
}
bool DRC_ENGINE::LoadRules( wxFileName aPath )
{
NULL_REPORTER nullReporter;
REPORTER* reporter = m_reporter ? m_reporter : &nullReporter;
if( aPath.FileExists() )
{
m_ruleConditions.clear();
m_rules.clear();
FILE* fp = wxFopen( aPath.GetFullPath(), wxT( "rt" ) );
if( fp )
{
try
{
DRC_RULES_PARSER parser( m_board, fp, aPath.GetFullPath() );
parser.Parse( m_rules, reporter );
}
catch( PARSE_ERROR& pe )
{
// Don't leave possibly malformed stuff around for us to trip over
m_ruleConditions.clear();
m_rules.clear();
// JEY TODO
//wxSafeYield( m_editFrame );
//m_editFrame->ShowBoardSetupDialog( _( "Rules" ), pe.What(), ID_RULES_EDITOR,
// pe.lineNumber, pe.byteIndex );
return false;
}
}
}
return true;
}
bool DRC_ENGINE::CompileRules()
{
ReportAux( wxString::Format( "Compiling Rules (%d rules, %d conditions): ",
@ -375,45 +410,6 @@ bool DRC_ENGINE::CompileRules()
}
bool DRC_ENGINE::LoadRules( wxFileName aPath )
{
NULL_REPORTER nullReporter;
REPORTER* reporter = m_reporter ? m_reporter : &nullReporter;
if( aPath.FileExists() )
{
m_ruleConditions.clear();
m_rules.clear();
FILE* fp = wxFopen( aPath.GetFullPath(), wxT( "rt" ) );
if( fp )
{
try
{
DRC_RULES_PARSER parser( m_board, fp, aPath.GetFullPath() );
parser.Parse( m_rules, reporter );
}
catch( PARSE_ERROR& pe )
{
// Don't leave possibly malformed stuff around for us to trip over
m_ruleConditions.clear();
m_rules.clear();
// JEY TODO
//wxSafeYield( m_editFrame );
//m_editFrame->ShowBoardSetupDialog( _( "Rules" ), pe.What(), ID_RULES_EDITOR,
// pe.lineNumber, pe.byteIndex );
return false;
}
}
}
return true;
}
void DRC_ENGINE::InitEngine( wxFileName aRulePath )
{
m_testProviders = DRC_TEST_PROVIDER_REGISTRY::Instance().GetTestProviders();
@ -570,10 +566,12 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
nullConstraint.m_DisallowFlags = 0;
return nullConstraint;
#undef REPORT
}
void DRC_ENGINE::Report( std::shared_ptr<DRC_ITEM> aItem, MARKER_PCB *aMarker )
void DRC_ENGINE::Report( const std::shared_ptr<DRC_ITEM>& aItem, MARKER_PCB *aMarker )
{
m_drcReport->AddItem( aItem, aMarker );
@ -584,7 +582,7 @@ void DRC_ENGINE::Report( std::shared_ptr<DRC_ITEM> aItem, MARKER_PCB *aMarker )
aItem->GetErrorMessage(),
aItem->GetErrorCode() );
auto rule = aItem->GetViolatingRule();
DRC_RULE* rule = aItem->GetViolatingRule();
if( rule )
msg += wxString::Format( ", violating rule: '%s'", rule->m_Name );
@ -655,8 +653,10 @@ DRC_CONSTRAINT DRC_ENGINE::GetWorstGlobalConstraint( DRC_CONSTRAINT_TYPE_T ruleI
std::vector<DRC_CONSTRAINT> DRC_ENGINE::QueryConstraintsById( DRC_CONSTRAINT_TYPE_T constraintID )
{
std::vector<DRC_CONSTRAINT> rv;
for ( auto c : m_constraintMap[constraintID]->sortedConstraints )
for ( CONSTRAINT_WITH_CONDITIONS* c : m_constraintMap[constraintID]->sortedConstraints )
rv.push_back(c->constraint);
return rv;
}
@ -676,7 +676,7 @@ bool DRC_ENGINE::QueryWorstConstraint( DRC_CONSTRAINT_TYPE_T aConstraintId,
{
int worst = 0;
for( const auto constraint : QueryConstraintsById( aConstraintId ) )
for( const DRC_CONSTRAINT& constraint : QueryConstraintsById( aConstraintId ) )
{
if( constraint.GetValue().HasMin() )
{

View File

@ -173,7 +173,7 @@ public:
bool CompileRules();
void Report( std::shared_ptr<DRC_ITEM> aItem, MARKER_PCB *Marker );
void Report( const std::shared_ptr<DRC_ITEM>& aItem, MARKER_PCB *Marker );
void ReportProgress( double aProgress );
void ReportStage ( const wxString& aStageName, int index, int total );
void ReportAux( const wxString& aStr );

View File

@ -23,17 +23,13 @@
#include <fctsys.h>
#include <class_board.h>
#include <class_board_item.h>
#include <reporter.h>
#include <drc/drc_rule.h>
#include <drc/drc_rule_condition.h>
#include <drc/drc_engine.h>
#include <pcb_expr_evaluator.h>
const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName,
REPORTER* aReporter )
int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName )
{
BOARD* board = aItem->GetBoard();
@ -42,23 +38,8 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM*
for( DRC_RULE* rule : board->GetDesignSettings().m_DRCRules )
{
if( aReporter )
{
aReporter->Report( wxString::Format( _( "Checking rule \"%s\"." ),
rule->m_Name ) );
}
if( !rule->m_LayerCondition.test( aLayer ) )
{
if( aReporter )
{
aReporter->Report( wxString::Format( _( "Rule layer \"%s\" not matched." ),
rule->m_LayerSource ) );
aReporter->Report( "Rule not applied." );
}
continue;
}
const DRC_CONSTRAINT* constraint = nullptr;
@ -71,32 +52,10 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM*
}
}
if( aReporter && !constraint )
if( constraint )
{
aReporter->Report( _( "Rule contains no applicable constraints." ) );
aReporter->Report( _( "Rule not applied." ) );
}
else
{
if( !rule->m_Condition )
{
if( aReporter )
aReporter->Report( _( "No condition found; rule not applied." ) );
return nullptr;
}
if( aReporter )
{
aReporter->Report( wxString::Format( _( "Checking rule condition \"%s\"." ),
rule->m_Condition->GetExpression() ) );
}
if( rule->m_Condition->EvaluateFor( aItem, bItem, aLayer ) )
{
if( aReporter )
aReporter->Report( "Rule applied." );
if( aRuleName )
*aRuleName = rule->m_Name;
@ -105,42 +64,23 @@ const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM*
if( bItem && rule->m_Condition->EvaluateFor( bItem, aItem, aLayer ) )
{
if( aReporter )
aReporter->Report( "Rule applied." );
if( aRuleName )
*aRuleName = rule->m_Name;
return constraint;
}
if( aReporter )
aReporter->Report( "Condition not satisfied; rule not applied." );
}
if( aReporter )
aReporter->Report( "" );
}
return nullptr;
}
wxString DRC_CONSTRAINT::GetName() const
{
if( m_parentRule )
return wxString::Format( _( "rule %s" ), m_parentRule->m_Name );
else
return m_name;
}
DRC_RULE::DRC_RULE() :
m_Unary( false ),
m_LayerCondition( LSET::AllLayersMask() ),
m_Condition( nullptr ),
m_Priority( 0 ),
m_Severity( SEVERITY::RPT_SEVERITY_ERROR )
m_Priority( 0 )
{
}
@ -158,77 +98,3 @@ void DRC_RULE::AddConstraint( DRC_CONSTRAINT& aConstraint )
}
DRC_RULE_CONDITION::DRC_RULE_CONDITION( const wxString& aExpression ) :
m_expression( aExpression ),
m_ucode ( nullptr )
{
}
DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
{
}
bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB,
PCB_LAYER_ID aLayer, REPORTER* aReporter )
{
#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
if( GetExpression().IsEmpty() )
{
REPORT( _( "Unconditional constraint." ) );
return true;
}
REPORT( _( "Checking rule condition \"" + GetExpression() + "\"." ) );
if( !m_ucode )
{
REPORT( _( "ERROR in expression." ) );
return false;
}
BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
BOARD_ITEM* b = aItemB ? const_cast<BOARD_ITEM*>( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
PCB_EXPR_CONTEXT ctx( aLayer );
ctx.SetItems( a, b );
ctx.SetErrorCallback( [&]( const wxString& aMessage, int aOffset )
{
REPORT( _( "ERROR: " ) + aMessage );
} );
return m_ucode->Run( &ctx )->AsDouble() != 0.0;
}
bool DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset )
{
auto errorHandler = [&]( const wxString& aMessage, int aOffset )
{
wxString rest;
wxString first = aMessage.BeforeFirst( '|', &rest );
wxString msg = wxString::Format( _( "ERROR: <a href='%d:%d'>%s</a>%s" ),
aSourceLine,
aSourceOffset + aOffset,
first,
rest );
aReporter->Report( msg, RPT_SEVERITY_ERROR );
};
PCB_EXPR_COMPILER compiler;
compiler.SetErrorCallback( errorHandler );
m_ucode = std::make_unique<PCB_EXPR_UCODE>();
PCB_EXPR_CONTEXT preflightContext( F_Cu );
bool ok = compiler.Compile( GetExpression().ToUTF8().data(), m_ucode.get(), &preflightContext );
return ok;
}

View File

@ -30,12 +30,11 @@
#include <libeval_compiler/libeval_compiler.h>
class BOARD_ITEM;
class PCB_EXPR_UCODE;
class DRC_RULE;
class DRC_CONSTRAINT;
class DRC_RULE_CONDITION;
enum DRC_CONSTRAINT_TYPE_T
{
DRC_CONSTRAINT_TYPE_UNKNOWN = -1,
@ -49,11 +48,10 @@ enum DRC_CONSTRAINT_TYPE_T
DRC_CONSTRAINT_TYPE_TRACK_WIDTH,
DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH,
DRC_CONSTRAINT_TYPE_DISALLOW,
DRC_CONSTRAINT_TYPE_VIA_DIAMETER,
DRC_CONSTRAINT_TYPE_COUNT
DRC_CONSTRAINT_TYPE_VIA_DIAMETER
};
enum DRC_DISALLOW_T
{
DRC_DISALLOW_VIAS = (1 << 0),
@ -95,57 +93,6 @@ private:
};
class DRC_CONSTRAINT
{
public:
DRC_CONSTRAINT( DRC_CONSTRAINT_TYPE_T aType = DRC_CONSTRAINT_TYPE_UNKNOWN,
const wxString& aName = wxEmptyString ) :
m_Type( aType ),
m_DisallowFlags( 0 ),
m_name( aName ),
m_parentRule( nullptr )
{
}
const MINOPTMAX<int>& GetValue() const { return m_Value; }
MINOPTMAX<int>& Value() { return m_Value; }
void SetParentRule( DRC_RULE *aParentRule ) { m_parentRule = aParentRule; }
DRC_RULE* GetParentRule() const { return m_parentRule; }
wxString GetName() const;
public:
DRC_CONSTRAINT_TYPE_T m_Type;
MINOPTMAX<int> m_Value;
int m_DisallowFlags;
private:
wxString m_name; // For just-in-time constraints
DRC_RULE* m_parentRule; // For constraints found in rules
};
class DRC_RULE_CONDITION
{
public:
DRC_RULE_CONDITION( const wxString& aExpression = "" );
~DRC_RULE_CONDITION();
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer,
REPORTER* aReporter = nullptr );
bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 );
void SetExpression( const wxString& aExpression ) { m_expression = aExpression; }
wxString GetExpression() const { return m_expression; }
private:
wxString m_expression;
std::unique_ptr<PCB_EXPR_UCODE> m_ucode;
};
class DRC_RULE
{
public:
@ -167,7 +114,7 @@ public:
return false;
};
virtual void FillSpecificItemSet( std::set<BOARD_ITEM*> specificItems )
virtual void FillSpecificItemSet( const std::set<BOARD_ITEM*>& specificItems )
{
};
@ -185,14 +132,49 @@ public:
std::vector<DRC_CONSTRAINT> m_Constraints;
int m_Priority; // 0 indicates automatic priority generation fixme: use enum
SEVERITY m_Severity;
};
class DRC_CONSTRAINT
{
public:
DRC_CONSTRAINT( DRC_CONSTRAINT_TYPE_T aType = DRC_CONSTRAINT_TYPE_UNKNOWN,
const wxString& aName = wxEmptyString ) :
m_Type( aType ),
m_DisallowFlags( 0 ),
m_name( aName ),
m_parentRule( nullptr )
{
}
const MINOPTMAX<int>& GetValue() const { return m_Value; }
MINOPTMAX<int>& Value() { return m_Value; }
void SetParentRule( DRC_RULE *aParentRule ) { m_parentRule = aParentRule; }
DRC_RULE* GetParentRule() const { return m_parentRule; }
wxString GetName() const
{
if( m_parentRule )
return wxString::Format( _( "rule %s" ), m_parentRule->m_Name );
else
return m_name;
}
public:
DRC_CONSTRAINT_TYPE_T m_Type;
MINOPTMAX<int> m_Value;
int m_DisallowFlags;
private:
wxString m_name; // For just-in-time constraints
DRC_RULE* m_parentRule; // For constraints found in rules
};
const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
int aConstraint, PCB_LAYER_ID aLayer,
wxString* aRuleName = nullptr,
REPORTER* aReporter = nullptr );
wxString* aRuleName = nullptr );
#endif // DRC_RULE_H

View File

@ -0,0 +1,107 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <fctsys.h>
#include <class_board_item.h>
#include <reporter.h>
#include <drc/drc_rule_condition.h>
#include <pcb_expr_evaluator.h>
DRC_RULE_CONDITION::DRC_RULE_CONDITION( const wxString& aExpression ) :
m_expression( aExpression ),
m_ucode ( nullptr )
{
}
DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
{
}
bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB,
PCB_LAYER_ID aLayer, REPORTER* aReporter )
{
#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
if( GetExpression().IsEmpty() )
{
REPORT( _( "Unconditional constraint." ) );
return true;
}
REPORT( _( "Checking rule condition \"" + GetExpression() + "\"." ) );
if( !m_ucode )
{
REPORT( _( "ERROR in expression." ) );
return false;
}
BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
BOARD_ITEM* b = aItemB ? const_cast<BOARD_ITEM*>( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
PCB_EXPR_CONTEXT ctx( aLayer );
ctx.SetItems( a, b );
ctx.SetErrorCallback( [&]( const wxString& aMessage, int aOffset )
{
REPORT( _( "ERROR: " ) + aMessage );
} );
return m_ucode->Run( &ctx )->AsDouble() != 0.0;
#undef REPORT
}
bool DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset )
{
auto errorHandler = [&]( const wxString& aMessage, int aOffset )
{
wxString rest;
wxString first = aMessage.BeforeFirst( '|', &rest );
wxString msg = wxString::Format( _( "ERROR: <a href='%d:%d'>%s</a>%s" ),
aSourceLine,
aSourceOffset + aOffset,
first,
rest );
aReporter->Report( msg, RPT_SEVERITY_ERROR );
};
PCB_EXPR_COMPILER compiler;
compiler.SetErrorCallback( errorHandler );
m_ucode = std::make_unique<PCB_EXPR_UCODE>();
PCB_EXPR_CONTEXT preflightContext( F_Cu );
bool ok = compiler.Compile( GetExpression().ToUTF8().data(), m_ucode.get(), &preflightContext );
return ok;
}

View File

@ -0,0 +1,56 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef DRC_RULE_CONDITION_H
#define DRC_RULE_CONDITION_H
#include <common.h>
#include <core/typeinfo.h>
#include <layers_id_colors_and_visibility.h>
class BOARD_ITEM;
class PCB_EXPR_UCODE;
class REPORTER;
class DRC_RULE_CONDITION
{
public:
DRC_RULE_CONDITION( const wxString& aExpression = "" );
~DRC_RULE_CONDITION();
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer,
REPORTER* aReporter = nullptr );
bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 );
void SetExpression( const wxString& aExpression ) { m_expression = aExpression; }
wxString GetExpression() const { return m_expression; }
private:
wxString m_expression;
std::unique_ptr<PCB_EXPR_UCODE> m_ucode;
};
#endif // DRC_RULE_CONDITION_H

View File

@ -24,9 +24,8 @@
#include <fctsys.h>
#include <class_board.h>
#include <class_board_item.h>
#include <drc/drc_rule_parser.h>
#include <drc/drc_rule_condition.h>
#include <drc_rules_lexer.h>
#include <pcb_expr_evaluator.h>
#include <reporter.h>

View File

@ -36,6 +36,7 @@ endif()
add_executable( drc_proto
drc_proto_test.cpp
../../pcbnew/drc/drc_rule.cpp
../../pcbnew/drc/drc_rule_condition.cpp
../../pcbnew/drc/drc_rule_parser.cpp
../../pcbnew/drc/drc_test_provider.cpp
../../pcbnew/drc/drc_test_provider_clearance_base.cpp