drc_proto: all tests now supported in drc_proto. Not tested yet!
This commit is contained in:
parent
147540b3bb
commit
adbd94553d
|
@ -44,6 +44,14 @@ add_executable( drc_proto
|
|||
drc_test_provider_hole_clearance.cpp
|
||||
drc_test_provider_edge_clearance.cpp
|
||||
drc_test_provider_hole_size.cpp
|
||||
drc_test_provider_disallow.cpp
|
||||
drc_test_provider_track_width.cpp
|
||||
drc_test_provider_annulus.cpp
|
||||
drc_test_provider_connectivity.cpp
|
||||
drc_test_provider_courtyard_clearance.cpp
|
||||
drc_test_provider_via_diameter.cpp
|
||||
drc_test_provider_lvs.cpp
|
||||
drc_test_provider_misc.cpp
|
||||
drc_engine.cpp
|
||||
drc_item.cpp
|
||||
../qa_utils/mocks.cpp
|
||||
|
|
|
@ -43,6 +43,10 @@ void drcPrintDebugMessage( int level, wxString msg, const char *function, int li
|
|||
if( wxGetEnv( "DRC_DEBUG", &valueStr ) )
|
||||
{
|
||||
int setLevel = wxAtoi( valueStr );
|
||||
if( level <= setLevel )
|
||||
{
|
||||
printf("%-30s:%d | %s\n", function, line, (const char *) msg.c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +54,8 @@ void drcPrintDebugMessage( int level, wxString msg, const char *function, int li
|
|||
test::DRC_ENGINE::DRC_ENGINE( BOARD* aBoard, BOARD_DESIGN_SETTINGS *aSettings ) :
|
||||
m_board( aBoard ),
|
||||
m_designSettings ( aSettings ),
|
||||
m_worksheet( nullptr ),
|
||||
m_schematicNetlist( nullptr ),
|
||||
m_reporter( nullptr ),
|
||||
m_progressReporter( nullptr )
|
||||
{
|
||||
|
@ -64,11 +70,6 @@ test::DRC_ENGINE::~DRC_ENGINE()
|
|||
|
||||
test::DRC_REPORT::~DRC_REPORT()
|
||||
{
|
||||
for( auto item : m_entries )
|
||||
{
|
||||
if ( item.m_marker )
|
||||
delete item.m_marker;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -139,11 +140,11 @@ bool test::DRC_ENGINE::CompileRules()
|
|||
for( auto provider : m_testProviders )
|
||||
{
|
||||
ReportAux( wxString::Format( "- Provider: '%s': ", provider->GetName() ) );
|
||||
drc_dbg(11, "do prov %s", provider->GetName() );
|
||||
drc_dbg(7, "do prov %s", provider->GetName() );
|
||||
|
||||
for ( auto id : provider->GetMatchingConstraintIds() )
|
||||
{
|
||||
drc_dbg(11, "do id %d", id);
|
||||
drc_dbg(7, "do id %d", id);
|
||||
if( m_constraintMap.find(id) == m_constraintMap.end() )
|
||||
m_constraintMap[id] = new CONSTRAINT_SET;
|
||||
|
||||
|
@ -151,14 +152,14 @@ bool test::DRC_ENGINE::CompileRules()
|
|||
|
||||
for( auto rule : m_rules )
|
||||
{
|
||||
drc_dbg(11, "Scan provider %s, rule %s", provider->GetName(), rule->GetName() );
|
||||
drc_dbg(7, "Scan provider %s, rule %s", provider->GetName(), rule->GetName() );
|
||||
|
||||
if( ! rule->IsEnabled() )
|
||||
continue;
|
||||
|
||||
for( auto& constraint : rule->Constraints() )
|
||||
{
|
||||
drc_dbg(11, "scan constraint id %d\n", constraint.GetType() );
|
||||
drc_dbg(7, "scan constraint id %d\n", constraint.GetType() );
|
||||
if( constraint.GetType() != id )
|
||||
continue;
|
||||
|
||||
|
@ -191,8 +192,6 @@ bool test::DRC_ENGINE::CompileRules()
|
|||
|
||||
void test::DRC_ENGINE::RunTests( )
|
||||
{
|
||||
//m_largestClearance = m_designSettings->GetBiggestClearanceValue();
|
||||
|
||||
m_drcReport.reset( new test::DRC_REPORT );
|
||||
m_testProviders = DRC_TEST_PROVIDER_REGISTRY::Instance().GetTestProviders();
|
||||
|
||||
|
@ -209,8 +208,11 @@ void test::DRC_ENGINE::RunTests( )
|
|||
for( auto provider : m_testProviders )
|
||||
{
|
||||
bool skipProvider = false;
|
||||
auto matchingConstraints = provider->GetMatchingConstraintIds();
|
||||
|
||||
for( auto ruleID : provider->GetMatchingConstraintIds() )
|
||||
if( matchingConstraints.size() )
|
||||
{
|
||||
for( auto ruleID : matchingConstraints )
|
||||
{
|
||||
if( !HasCorrectRulesForId( ruleID ) )
|
||||
{
|
||||
|
@ -219,6 +221,7 @@ void test::DRC_ENGINE::RunTests( )
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( skipProvider )
|
||||
continue;
|
||||
|
@ -271,11 +274,17 @@ void test::DRC_ENGINE::Report( std::shared_ptr<DRC_ITEM> aItem, ::MARKER_PCB *aM
|
|||
|
||||
if( m_reporter )
|
||||
{
|
||||
m_reporter->Report ( wxString::Format( "Test '%s': violation of rule '%s' : %s (code %d)",
|
||||
wxString msg = wxString::Format( "Test '%s': %s (code %d)",
|
||||
aItem->GetViolatingTest()->GetName(),
|
||||
aItem->GetViolatingRule()->GetName(),
|
||||
aItem->GetErrorMessage(),
|
||||
aItem->GetErrorCode() ), RPT_SEVERITY_ERROR /* fixme */ );
|
||||
aItem->GetErrorCode() );
|
||||
|
||||
auto rule = aItem->GetViolatingRule();
|
||||
|
||||
if( rule )
|
||||
msg += wxString::Format( ", violating rule: '%s'", rule->GetName() );
|
||||
|
||||
m_reporter->Report ( msg, RPT_SEVERITY_ERROR /* fixme */ );
|
||||
|
||||
wxString violatingItemsStr = "Violating items: ";
|
||||
|
||||
|
|
|
@ -53,12 +53,20 @@ class NETLIST;
|
|||
class PROGRESS_REPORTER;
|
||||
class REPORTER;
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class WS_PROXY_VIEW_ITEM;
|
||||
};
|
||||
|
||||
void drcPrintDebugMessage( int level, wxString msg, const char *function, int line );
|
||||
|
||||
#define drc_dbg(level, fmt, ...) \
|
||||
drcPrintDebugMessage(level, wxString::Format( fmt, __VA_ARGS__ ), __FUNCTION__, __LINE__ );
|
||||
|
||||
|
||||
//#define drc_dbg(level, fmt, ...) \
|
||||
// wxLogTrace("DUPA", fmt, __VA_ARGS__);
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
|
@ -91,7 +99,7 @@ enum PCB_DRC_CODE
|
|||
DRCE_HOLE_CLEARANCE, ///< overlapping drilled holes break drill bits
|
||||
DRCE_TRACK_WIDTH, ///< Track width is too small or too large
|
||||
DRCE_TOO_SMALL_VIA, ///< Too small via size
|
||||
DRCE_VIA_ANNULUS, ///< Via size and drill leave annulus too small or too large
|
||||
DRCE_ANNULUS, ///< Via size and drill leave annulus too small or too large
|
||||
DRCE_TOO_SMALL_DRILL, ///< Too small via or pad drill
|
||||
DRCE_VIA_HOLE_BIGGER, ///< via's hole is bigger than its diameter
|
||||
DRCE_PADSTACK, ///< something is wrong with a pad or via stackup
|
||||
|
@ -111,6 +119,7 @@ enum PCB_DRC_CODE
|
|||
DRCE_EXTRA_FOOTPRINT, ///< netlist item not found for footprint
|
||||
|
||||
DRCE_UNRESOLVED_VARIABLE,
|
||||
DRCE_VIA_DIAMETER, ///< Via diameter checks (min/max)
|
||||
|
||||
DRCE_LAST = DRCE_UNRESOLVED_VARIABLE
|
||||
};
|
||||
|
@ -158,6 +167,26 @@ public:
|
|||
DRC_ENGINE( BOARD* aBoard, BOARD_DESIGN_SETTINGS* aSettings );
|
||||
~DRC_ENGINE();
|
||||
|
||||
void SetSchematicNetlist( NETLIST* aNetlist )
|
||||
{
|
||||
m_schematicNetlist = aNetlist;
|
||||
}
|
||||
|
||||
NETLIST* GetSchematicNetlist() const
|
||||
{
|
||||
return m_schematicNetlist;
|
||||
}
|
||||
|
||||
void SetWorksheet( KIGFX::WS_PROXY_VIEW_ITEM* aWorksheet )
|
||||
{
|
||||
m_worksheet = aWorksheet;
|
||||
}
|
||||
|
||||
KIGFX::WS_PROXY_VIEW_ITEM* GetWorksheet() const
|
||||
{
|
||||
return m_worksheet;
|
||||
}
|
||||
|
||||
void SetProgressReporter( PROGRESS_REPORTER* aProgRep )
|
||||
{
|
||||
m_progressReporter = aProgRep;
|
||||
|
@ -183,6 +212,8 @@ public:
|
|||
return m_board;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const DRC_CONSTRAINT& EvalRulesForItems(
|
||||
DRC_CONSTRAINT_TYPE_T ruleID, BOARD_ITEM* a, BOARD_ITEM* b = nullptr, PCB_LAYER_ID aLayer = UNDEFINED_LAYER );
|
||||
|
||||
|
@ -233,6 +264,8 @@ private:
|
|||
|
||||
BOARD_DESIGN_SETTINGS* m_designSettings;
|
||||
BOARD* m_board;
|
||||
KIGFX::WS_PROXY_VIEW_ITEM* m_worksheet;
|
||||
NETLIST* m_schematicNetlist;
|
||||
|
||||
std::shared_ptr<DRC_REPORT> m_drcReport;
|
||||
|
||||
|
|
|
@ -88,9 +88,9 @@ test::DRC_ITEM test::DRC_ITEM::viaTooSmall( DRCE_TOO_SMALL_VIA,
|
|||
_( "Via size too small" ),
|
||||
wxT( "via_too_small" ) );
|
||||
|
||||
test::DRC_ITEM test::DRC_ITEM::viaAnnulus( DRCE_VIA_ANNULUS,
|
||||
_( "Via annulus" ),
|
||||
wxT( "via_annulus" ) );
|
||||
test::DRC_ITEM test::DRC_ITEM::annulus( DRCE_ANNULUS,
|
||||
_( "annulus" ),
|
||||
wxT( "annulus" ) );
|
||||
|
||||
test::DRC_ITEM test::DRC_ITEM::drillTooSmall( DRCE_TOO_SMALL_DRILL,
|
||||
_( "Drill too small" ),
|
||||
|
@ -175,7 +175,7 @@ std::vector<std::reference_wrapper<RC_ITEM>> test::DRC_ITEM::allItemTypes( {
|
|||
DRC_ITEM::holeClearance,
|
||||
DRC_ITEM::trackWidth,
|
||||
DRC_ITEM::viaTooSmall,
|
||||
DRC_ITEM::viaAnnulus,
|
||||
DRC_ITEM::annulus,
|
||||
DRC_ITEM::drillTooSmall,
|
||||
DRC_ITEM::viaHoleLargerThanPad,
|
||||
DRC_ITEM::padstack,
|
||||
|
@ -215,7 +215,7 @@ std::shared_ptr<test::DRC_ITEM> test::DRC_ITEM::Create( int aErrorCode )
|
|||
case DRCE_HOLE_CLEARANCE: item = new DRC_ITEM( holeClearance ); break;
|
||||
case DRCE_TRACK_WIDTH: item = new DRC_ITEM( trackWidth ); break;
|
||||
case DRCE_TOO_SMALL_VIA: item = new DRC_ITEM( viaTooSmall ); break;
|
||||
case DRCE_VIA_ANNULUS: item = new DRC_ITEM( viaAnnulus ); break;
|
||||
case DRCE_ANNULUS: item = new DRC_ITEM( annulus ); break;
|
||||
case DRCE_TOO_SMALL_DRILL: item = new DRC_ITEM( drillTooSmall ); break;
|
||||
case DRCE_VIA_HOLE_BIGGER: item = new DRC_ITEM( viaHoleLargerThanPad ); break;
|
||||
case DRCE_PADSTACK: item = new DRC_ITEM( padstack ); break;
|
||||
|
|
|
@ -98,7 +98,7 @@ private:
|
|||
static DRC_ITEM holeClearance;
|
||||
static DRC_ITEM trackWidth;
|
||||
static DRC_ITEM viaTooSmall;
|
||||
static DRC_ITEM viaAnnulus;
|
||||
static DRC_ITEM annulus;
|
||||
static DRC_ITEM drillTooSmall;
|
||||
static DRC_ITEM viaHoleLargerThanPad;
|
||||
static DRC_ITEM padstack;
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
|
||||
wxLogTrace("DUPA", "Debug Test!\n");
|
||||
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
propMgr.Rebuild();
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define DRC_RTREE_H_
|
||||
|
||||
#include <eda_rect.h>
|
||||
#include <board_connected_item.h>
|
||||
#include <class_board_item.h>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
|
@ -46,7 +46,7 @@ private:
|
|||
public:
|
||||
DRC_RTREE()
|
||||
{
|
||||
for( int layer : LSET::AllCuMask().Seq() )
|
||||
for( int layer : LSET::AllLayersMask().Seq() )
|
||||
m_tree[layer] = new drc_rtree();
|
||||
|
||||
m_count = 0;
|
||||
|
|
|
@ -57,7 +57,8 @@ enum DRC_CONSTRAINT_TYPE_T
|
|||
DRC_CONSTRAINT_TYPE_SILK_TO_SILK,
|
||||
DRC_CONSTRAINT_TYPE_TRACK_WIDTH,
|
||||
DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH,
|
||||
DRC_CONSTRAINT_TYPE_DISALLOW
|
||||
DRC_CONSTRAINT_TYPE_DISALLOW,
|
||||
DRC_CONSTRAINT_TYPE_VIA_DIAMETER
|
||||
};
|
||||
|
||||
enum DRC_DISALLOW_T
|
||||
|
@ -93,7 +94,7 @@ public:
|
|||
bool HasMax() const { return m_hasMax; }
|
||||
bool HasOpt() const { return m_hasOpt; }
|
||||
|
||||
void SetMin( T v ) { m_min = v; m_hasMin = true; }
|
||||
void SetMin( T v ) { m_min = v; m_hasMin = true; }
|
||||
void SetMax( T v ) { m_max = v; m_hasMax = true; }
|
||||
void SetOpt( T v ) { m_opt = v; m_hasOpt = true; }
|
||||
|
||||
|
@ -127,6 +128,8 @@ class DRC_CONSTRAINT
|
|||
|
||||
DRC_CONSTRAINT_TYPE_T GetType() const { return m_Type; }
|
||||
|
||||
const LSET& GetAllowedLayers() const { return m_LayerCondition; }
|
||||
|
||||
public:
|
||||
DRC_CONSTRAINT_TYPE_T m_Type;
|
||||
int m_DisallowFlags;
|
||||
|
|
|
@ -99,7 +99,7 @@ void test::DRC_TEST_PROVIDER::reportRuleStatistics()
|
|||
}
|
||||
}
|
||||
|
||||
int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T> aTypes, const LSET aLayers, std::function<int(BOARD_ITEM*)> aFunc )
|
||||
int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T> aTypes, const LSET aLayers, std::function<bool(BOARD_ITEM*)> aFunc )
|
||||
{
|
||||
BOARD *brd = m_drcEngine->GetBoard();
|
||||
std::bitset<MAX_STRUCT_TYPE_ID> typeMask;
|
||||
|
@ -124,6 +124,8 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T> aTy
|
|||
case PCB_VIA_T:
|
||||
case PCB_ARC_T:*/
|
||||
for ( auto item : brd->Tracks() )
|
||||
{
|
||||
if( (item->GetLayerSet() & aLayers).any() )
|
||||
{
|
||||
if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T )
|
||||
{
|
||||
|
@ -141,6 +143,7 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T> aTy
|
|||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* case PCB_DIMENSION_T:
|
||||
case PCB_LINE_T:
|
||||
|
@ -148,80 +151,124 @@ int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T> aTy
|
|||
case PCB_TARGET_T:
|
||||
*/
|
||||
for( auto item : brd->Drawings() )
|
||||
{
|
||||
if( (item->GetLayerSet() & aLayers).any() )
|
||||
{
|
||||
if( typeMask[ PCB_DIMENSION_T ] && item->Type() == PCB_DIMENSION_T )
|
||||
{
|
||||
aFunc( item );
|
||||
if( !aFunc( item ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
else if( typeMask[ PCB_LINE_T ] && item->Type() == PCB_LINE_T )
|
||||
{
|
||||
aFunc( item );
|
||||
if( !aFunc( item ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T )
|
||||
{
|
||||
aFunc( item );
|
||||
if( !aFunc( item ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T )
|
||||
{
|
||||
aFunc( item );
|
||||
if( !aFunc( item ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( auto item : brd->Zones() )
|
||||
{
|
||||
if( (item->GetLayerSet() & aLayers).any() )
|
||||
{
|
||||
if( typeMask[ PCB_ZONE_AREA_T ] && item->Type() == PCB_ZONE_AREA_T )
|
||||
{
|
||||
aFunc( item );
|
||||
if( !aFunc( item ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( auto mod : brd->Modules() )
|
||||
{
|
||||
if( typeMask[ PCB_MODULE_TEXT_T ] )
|
||||
{
|
||||
aFunc( &mod->Reference() );
|
||||
if( (mod->Reference().GetLayerSet() & aLayers).any() )
|
||||
{
|
||||
if( !aFunc( &mod->Reference() ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
aFunc( &mod->Value() );
|
||||
}
|
||||
|
||||
if( (mod->Value().GetLayerSet() & aLayers).any() )
|
||||
{
|
||||
if( !aFunc( &mod->Value() ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
for( auto pad : mod->Pads() )
|
||||
{
|
||||
if( (pad->GetLayerSet() & aLayers).any() )
|
||||
{
|
||||
if( typeMask[ PCB_PAD_T ] && pad->Type() == PCB_PAD_T )
|
||||
{
|
||||
aFunc( pad );
|
||||
if( !aFunc( pad ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( auto dwg : mod->GraphicalItems() )
|
||||
{
|
||||
if( (dwg->GetLayerSet() & aLayers).any() )
|
||||
{
|
||||
if( typeMask[ PCB_MODULE_TEXT_T ] && dwg->Type() == PCB_MODULE_TEXT_T )
|
||||
{
|
||||
aFunc( dwg );
|
||||
if( !aFunc( dwg ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
else if( typeMask[ PCB_MODULE_EDGE_T ] && dwg->Type() == PCB_MODULE_EDGE_T )
|
||||
{
|
||||
aFunc( dwg );
|
||||
if( !aFunc( dwg ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( auto zone : mod->Zones() )
|
||||
{
|
||||
if( (zone->GetLayerSet() & aLayers).any() )
|
||||
{
|
||||
if( typeMask[ PCB_MODULE_ZONE_AREA_T ] && zone->Type() == PCB_MODULE_ZONE_AREA_T )
|
||||
{
|
||||
aFunc( zone );
|
||||
if( ! aFunc( zone ) )
|
||||
return n;
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -106,9 +106,14 @@ public:
|
|||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const = 0;
|
||||
|
||||
virtual bool IsRuleDriven() const
|
||||
{
|
||||
return m_isRuleDriven;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
int forEachGeometryItem( const std::vector<KICAD_T> aTypes, const LSET aLayers, std::function<int(BOARD_ITEM*)> aFunc );
|
||||
int forEachGeometryItem( const std::vector<KICAD_T> aTypes, const LSET aLayers, std::function<bool(BOARD_ITEM*)> aFunc );
|
||||
|
||||
virtual void reportRuleStatistics();
|
||||
virtual void accountCheck( const test::DRC_RULE* ruleToTest );
|
||||
|
@ -119,6 +124,7 @@ protected:
|
|||
DRC_ENGINE *m_drcEngine;
|
||||
std::unordered_map<const test::DRC_RULE*, int> m_stats;
|
||||
bool m_enable;
|
||||
bool m_isRuleDriven = true;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2020 KiCad Developers.
|
||||
*
|
||||
* 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 <class_board.h>
|
||||
#include <class_track.h>
|
||||
#include <class_via.h>
|
||||
#include <class_pad.h>
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <drc_proto/drc_engine.h>
|
||||
#include <drc_proto/drc_item.h>
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <drc_proto/drc_test_provider.h>
|
||||
|
||||
|
||||
/*
|
||||
Via/pad annular ring width test. Checks if there's sufficient copper ring around PTH/NPTH holes (vias/pads)
|
||||
Errors generated:
|
||||
- DRCE_ANNULUS
|
||||
|
||||
Todo:
|
||||
- check pad holes too.
|
||||
- pad stack support (different IAR/OAR values depending on layer)
|
||||
*/
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
class DRC_TEST_PROVIDER_ANNULUS : public DRC_TEST_PROVIDER
|
||||
{
|
||||
public:
|
||||
DRC_TEST_PROVIDER_ANNULUS()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DRC_TEST_PROVIDER_ANNULUS()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Run() override;
|
||||
|
||||
virtual const wxString GetName() const override
|
||||
{
|
||||
return "annulus";
|
||||
};
|
||||
|
||||
virtual const wxString GetDescription() const override
|
||||
{
|
||||
return "Tests pad/via annular rings";
|
||||
}
|
||||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||
};
|
||||
|
||||
}; // namespace test
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_ANNULUS::Run()
|
||||
{
|
||||
if( !m_drcEngine->HasCorrectRulesForId(
|
||||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH ) )
|
||||
{
|
||||
ReportAux( "No annulus constraints found. Skipping check." );
|
||||
return false;
|
||||
}
|
||||
|
||||
ReportStage( ( "Testing via annular rings" ), 0, 2 );
|
||||
|
||||
auto checkAnnulus = [&]( BOARD_ITEM* item ) -> bool
|
||||
{
|
||||
bool fail_min = false, fail_max = false;
|
||||
int v_min, v_max;
|
||||
auto via = dyn_cast<VIA*>( item );
|
||||
|
||||
// fixme: check minimum IAR/OAR ring for THT pads too
|
||||
if( !via )
|
||||
return true;
|
||||
|
||||
test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems(
|
||||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, via );
|
||||
|
||||
int annulus = ( via->GetWidth() - via->GetDrillValue() ) / 2;
|
||||
|
||||
if( constraint.Value().HasMin() )
|
||||
{
|
||||
v_min = constraint.Value().Min();
|
||||
fail_min = annulus < v_min;
|
||||
}
|
||||
|
||||
if( constraint.Value().HasMax() )
|
||||
{
|
||||
v_max = constraint.Value().Max();
|
||||
fail_max = annulus > v_max;
|
||||
}
|
||||
|
||||
if( fail_min || fail_max )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ANNULUS );
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() + _( " (%s; actual annulus %s, constraint %s %s)" ),
|
||||
constraint.GetParentRule()->GetName(),
|
||||
MessageTextFromValue( userUnits(), annulus, true ),
|
||||
fail_min ? _( "minimum" ) : _( "maximum" ),
|
||||
MessageTextFromValue( userUnits(), fail_min ? v_min : v_max, true ) );
|
||||
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( item );
|
||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||
|
||||
ReportWithMarker( drcItem, via->GetPosition() );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_ANNULUS ) )
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
forEachGeometryItem( { PCB_VIA_T }, LSET::AllCuMask(), checkAnnulus );
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T>
|
||||
test::DRC_TEST_PROVIDER_ANNULUS::GetMatchingConstraintIds() const
|
||||
{
|
||||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH };
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_ANNULUS> dummy;
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2020 KiCad Developers.
|
||||
*
|
||||
* 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 <class_board.h>
|
||||
#include <common.h>
|
||||
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <connectivity/connectivity_algo.h>
|
||||
|
||||
#include <drc_proto/drc_engine.h>
|
||||
#include <drc_proto/drc_item.h>
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <drc_proto/drc_test_provider.h>
|
||||
|
||||
|
||||
/*
|
||||
Connectivity test provider. Not rule-driven.
|
||||
Errors generated:
|
||||
- DRCE_DANGLING_TRACK
|
||||
- DRCE_DANGLING_VIA
|
||||
- DRCE_ZONE_HAS_EMPTY_NET
|
||||
*/
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
class DRC_TEST_PROVIDER_CONNECTIVITY : public DRC_TEST_PROVIDER
|
||||
{
|
||||
public:
|
||||
DRC_TEST_PROVIDER_CONNECTIVITY()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DRC_TEST_PROVIDER_CONNECTIVITY()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Run() override;
|
||||
|
||||
virtual const wxString GetName() const override
|
||||
{
|
||||
return "connectivity";
|
||||
};
|
||||
|
||||
virtual const wxString GetDescription() const override
|
||||
{
|
||||
return "Tests board connectivity";
|
||||
}
|
||||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||
};
|
||||
|
||||
}; // namespace test
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run()
|
||||
{
|
||||
ReportStage( ( "Testing dangling pads/vias" ), 0, 2 );
|
||||
|
||||
BOARD* board = m_drcEngine->GetBoard();
|
||||
|
||||
std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity();
|
||||
connectivity->Clear();
|
||||
connectivity->Build( board ); // just in case. This really needs to be reliable.
|
||||
|
||||
|
||||
for( auto track : board->Tracks() )
|
||||
{
|
||||
bool exceedT = isErrorLimitExceeded( DRCE_DANGLING_TRACK );
|
||||
bool exceedV = isErrorLimitExceeded( DRCE_DANGLING_VIA );
|
||||
// Test for dangling items
|
||||
int code = track->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
|
||||
wxPoint pos;
|
||||
|
||||
if( track->Type() == PCB_VIA_T && exceedV )
|
||||
continue;
|
||||
else if( track->Type() == PCB_TRACE_T && exceedT )
|
||||
continue;
|
||||
|
||||
if( connectivity->TestTrackEndpointDangling( track, &pos ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( code );
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() );
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( track );
|
||||
ReportWithMarker( drcItem, pos );
|
||||
}
|
||||
|
||||
if( exceedV && exceedT )
|
||||
break;
|
||||
}
|
||||
|
||||
ReportStage( ( "Testing starved zones" ), 0, 2 );
|
||||
|
||||
/* test starved zones */
|
||||
for( auto zone : board->Zones() )
|
||||
{
|
||||
if( !zone->IsOnCopperLayer() )
|
||||
continue;
|
||||
|
||||
int netcode = zone->GetNetCode();
|
||||
// a netcode < 0 or > 0 and no pad in net is a error or strange
|
||||
// perhaps a "dead" net, which happens when all pads in this net were removed
|
||||
// Remark: a netcode < 0 should not happen (this is more a bug somewhere)
|
||||
int pads_in_net = ( netcode > 0 ) ? connectivity->GetPadCount( netcode ) : 1;
|
||||
|
||||
if( ( netcode < 0 ) || pads_in_net == 0 )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ZONE_HAS_EMPTY_NET );
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() );
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( zone );
|
||||
ReportWithMarker( drcItem, zone->GetPosition() );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_ZONE_HAS_EMPTY_NET ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ReportStage( ( "Testing unconnected ratlines" ), 0, 2 );
|
||||
|
||||
connectivity->RecalculateRatsnest();
|
||||
std::vector<CN_EDGE> edges;
|
||||
connectivity->GetUnconnectedEdges( edges );
|
||||
|
||||
for( const CN_EDGE& edge : edges )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS );
|
||||
|
||||
drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );
|
||||
ReportWithMarker( drcItem, edge.GetSourceNode()->Pos() );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_UNCONNECTED_ITEMS ) )
|
||||
break;
|
||||
}
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T>
|
||||
test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchingConstraintIds() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_CONNECTIVITY> dummy;
|
||||
}
|
|
@ -46,6 +46,7 @@
|
|||
- DRCE_CLEARANCE
|
||||
- DRCE_TRACKS_CROSSING
|
||||
- DRCE_ZONES_INTERSECT
|
||||
- DRCE_SHORTING_ITEMS
|
||||
|
||||
TODO: improve zone clearance check (super slow)
|
||||
*/
|
||||
|
@ -121,6 +122,8 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
|
|||
ReportStage( ("Testing copper zone clearances"), 1, 2 );
|
||||
testZones();
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2020 KiCad Developers.
|
||||
*
|
||||
* 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 <common.h>
|
||||
#include <class_board.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_pad.h>
|
||||
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <geometry/polygon_test_point_inside.h>
|
||||
|
||||
#include <geometry/seg.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <geometry/shape_rect.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
|
||||
#include <drc_proto/drc_engine.h>
|
||||
#include <drc_proto/drc_item.h>
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <drc_proto/drc_test_provider_clearance_base.h>
|
||||
|
||||
/*
|
||||
Couartyard clearance. Tests for malformed component courtyards and overlapping footprints.
|
||||
Generated errors:
|
||||
- DRCE_OVERLAPPING_FOOTPRINTS
|
||||
- DRCE_MISSING_COURTYARD
|
||||
- DRCE_MALFORMED_COURTYARD
|
||||
|
||||
TODO: do an actual clearance check instead of polygon intersection. Treat closed outlines
|
||||
as filled and allow open curves in the courtyard.
|
||||
*/
|
||||
|
||||
namespace test {
|
||||
|
||||
class DRC_TEST_PROVIDER_COURTYARD_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
|
||||
{
|
||||
public:
|
||||
DRC_TEST_PROVIDER_COURTYARD_CLEARANCE ()
|
||||
{
|
||||
m_isRuleDriven = false;
|
||||
}
|
||||
|
||||
virtual ~DRC_TEST_PROVIDER_COURTYARD_CLEARANCE ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Run() override;
|
||||
|
||||
virtual const wxString GetName() const override
|
||||
{
|
||||
return "courtyard_clearance";
|
||||
};
|
||||
|
||||
virtual const wxString GetDescription() const override
|
||||
{
|
||||
return "Tests components' courtyard clearance";
|
||||
}
|
||||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||
|
||||
private:
|
||||
|
||||
void testFootprintCourtyardDefinitions();
|
||||
void testOverlappingComponentCourtyards();
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
void test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
|
||||
{
|
||||
ReportStage( _("Testing component courtyard definitions"), 0, 2 );
|
||||
|
||||
for( MODULE* footprint : m_board->Modules() )
|
||||
{
|
||||
if( footprint->BuildPolyCourtyard() )
|
||||
{
|
||||
if( footprint->GetPolyCourtyardFront().OutlineCount() == 0
|
||||
&& footprint->GetPolyCourtyardBack().OutlineCount() == 0 )
|
||||
{
|
||||
if( isErrorLimitExceeded( DRCE_MISSING_COURTYARD ) )
|
||||
continue;
|
||||
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_COURTYARD );
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( drcItem->GetErrorText( ));
|
||||
|
||||
drcItem->SetItems( footprint );
|
||||
ReportWithMarker( drcItem, footprint->GetPosition() );
|
||||
}
|
||||
else
|
||||
{
|
||||
footprint->GetPolyCourtyardFront().BuildBBoxCaches();
|
||||
footprint->GetPolyCourtyardBack().BuildBBoxCaches();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !isErrorLimitExceeded( DRCE_MALFORMED_COURTYARD) )
|
||||
{
|
||||
wxString msg;
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MALFORMED_COURTYARD );
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() + _( " (not a closed shape)" ) );
|
||||
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( footprint );
|
||||
ReportWithMarker( drcItem, footprint->GetPosition() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testOverlappingComponentCourtyards()
|
||||
{
|
||||
ReportStage( _("Testing component courtyard overlap"), 0, 2 );
|
||||
|
||||
for( auto it1 = m_board->Modules().begin(); it1 != m_board->Modules().end(); it1++ )
|
||||
{
|
||||
MODULE* footprint = *it1;
|
||||
SHAPE_POLY_SET& footprintFront = footprint->GetPolyCourtyardFront();
|
||||
SHAPE_POLY_SET& footprintBack = footprint->GetPolyCourtyardBack();
|
||||
|
||||
if( footprintFront.OutlineCount() == 0 && footprintBack.OutlineCount() == 0 )
|
||||
continue; // No courtyards defined
|
||||
|
||||
for( auto it2 = it1 + 1; it2 != m_board->Modules().end(); it2++ )
|
||||
{
|
||||
MODULE* test = *it2;
|
||||
SHAPE_POLY_SET& testFront = test->GetPolyCourtyardFront();
|
||||
SHAPE_POLY_SET& testBack = test->GetPolyCourtyardBack();
|
||||
SHAPE_POLY_SET intersection;
|
||||
bool overlap = false;
|
||||
wxPoint pos;
|
||||
|
||||
if( footprintFront.OutlineCount() > 0 && testFront.OutlineCount() > 0
|
||||
&& footprintFront.BBoxFromCaches().Intersects( testFront.BBoxFromCaches() ) )
|
||||
{
|
||||
intersection.RemoveAllContours();
|
||||
intersection.Append( footprintFront );
|
||||
|
||||
// Build the common area between footprint and the test:
|
||||
intersection.BooleanIntersection( testFront, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
// If the intersection exists then they overlap
|
||||
if( intersection.OutlineCount() > 0 )
|
||||
{
|
||||
overlap = true;
|
||||
pos = (wxPoint) intersection.CVertex( 0, 0, -1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( footprintBack.OutlineCount() > 0 && testBack.OutlineCount() > 0
|
||||
&& footprintBack.BBoxFromCaches().Intersects( testBack.BBoxFromCaches() ) )
|
||||
{
|
||||
intersection.RemoveAllContours();
|
||||
intersection.Append( footprintBack );
|
||||
|
||||
intersection.BooleanIntersection( testBack, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
if( intersection.OutlineCount() > 0 )
|
||||
{
|
||||
overlap = true;
|
||||
pos = (wxPoint) intersection.CVertex( 0, 0, -1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( overlap )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_FOOTPRINTS );
|
||||
drcItem->SetItems( footprint, test );
|
||||
ReportWithMarker ( drcItem, pos );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS ) )
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::Run()
|
||||
{
|
||||
m_board = m_drcEngine->GetBoard();
|
||||
|
||||
// fixme: don't use polygon intersection but distance for clearance tests
|
||||
//m_largestClearance = 0;
|
||||
//ReportAux( "Worst courtyard clearance : %d nm", m_largestClearance );
|
||||
|
||||
testFootprintCourtyardDefinitions();
|
||||
testOverlappingComponentCourtyards();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::GetMatchingConstraintIds() const
|
||||
{
|
||||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE };
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE> dummy;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2020 KiCad Developers.
|
||||
*
|
||||
* 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 <class_board.h>
|
||||
#include <common.h>
|
||||
|
||||
#include <geometry/shape.h>
|
||||
|
||||
#include <drc_proto/drc_engine.h>
|
||||
#include <drc_proto/drc_item.h>
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <drc_proto/drc_test_provider.h>
|
||||
|
||||
/*
|
||||
"Disallow" test. Goes through all items, matching types/conditions drop errors.
|
||||
Errors generated:
|
||||
- DRCE_ALLOWED_ITEMS
|
||||
*/
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
class DRC_TEST_PROVIDER_DISALLOW : public DRC_TEST_PROVIDER
|
||||
{
|
||||
public:
|
||||
DRC_TEST_PROVIDER_DISALLOW()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DRC_TEST_PROVIDER_DISALLOW()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Run() override;
|
||||
|
||||
virtual const wxString GetName() const override
|
||||
{
|
||||
return "disallow";
|
||||
};
|
||||
|
||||
virtual const wxString GetDescription() const override
|
||||
{
|
||||
return "Tests for disallowed items (e.g. keepouts)";
|
||||
}
|
||||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
}; // namespace test
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_DISALLOW::Run()
|
||||
{
|
||||
if( !m_drcEngine->HasCorrectRulesForId( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW ) )
|
||||
{
|
||||
ReportAux( "No disallow constraints found. Skipping check." );
|
||||
return false;
|
||||
}
|
||||
|
||||
ReportStage( ("Testing for disallow constraints"), 0, 2 );
|
||||
|
||||
auto checkItem = [&] ( BOARD_ITEM *item ) -> bool
|
||||
{
|
||||
test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems(
|
||||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW, item );
|
||||
|
||||
if( constraint.Allowed() )
|
||||
return true;
|
||||
|
||||
if( ( constraint.GetAllowedLayers() & item->GetLayerSet() ).any() )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
|
||||
wxString msg;
|
||||
|
||||
msg.Printf(
|
||||
drcItem->GetErrorText() + _( " (%s)" ), constraint.GetParentRule()->GetName() );
|
||||
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( item );
|
||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||
|
||||
ReportWithMarker( drcItem, item->GetPosition() );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
forEachGeometryItem( {}, LSET::AllLayersMask(), checkItem );
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T>
|
||||
test::DRC_TEST_PROVIDER_DISALLOW::GetMatchingConstraintIds() const
|
||||
{
|
||||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW };
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_DISALLOW> dummy;
|
||||
}
|
|
@ -104,34 +104,36 @@ bool test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
|||
std::vector<DRAWSEGMENT*> boardOutline;
|
||||
std::vector<BOARD_ITEM*> boardItems;
|
||||
|
||||
auto queryBoardOutlineItems = [&] ( BOARD_ITEM *item ) -> int
|
||||
auto queryBoardOutlineItems = [&] ( BOARD_ITEM *item ) -> bool
|
||||
{
|
||||
boardOutline.push_back( dyn_cast<DRAWSEGMENT*>( item ) );
|
||||
return 0;
|
||||
return true;
|
||||
};
|
||||
|
||||
auto queryBoardGeometryItems = [&] ( BOARD_ITEM *item ) -> int
|
||||
auto queryBoardGeometryItems = [&] ( BOARD_ITEM *item ) -> bool
|
||||
{
|
||||
boardItems.push_back( item );
|
||||
return 0;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
forEachGeometryItem( { PCB_LINE_T }, LSET( Edge_Cuts ), queryBoardOutlineItems );
|
||||
forEachGeometryItem( {}, LSET::AllTechMask() | LSET::AllCuMask(), queryBoardGeometryItems );
|
||||
|
||||
wxString val;
|
||||
wxGetEnv( "WXTRACE", &val);
|
||||
|
||||
drc_dbg(2,"outline: %d items, board: %d items\n", boardOutline.size(), boardItems.size() );
|
||||
|
||||
bool stop = false;
|
||||
|
||||
for( auto outlineItem : boardOutline )
|
||||
{
|
||||
drc_dbg(12, "RefT %d %p\n", outlineItem->Type(), outlineItem );
|
||||
auto refShape = outlineItem->GetEffectiveShape();
|
||||
|
||||
for( auto boardItem : boardItems )
|
||||
{
|
||||
drc_dbg(12, "BoardT %d %p\n", boardItem->Type(), boardItem );
|
||||
drc_dbg(10, "RefT %d %p %s %d\n", outlineItem->Type(), outlineItem, outlineItem->GetClass(), outlineItem->GetLayer() );
|
||||
drc_dbg(10, "BoardT %d %p %s %d\n", boardItem->Type(), boardItem, boardItem->GetClass(), boardItem->GetLayer() );
|
||||
|
||||
auto shape = boardItem->GetEffectiveShape();
|
||||
|
||||
|
@ -154,10 +156,21 @@ bool test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
|||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||
|
||||
ReportWithMarker( drcItem, refShape->Centre() );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_COPPER_EDGE_CLEARANCE ) )
|
||||
{
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( stop )
|
||||
break;
|
||||
}
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2020 KiCad Developers.
|
||||
*
|
||||
* 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 <class_board.h>
|
||||
#include <class_track.h>
|
||||
#include <common.h>
|
||||
|
||||
#include <drc_proto/drc_engine.h>
|
||||
#include <drc_proto/drc_item.h>
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <drc_proto/drc_test_provider.h>
|
||||
|
||||
#include <kiway.h>
|
||||
#include <netlist_reader/pcb_netlist.h>
|
||||
|
||||
/*
|
||||
Layout-versus-schematic (LVS) test.
|
||||
|
||||
Errors generated:
|
||||
- DRCE_MISSING_FOOTPRINT
|
||||
- DRCE_DUPLICATE_FOOTPRINT
|
||||
- DRCE_EXTRA_FOOTPRINT
|
||||
|
||||
TODO:
|
||||
- cross-check PCB netlist against SCH netlist
|
||||
- cross-check PCB fields against SCH fields
|
||||
*/
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
class DRC_TEST_PROVIDER_LVS : public DRC_TEST_PROVIDER
|
||||
{
|
||||
public:
|
||||
DRC_TEST_PROVIDER_LVS()
|
||||
{
|
||||
m_isRuleDriven = false;
|
||||
}
|
||||
|
||||
virtual ~DRC_TEST_PROVIDER_LVS()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Run() override;
|
||||
|
||||
virtual const wxString GetName() const override
|
||||
{
|
||||
return "LVS";
|
||||
};
|
||||
|
||||
virtual const wxString GetDescription() const override
|
||||
{
|
||||
return "Performs layout-vs-schematics integity check";
|
||||
}
|
||||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||
|
||||
private:
|
||||
|
||||
bool fetchNetlistFromSchematic( NETLIST& aNetlist );
|
||||
void testFootprints( NETLIST& aNetlist );
|
||||
};
|
||||
|
||||
}; // namespace test
|
||||
|
||||
|
||||
void test::DRC_TEST_PROVIDER_LVS::testFootprints( NETLIST& aNetlist )
|
||||
{
|
||||
wxString msg;
|
||||
BOARD* board = m_drcEngine->GetBoard();
|
||||
|
||||
auto comp = []( const MODULE* x, const MODULE* y ) {
|
||||
return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
|
||||
};
|
||||
|
||||
auto mods = std::set<MODULE*, decltype( comp )>( comp );
|
||||
|
||||
for( MODULE* mod : board->Modules() )
|
||||
{
|
||||
auto ins = mods.insert( mod );
|
||||
|
||||
if( !ins.second )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_DUPLICATE_FOOTPRINT );
|
||||
drcItem->SetItems( mod, *ins.first );
|
||||
|
||||
ReportWithMarker( drcItem, mod->GetPosition() );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_DUPLICATE_FOOTPRINT ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Search for component footprints in the netlist but not on the board.
|
||||
for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
|
||||
{
|
||||
COMPONENT* component = aNetlist.GetComponent( ii );
|
||||
MODULE* module = board->FindModuleByReference( component->GetReference() );
|
||||
|
||||
if( module == nullptr )
|
||||
{
|
||||
msg.Printf( _( "Missing footprint %s (%s)" ), component->GetReference(),
|
||||
component->GetValue() );
|
||||
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_FOOTPRINT );
|
||||
|
||||
drcItem->SetErrorMessage( msg );
|
||||
Report( drcItem );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_MISSING_FOOTPRINT ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for( auto module : mods )
|
||||
{
|
||||
COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
|
||||
|
||||
if( component == NULL )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_EXTRA_FOOTPRINT );
|
||||
|
||||
drcItem->SetItems( module );
|
||||
ReportWithMarker( drcItem, module->GetPosition() );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_EXTRA_FOOTPRINT ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_LVS::fetchNetlistFromSchematic( NETLIST& aNetlist )
|
||||
{
|
||||
// fixme: make it work without dependency on EDIT_FRAME/kiway
|
||||
#if 0
|
||||
std::string payload;
|
||||
|
||||
Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_GET_NETLIST, payload, nullptr );
|
||||
|
||||
try
|
||||
{
|
||||
auto lineReader = new STRING_LINE_READER( payload, _( "Eeschema netlist" ) );
|
||||
KICAD_NETLIST_READER netlistReader( lineReader, &aNetlist );
|
||||
netlistReader.LoadNetlist();
|
||||
}
|
||||
catch( const IO_ERROR& )
|
||||
{
|
||||
assert( false ); // should never happen
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_LVS::Run()
|
||||
{
|
||||
ReportStage( _( "Layout-vs-Schematic checks..." ), 0, 2 );
|
||||
|
||||
#if 0
|
||||
|
||||
if ( !Kiface().IsSingle() )
|
||||
{
|
||||
NETLIST netlist; // fixme: fetch from schematic without referring directly to the FRAME
|
||||
|
||||
if( ! fetchNetlistFromSchematic( netlist ) )
|
||||
{
|
||||
ReportAux( _( "Unable to fetch the schematic netlist. Skipping LVS checks. ") );
|
||||
return true;
|
||||
}
|
||||
|
||||
testFootprints( netlist );
|
||||
}
|
||||
#endif
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_LVS::GetMatchingConstraintIds() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_LVS> dummy;
|
||||
}
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2020 KiCad Developers.
|
||||
*
|
||||
* 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 <class_board.h>
|
||||
#include <class_track.h>
|
||||
#include <common.h>
|
||||
|
||||
#include <class_module.h>
|
||||
#include <class_pcb_text.h>
|
||||
|
||||
#include <drc_proto/drc_engine.h>
|
||||
#include <drc_proto/drc_item.h>
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <drc_proto/drc_test_provider.h>
|
||||
|
||||
#include <ws_draw_item.h>
|
||||
#include <ws_proxy_view_item.h>
|
||||
|
||||
/*
|
||||
Miscellaneous tests:
|
||||
|
||||
- DRCE_DISABLED_LAYER_ITEM, ///< item on a disabled layer
|
||||
- DRCE_INVALID_OUTLINE, ///< invalid board outline
|
||||
- DRCE_UNRESOLVED_VARIABLE,
|
||||
|
||||
TODO:
|
||||
- if grows too big, split into separate providers
|
||||
*/
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
class DRC_TEST_PROVIDER_MISC : public DRC_TEST_PROVIDER
|
||||
{
|
||||
public:
|
||||
DRC_TEST_PROVIDER_MISC()
|
||||
{
|
||||
m_isRuleDriven = false;
|
||||
}
|
||||
|
||||
virtual ~DRC_TEST_PROVIDER_MISC()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Run() override;
|
||||
|
||||
virtual const wxString GetName() const override
|
||||
{
|
||||
return "miscellanous";
|
||||
};
|
||||
|
||||
virtual const wxString GetDescription() const override
|
||||
{
|
||||
return "Misc checks (board outline, missing textvars)";
|
||||
}
|
||||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||
|
||||
private:
|
||||
void testOutline();
|
||||
void testDisabledLayers();
|
||||
void testTextVars();
|
||||
|
||||
BOARD* m_board;
|
||||
};
|
||||
|
||||
}; // namespace test
|
||||
|
||||
|
||||
void test::DRC_TEST_PROVIDER_MISC::testOutline()
|
||||
{
|
||||
wxPoint error_loc( m_board->GetBoardEdgesBoundingBox().GetPosition() );
|
||||
|
||||
SHAPE_POLY_SET boardOutlines;
|
||||
|
||||
if( m_board->GetBoardPolygonOutlines( boardOutlines, nullptr, &error_loc ) )
|
||||
return;
|
||||
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() + _( " (not a closed shape)" ) );
|
||||
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( m_board );
|
||||
|
||||
ReportWithMarker( drcItem, error_loc );
|
||||
}
|
||||
|
||||
|
||||
void test::DRC_TEST_PROVIDER_MISC::testDisabledLayers()
|
||||
{
|
||||
LSET disabledLayers = m_board->GetEnabledLayers().flip();
|
||||
|
||||
|
||||
// Perform the test only for copper layers
|
||||
disabledLayers &= LSET::AllCuMask();
|
||||
|
||||
auto checkDisabledLayers = [&]( BOARD_ITEM* item ) -> bool {
|
||||
if( ( disabledLayers & item->GetLayerSet() ).any() )
|
||||
{
|
||||
wxString msg;
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_DISABLED_LAYER_ITEM );
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() + _( " (layer %s)" ), item->GetLayerName() );
|
||||
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( item );
|
||||
|
||||
ReportWithMarker( drcItem, item->GetPosition() );
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// fixme: what about graphical items?
|
||||
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_ZONE_AREA_T, PCB_PAD_T },
|
||||
LSET::AllLayersMask(), checkDisabledLayers );
|
||||
}
|
||||
|
||||
void test::DRC_TEST_PROVIDER_MISC::testTextVars()
|
||||
{
|
||||
auto checkUnresolvedTextVar = [&]( EDA_ITEM* item ) -> bool {
|
||||
EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
|
||||
|
||||
assert( text );
|
||||
|
||||
|
||||
if( text->GetShownText().Matches( wxT( "*${*}*" ) ) )
|
||||
{
|
||||
if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) )
|
||||
return false;
|
||||
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
|
||||
drcItem->SetItems( item );
|
||||
|
||||
ReportWithMarker( drcItem, item->GetPosition() );
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
forEachGeometryItem(
|
||||
{ PCB_MODULE_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(), checkUnresolvedTextVar );
|
||||
|
||||
WS_DRAW_ITEM_LIST wsItems;
|
||||
|
||||
auto worksheet = m_drcEngine->GetWorksheet();
|
||||
|
||||
if( !worksheet )
|
||||
return;
|
||||
|
||||
wsItems.SetMilsToIUfactor( IU_PER_MILS );
|
||||
wsItems.BuildWorkSheetGraphicList( worksheet->GetPageInfo(), worksheet->GetTitleBlock() );
|
||||
|
||||
for( WS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() )
|
||||
{
|
||||
if( WS_DRAW_ITEM_TEXT* text = dynamic_cast<WS_DRAW_ITEM_TEXT*>( item ) )
|
||||
{
|
||||
if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) )
|
||||
return;
|
||||
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
|
||||
drcItem->SetItems( text );
|
||||
|
||||
ReportWithMarker( drcItem, text->GetPosition() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_MISC::Run()
|
||||
{
|
||||
m_board = m_drcEngine->GetBoard();
|
||||
|
||||
ReportStage( _( "Test board outline" ), 0, 3 );
|
||||
testOutline();
|
||||
|
||||
ReportStage( _( "Test disabled layers" ), 1, 3 );
|
||||
testDisabledLayers();
|
||||
|
||||
ReportStage( _( "Test text variables" ), 2, 3 );
|
||||
testTextVars();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_MISC::GetMatchingConstraintIds() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_MISC> dummy;
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2020 KiCad Developers.
|
||||
*
|
||||
* 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 <common.h>
|
||||
#include <class_board.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_pad.h>
|
||||
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <geometry/polygon_test_point_inside.h>
|
||||
|
||||
#include <geometry/seg.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <geometry/shape_rect.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
|
||||
#include <drc_proto/drc_engine.h>
|
||||
#include <drc_proto/drc_item.h>
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <drc_proto/drc_test_provider_clearance_base.h>
|
||||
|
||||
/*
|
||||
Silk to pads clearance test. Check all pads against silkscreen (mask opening in the pad vs silkscreen)
|
||||
Errors generated:
|
||||
- DRCE_SILK_ON_PADS
|
||||
|
||||
TODO:
|
||||
- tester only looks for edge crossings. it doesn't check if items are inside/outside the board area.
|
||||
*/
|
||||
|
||||
namespace test {
|
||||
|
||||
class DRC_TEST_PROVIDER_SILK_TO_PAD : public DRC_TEST_PROVIDER
|
||||
{
|
||||
public:
|
||||
DRC_TEST_PROVIDER_SILK_TO_PAD ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DRC_TEST_PROVIDER_SILK_TO_PAD()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Run() override;
|
||||
|
||||
virtual const wxString GetName() const override
|
||||
{
|
||||
return "silk_to_pad";
|
||||
};
|
||||
|
||||
virtual const wxString GetDescription() const override
|
||||
{
|
||||
return "Tests for silkscreen covering components pads";
|
||||
}
|
||||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_SILK_TO_PAD::Run()
|
||||
{
|
||||
m_board = m_drcEngine->GetBoard();
|
||||
|
||||
DRC_CONSTRAINT worstClearanceConstraint;
|
||||
m_largestClearance = 0;
|
||||
|
||||
if( m_drcEngine->QueryWorstConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_SILK_TO_PAD, worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) )
|
||||
{
|
||||
m_largestClearance = worstClearanceConstraint.m_Value.Min();
|
||||
}
|
||||
|
||||
ReportAux( "Worst clearance : %d nm", m_largestClearance );
|
||||
ReportStage( ("Testing pads vs silkscreen clearance"), 0, 2 );
|
||||
|
||||
|
||||
std::vector<DRAWSEGMENT*> boardOutline;
|
||||
std::vector<BOARD_ITEM*> boardItems;
|
||||
|
||||
auto queryBoardOutlineItems = [&] ( BOARD_ITEM *item ) -> int
|
||||
{
|
||||
boardOutline.push_back( dyn_cast<DRAWSEGMENT*>( item ) );
|
||||
};
|
||||
|
||||
auto queryBoardGeometryItems = [&] ( BOARD_ITEM *item ) -> int
|
||||
{
|
||||
boardItems.push_back( item );
|
||||
};
|
||||
|
||||
|
||||
|
||||
forEachGeometryItem( { PCB_LINE_T }, LSET( Edge_Cuts ), queryBoardOutlineItems );
|
||||
forEachGeometryItem( {}, LSET::AllTechMask() | LSET::AllCuMask(), queryBoardGeometryItems );
|
||||
|
||||
|
||||
drc_dbg(2,"outline: %d items, board: %d items\n", boardOutline.size(), boardItems.size() );
|
||||
|
||||
for( auto outlineItem : boardOutline )
|
||||
{
|
||||
//printf("RefT %d\n", outlineItem->Type() );
|
||||
auto refShape = outlineItem->GetEffectiveShape();
|
||||
|
||||
for( auto boardItem : boardItems )
|
||||
{
|
||||
// printf("BoardT %d\n", boardItem->Type() );
|
||||
|
||||
auto shape = boardItem->GetEffectiveShape();
|
||||
|
||||
test::DRC_RULE* rule = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, outlineItem, boardItem );
|
||||
int minClearance = rule->GetConstraint().GetValue().Min();
|
||||
int actual;
|
||||
|
||||
if( refShape->Collide( shape.get(), minClearance, &actual ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_COPPER_EDGE_CLEARANCE );
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
rule->GetName(),
|
||||
MessageTextFromValue( userUnits(), minClearance, true ),
|
||||
MessageTextFromValue( userUnits(), actual, true ) );
|
||||
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( outlineItem, boardItem );
|
||||
drcItem->SetViolatingRule( rule );
|
||||
|
||||
ReportWithMarker( drcItem, refShape->Centre() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::GetMatchingConstraintIds() const
|
||||
{
|
||||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE };
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_EDGE_CLEARANCE> dummy;
|
||||
}
|
|
@ -22,44 +22,32 @@
|
|||
*/
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_track.h>
|
||||
#include <common.h>
|
||||
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <geometry/polygon_test_point_inside.h>
|
||||
|
||||
#include <geometry/seg.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <geometry/shape_rect.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
|
||||
#include <drc_proto/drc_engine.h>
|
||||
#include <drc_proto/drc_item.h>
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <drc_proto/drc_test_provider_clearance_base.h>
|
||||
#include <drc_proto/drc_test_provider.h>
|
||||
|
||||
|
||||
/*
|
||||
Drilled hole size test. scans vias/through-hole pads and checks for min drill sizes
|
||||
Track width test. As the name says, checks width of the tracks (including segments and arcs)
|
||||
Errors generated:
|
||||
- DRCE_TOO_SMALL_DRILL
|
||||
- DRCE_TOO_SMALL_MICROVIA_DRILL
|
||||
|
||||
TODO: max drill size check
|
||||
- DRCE_TRACK_WIDTH
|
||||
*/
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
class DRC_TEST_PROVIDER_HOLE_SIZE : public DRC_TEST_PROVIDER
|
||||
class DRC_TEST_PROVIDER_TRACK_WIDTH : public DRC_TEST_PROVIDER
|
||||
{
|
||||
public:
|
||||
DRC_TEST_PROVIDER_HOLE_SIZE()
|
||||
DRC_TEST_PROVIDER_TRACK_WIDTH()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DRC_TEST_PROVIDER_HOLE_SIZE()
|
||||
virtual ~DRC_TEST_PROVIDER_TRACK_WIDTH()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -67,137 +55,105 @@ public:
|
|||
|
||||
virtual const wxString GetName() const override
|
||||
{
|
||||
return "hole_size";
|
||||
return "width";
|
||||
};
|
||||
|
||||
virtual const wxString GetDescription() const override
|
||||
{
|
||||
return "Tests sizes of drilled holes (via/pad drills)";
|
||||
return "Tests track widths";
|
||||
}
|
||||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||
|
||||
private:
|
||||
bool checkVia( VIA* via );
|
||||
bool checkPad( D_PAD* aPad );
|
||||
|
||||
BOARD* m_board;
|
||||
};
|
||||
|
||||
}; // namespace test
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_HOLE_SIZE::Run()
|
||||
bool test::DRC_TEST_PROVIDER_TRACK_WIDTH::Run()
|
||||
{
|
||||
ReportStage( ( "Testing pad holes" ), 0, 2 );
|
||||
|
||||
for( auto module : m_board->Modules() )
|
||||
if( !m_drcEngine->HasCorrectRulesForId(
|
||||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH ) )
|
||||
{
|
||||
for( auto pad : module->Pads() )
|
||||
{
|
||||
if( checkPad( pad ) )
|
||||
break;
|
||||
}
|
||||
ReportAux( "No track width constraints found. Skipping check." );
|
||||
return false;
|
||||
}
|
||||
|
||||
ReportStage( ( "Testing via/microvia holes" ), 0, 2 );
|
||||
ReportStage( ( "Testing track widths" ), 0, 2 );
|
||||
|
||||
std::vector<VIA*> vias;
|
||||
auto checkTrackWidth = [&]( BOARD_ITEM* item ) -> bool {
|
||||
int width;
|
||||
VECTOR2I p0;
|
||||
|
||||
for( auto track : m_board->Tracks() )
|
||||
if( auto arc = dyn_cast<ARC*>( item ) )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T )
|
||||
{
|
||||
vias.push_back( static_cast<VIA*>( track ) );
|
||||
width = arc->GetWidth();
|
||||
p0 = arc->GetStart();
|
||||
}
|
||||
else if( auto trk = dyn_cast<TRACK*>( item ) )
|
||||
{
|
||||
width = trk->GetWidth();
|
||||
p0 = ( trk->GetStart() + trk->GetEnd() ) / 2;
|
||||
}
|
||||
|
||||
test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems(
|
||||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH, item );
|
||||
|
||||
for( auto via : vias )
|
||||
bool fail_min = false, fail_max = false;
|
||||
int constraintWidth;
|
||||
|
||||
if( constraint.Value().HasMin() && width < constraint.Value().Min() )
|
||||
{
|
||||
if( checkVia( via ) )
|
||||
break;
|
||||
fail_min = true;
|
||||
constraintWidth = constraint.Value().Min();
|
||||
}
|
||||
|
||||
if( constraint.Value().HasMax() && width > constraint.Value().Max() )
|
||||
{
|
||||
fail_max = true;
|
||||
constraintWidth = constraint.Value().Max();
|
||||
}
|
||||
|
||||
if( fail_min || fail_max )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TRACK_WIDTH );
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() + _( " (%s; width %s, constraint %s %s)" ),
|
||||
constraint.GetParentRule()->GetName(),
|
||||
MessageTextFromValue( userUnits(), width, true ),
|
||||
fail_min ? _( "minimum" ) : _( "maximum" ),
|
||||
MessageTextFromValue( userUnits(), constraintWidth, true ) );
|
||||
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( item );
|
||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||
|
||||
ReportWithMarker( drcItem, p0 );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_TRACK_WIDTH ) )
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T }, LSET::AllCuMask(), checkTrackWidth );
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( D_PAD* aPad )
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T>
|
||||
test::DRC_TEST_PROVIDER_TRACK_WIDTH::GetMatchingConstraintIds() const
|
||||
{
|
||||
int holeSize = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y );
|
||||
|
||||
if( holeSize == 0 )
|
||||
return true;
|
||||
|
||||
auto rule = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE, aPad );
|
||||
auto minHole = rule->GetConstraint().GetValue().Min();
|
||||
|
||||
accountCheck( rule );
|
||||
|
||||
if( holeSize < minHole )
|
||||
{
|
||||
wxString msg;
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ),
|
||||
MessageTextFromValue( userUnits(), minHole, true ),
|
||||
MessageTextFromValue( userUnits(), holeSize, true ) );
|
||||
|
||||
drcItem->SetViolatingRule( rule );
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( aPad );
|
||||
|
||||
ReportWithMarker( drcItem, aPad->GetPosition() );
|
||||
|
||||
return isErrorLimitExceeded( DRCE_TOO_SMALL_DRILL );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkVia( VIA* via )
|
||||
{
|
||||
auto rule = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE, via );
|
||||
auto minHole = rule->GetConstraint().GetValue().Min();
|
||||
|
||||
accountCheck( rule );
|
||||
|
||||
if( via->GetDrillValue() < minHole )
|
||||
{
|
||||
wxString msg;
|
||||
int errorCode = via->GetViaType() == VIATYPE::MICROVIA ? DRCE_TOO_SMALL_MICROVIA_DRILL :
|
||||
DRCE_TOO_SMALL_DRILL;
|
||||
|
||||
DRC_ITEM* drcItem = DRC_ITEM::Create( errorCode );
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ),
|
||||
MessageTextFromValue( userUnits(), minHole, true ),
|
||||
MessageTextFromValue( userUnits(), via->GetDrillValue(), true ) );
|
||||
|
||||
drcItem->SetViolatingRule( rule );
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( via );
|
||||
|
||||
ReportWithMarker( drcItem, via->GetPosition() );
|
||||
|
||||
return isErrorLimitExceeded( errorCode );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_HOLE_SIZE::GetMatchingConstraintIds() const
|
||||
{
|
||||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_HOLE_SIZE };
|
||||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_TRACK_WIDTH };
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_HOLE_SIZE> dummy;
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_TRACK_WIDTH> dummy;
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2020 KiCad Developers.
|
||||
*
|
||||
* 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 <class_board.h>
|
||||
#include <class_track.h>
|
||||
#include <common.h>
|
||||
|
||||
#include <drc_proto/drc_engine.h>
|
||||
#include <drc_proto/drc_item.h>
|
||||
#include <drc_proto/drc_rule.h>
|
||||
#include <drc_proto/drc_test_provider.h>
|
||||
|
||||
|
||||
/*
|
||||
Via diameter test.
|
||||
|
||||
Errors generated:
|
||||
- DRCE_TOO_SMALL_VIA
|
||||
- DRCE_TOO_SMALL_MICROVIA
|
||||
*/
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
class DRC_TEST_PROVIDER_VIA_DIAMETER : public DRC_TEST_PROVIDER
|
||||
{
|
||||
public:
|
||||
DRC_TEST_PROVIDER_VIA_DIAMETER()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DRC_TEST_PROVIDER_VIA_DIAMETER()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Run() override;
|
||||
|
||||
virtual const wxString GetName() const override
|
||||
{
|
||||
return "diameter";
|
||||
};
|
||||
|
||||
virtual const wxString GetDescription() const override
|
||||
{
|
||||
return "Tests via diameters";
|
||||
}
|
||||
|
||||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override;
|
||||
};
|
||||
|
||||
}; // namespace test
|
||||
|
||||
|
||||
bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run()
|
||||
{
|
||||
if( !m_drcEngine->HasCorrectRulesForId(
|
||||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER ) )
|
||||
{
|
||||
ReportAux( "No diameter constraints found. Skipping check." );
|
||||
return false;
|
||||
}
|
||||
|
||||
ReportStage( ( "Testing via diameters" ), 0, 2 );
|
||||
|
||||
auto checkViaDiameter = [&]( BOARD_ITEM* item ) -> bool {
|
||||
auto via = dyn_cast<VIA*>( item );
|
||||
|
||||
// fixme: move to pad stack check?
|
||||
if( !via )
|
||||
return true;
|
||||
|
||||
test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems(
|
||||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER, item );
|
||||
|
||||
bool fail_min = false, fail_max = false;
|
||||
int constraintDiameter;
|
||||
int diameter = via->GetWidth();
|
||||
|
||||
if( constraint.Value().HasMin() && diameter < constraint.Value().Min() )
|
||||
{
|
||||
fail_min = true;
|
||||
constraintDiameter = constraint.Value().Min();
|
||||
}
|
||||
|
||||
if( constraint.Value().HasMax() && diameter > constraint.Value().Max() )
|
||||
{
|
||||
fail_max = true;
|
||||
constraintDiameter = constraint.Value().Max();
|
||||
}
|
||||
|
||||
if( fail_min || fail_max )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_VIA_DIAMETER );
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( drcItem->GetErrorText() + _( " (%s; diameter %s, constraint %s %s)" ),
|
||||
constraint.GetParentRule()->GetName(),
|
||||
MessageTextFromValue( userUnits(), diameter, true ),
|
||||
fail_min ? _( "minimum" ) : _( "maximum" ),
|
||||
MessageTextFromValue( userUnits(), constraintDiameter, true ) );
|
||||
|
||||
drcItem->SetErrorMessage( msg );
|
||||
drcItem->SetItems( item );
|
||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||
|
||||
ReportWithMarker( drcItem, via->GetPosition() );
|
||||
|
||||
if( isErrorLimitExceeded( DRCE_VIA_DIAMETER ) )
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
forEachGeometryItem( { PCB_VIA_T }, LSET::AllCuMask(), checkViaDiameter );
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::set<test::DRC_CONSTRAINT_TYPE_T>
|
||||
test::DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchingConstraintIds() const
|
||||
{
|
||||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER };
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_VIA_DIAMETER> dummy;
|
||||
}
|
Loading…
Reference in New Issue