From 52fefd15e0f6ac1b0428df4ff96f9a49d39f69bf Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Wed, 12 Aug 2020 00:15:50 +0200 Subject: [PATCH] common: include drc_proto keywords in the main DRC parser --- common/drc_rules.keywords | 8 + qa/drc_proto/drc_engine.cpp | 91 +++++++----- qa/drc_proto/drc_engine.h | 54 ++++++- qa/drc_proto/drc_item.cpp | 71 ++++----- qa/drc_proto/drc_item.h | 4 +- qa/drc_proto/drc_rule.cpp | 4 +- qa/drc_proto/drc_rule.h | 68 ++++----- qa/drc_proto/drc_rule_parser.cpp | 13 +- qa/drc_proto/drc_test_provider.cpp | 139 +++++++++++++++++- qa/drc_proto/drc_test_provider.h | 8 +- .../drc_test_provider_copper_clearance.cpp | 25 ++-- .../drc_test_provider_edge_clearance.cpp | 81 +++++----- .../drc_test_provider_hole_clearance.cpp | 6 +- qa/drc_proto/drc_test_provider_hole_size.cpp | 4 +- qa/drc_proto/footprint_tester.cpp | 2 +- 15 files changed, 390 insertions(+), 188 deletions(-) diff --git a/common/drc_rules.keywords b/common/drc_rules.keywords index 664b79affa..49e8585474 100644 --- a/common/drc_rules.keywords +++ b/common/drc_rules.keywords @@ -26,3 +26,11 @@ track_width version via zone +edge_clearance +hole_clearance +courtyard_clearance +silk_to_pad +silk_to_silk +match_lengths +match_skew +diff_pair \ No newline at end of file diff --git a/qa/drc_proto/drc_engine.cpp b/qa/drc_proto/drc_engine.cpp index 00562e02cc..f3b12ca160 100644 --- a/qa/drc_proto/drc_engine.cpp +++ b/qa/drc_proto/drc_engine.cpp @@ -48,8 +48,15 @@ test::DRC_ENGINE::DRC_ENGINE( BOARD* aBoard, BOARD_DESIGN_SETTINGS *aSettings ) test::DRC_ENGINE::~DRC_ENGINE() { - for( DRC_ITEM* item : m_drcItems ) - delete item; +} + +test::DRC_REPORT::~DRC_REPORT() +{ + for( auto item : m_entries ) + { + if ( item.m_marker ) + delete item.m_marker; + } } /*void test::DRC_ENGINE::AddMarker( MARKER_PCB* aMarker ) @@ -111,31 +118,6 @@ void test::DRC_ENGINE::inferImplicitRules() } -static const int drc_debug_level = 0; - -void test::drc_dbg( int level, const char* fmt, ... ) -{ -#ifdef DEBUG - long dlevel = drc_debug_level; - wxString dlevelstr; - if( wxGetEnv( "DRC_DEBUG_LEVEL", &dlevelstr ) ) - { - dlevelstr.ToLong( &dlevel ); - } - - - if(level < dlevel) // fixme: tom's debugging. - { - va_list ap; - va_start( ap, fmt ); - fprintf( stderr, "drc: " ); - vfprintf( stderr, fmt, ap ); - va_end( ap ); - } -#endif -} - - bool test::DRC_ENGINE::CompileRules() { ReportAux( wxString::Format( "Compiling Rules (%d rules, %d conditions): ", m_rules.size(), m_ruleConditions.size() ) ); @@ -176,7 +158,7 @@ bool test::DRC_ENGINE::CompileRules() { rcons->conditions.push_back( condition ); - bool compileOk = condition->Compile( &NULL_REPORTER::GetInstance() ); + bool compileOk = condition->Compile(); ReportAux( wxString::Format( " |- condition: '%s' compile: %s", condition->m_TargetRuleName, compileOk ? "OK" : "ERROR") ); @@ -198,6 +180,7 @@ 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(); for( auto provider : m_testProviders ) @@ -268,22 +251,25 @@ test::DRC_RULE* test::DRC_ENGINE::EvalRulesForItems( test::DRC_RULE_ID_T ruleID, } -void test::DRC_ENGINE::Report( DRC_ITEM* aItem, ::MARKER_PCB *aMarker ) +void test::DRC_ENGINE::Report( std::shared_ptr aItem, ::MARKER_PCB *aMarker ) { - m_drcItems.push_back( aItem ); - m_markers.push_back( aMarker ); + m_drcReport->AddItem( aItem, aMarker ); + if( m_reporter ) { m_reporter->Report ( wxString::Format( "Test '%s': violation of rule '%s' : %s (code %d)", - aItem->GetViolatingTest()->GetName(), - aItem->GetViolatingRule()->GetName(), - aItem->GetErrorMessage(), - aItem->GetErrorCode() ), RPT_SEVERITY_ERROR /* fixme */ ); - if( aMarker ) - { - m_reporter->Report( wxString::Format( " |- violating position (%d, %d)", aMarker->GetPos().x, aMarker->GetPos().y ), - RPT_SEVERITY_ERROR /* fixme */ ); - } + aItem->GetViolatingTest()->GetName(), + aItem->GetViolatingRule()->GetName(), + aItem->GetErrorMessage(), + aItem->GetErrorCode() ), RPT_SEVERITY_ERROR /* fixme */ ); + + wxString violatingItemsStr = "Violating items: "; + + if( aMarker ) + { + m_reporter->Report( wxString::Format( " |- violating position (%d, %d)", aMarker->GetPos().x, aMarker->GetPos().y ), + RPT_SEVERITY_ERROR /* fixme */ ); + } } } @@ -358,3 +344,28 @@ bool test::DRC_ENGINE::HasCorrectRulesForId( test::DRC_RULE_ID_T ruleID ) return m_ruleMap[ruleID]->defaultRule != nullptr; } + +bool test::DRC_ENGINE::QueryWorstConstraint( test::DRC_RULE_ID_T aRuleId, test::DRC_CONSTRAINT& aConstraint, test::DRC_CONSTRAINT_QUERY_T aQueryType ) +{ + if( aQueryType == DRCCQ_LARGEST_MINIMUM ) + { + int worst = 0; + for( auto rule : QueryRulesById( test::DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE ) ) + { + if( rule->GetConstraint().m_Value.HasMin() ) + { + int current = rule->GetConstraint().m_Value.Min(); + + if( current > worst ) + { + worst = current; + aConstraint = rule->GetConstraint(); + } + } + } + + return worst > 0; + } + + return false; +} diff --git a/qa/drc_proto/drc_engine.h b/qa/drc_proto/drc_engine.h index e3f65a0bad..364a438e54 100644 --- a/qa/drc_proto/drc_engine.h +++ b/qa/drc_proto/drc_engine.h @@ -53,6 +53,13 @@ class NETLIST; class PROGRESS_REPORTER; class REPORTER; +//#ifdef DEBUG +#define drc_dbg(level, fmt, ...) \ + wxLogTrace( "drc_proto", fmt, __VA_ARGS__ ); +//#else +//#define drc_dbg(level, fmt, ...) +//#endif + namespace test { @@ -62,6 +69,12 @@ class DRC_RULE; class DRC_TEST_PROVIDER; class DRC_CONSTRAINT; +enum DRC_CONSTRAINT_QUERY_T +{ + DRCCQ_LARGEST_MINIMUM = 0 + // fixme: more to come I guess... +}; + /// DRC error codes: enum PCB_DRC_CODE { @@ -103,6 +116,33 @@ enum PCB_DRC_CODE DRCE_LAST = DRCE_UNRESOLVED_VARIABLE }; +class DRC_REPORT +{ +public: + struct ENTRY + { + std::shared_ptr m_item; + ::MARKER_PCB* m_marker; + }; + + typedef std::vector ENTRIES; + + DRC_REPORT() {}; + ~DRC_REPORT(); + + void AddItem( std::shared_ptr aItem, ::MARKER_PCB *aMarker = nullptr) + { + ENTRY ent; + ent.m_item = aItem; + ent.m_marker = aMarker; + m_entries.push_back(ent); + } + + const ENTRIES& GetReportEntries() const { return m_entries; }; + +private: + ENTRIES m_entries; +}; /** * Design Rule Checker object that performs all the DRC tests. The output of @@ -157,13 +197,19 @@ public: bool CompileRules(); - void Report( DRC_ITEM* aItem, ::MARKER_PCB *Marker ); + void Report( std::shared_ptr aItem, ::MARKER_PCB *Marker ); void ReportProgress( double aProgress ); void ReportStage ( const wxString& aStageName, int index, int total ); void ReportAux( const wxString& aStr ); + std::shared_ptr GetReport() const { return m_drcReport; } + + bool QueryWorstConstraint( DRC_RULE_ID_T aRuleId, test::DRC_CONSTRAINT& aConstraint, DRC_CONSTRAINT_QUERY_T aQueryType ); + + private: + void freeCompiledRules(); struct RULE_WITH_CONDITIONS @@ -187,13 +233,13 @@ private: BOARD_DESIGN_SETTINGS* m_designSettings; BOARD* m_board; - std::vector m_drcItems; + + std::shared_ptr m_drcReport; std::vector m_ruleConditions; std::vector m_rules; std::vector m_testProviders; std::unordered_map m_implicitRules; - std::vector<::MARKER_PCB*> m_markers; RULE_MAP m_ruleMap; REPORTER* m_reporter; PROGRESS_REPORTER* m_progressReporter; @@ -201,8 +247,6 @@ private: // condition -> rule -> provider }; -void drc_dbg( int level, const char* fmt, ... ); - }; // namespace test #endif // DRC_H diff --git a/qa/drc_proto/drc_item.cpp b/qa/drc_proto/drc_item.cpp index 41ef7f602d..1c50eca9e7 100644 --- a/qa/drc_proto/drc_item.cpp +++ b/qa/drc_proto/drc_item.cpp @@ -196,55 +196,58 @@ std::vector> test::DRC_ITEM::allItemTypes( { } ); -test::DRC_ITEM* test::DRC_ITEM::Create( int aErrorCode ) +std::shared_ptr test::DRC_ITEM::Create( int aErrorCode ) { + DRC_ITEM *item; + switch( aErrorCode ) { - case DRCE_UNCONNECTED_ITEMS: return new DRC_ITEM( unconnectedItems ); - case DRCE_SHORTING_ITEMS: return new DRC_ITEM( shortingItems ); - case DRCE_ALLOWED_ITEMS: return new DRC_ITEM( itemsNotAllowed ); - case DRCE_CLEARANCE: return new DRC_ITEM( clearance ); - case DRCE_TRACKS_CROSSING: return new DRC_ITEM( tracksCrossing ); - case DRCE_COPPER_EDGE_CLEARANCE: return new DRC_ITEM( copperEdgeClearance ); - case DRCE_ZONES_INTERSECT: return new DRC_ITEM( zonesIntersect ); - case DRCE_ZONE_HAS_EMPTY_NET: return new DRC_ITEM( zoneHasEmptyNet ); - case DRCE_DANGLING_VIA: return new DRC_ITEM( viaDangling ); - case DRCE_DANGLING_TRACK: return new DRC_ITEM( trackDangling ); - case DRCE_HOLE_CLEARANCE: return new DRC_ITEM( holeClearance ); - case DRCE_TRACK_WIDTH: return new DRC_ITEM( trackWidth ); - case DRCE_TOO_SMALL_VIA: return new DRC_ITEM( viaTooSmall ); - case DRCE_VIA_ANNULUS: return new DRC_ITEM( viaAnnulus ); - case DRCE_TOO_SMALL_DRILL: return new DRC_ITEM( drillTooSmall ); - case DRCE_VIA_HOLE_BIGGER: return new DRC_ITEM( viaHoleLargerThanPad ); - case DRCE_PADSTACK: return new DRC_ITEM( padstack ); - case DRCE_TOO_SMALL_MICROVIA: return new DRC_ITEM( microviaTooSmall ); - case DRCE_TOO_SMALL_MICROVIA_DRILL: return new DRC_ITEM( microviaDrillTooSmall ); - case DRCE_KEEPOUT: return new DRC_ITEM( keepout ); - case DRCE_OVERLAPPING_FOOTPRINTS: return new DRC_ITEM( courtyardsOverlap ); - case DRCE_MISSING_COURTYARD: return new DRC_ITEM( missingCourtyard ); - case DRCE_MALFORMED_COURTYARD: return new DRC_ITEM( malformedCourtyard ); - case DRCE_PTH_IN_COURTYARD: return new DRC_ITEM( pthInsideCourtyard ); - case DRCE_NPTH_IN_COURTYARD: return new DRC_ITEM( npthInsideCourtyard ); - case DRCE_DISABLED_LAYER_ITEM: return new DRC_ITEM( itemOnDisabledLayer ); - case DRCE_INVALID_OUTLINE: return new DRC_ITEM( invalidOutline ); - case DRCE_MISSING_FOOTPRINT: return new DRC_ITEM( duplicateFootprints ); - case DRCE_DUPLICATE_FOOTPRINT: return new DRC_ITEM( missingFootprint ); - case DRCE_EXTRA_FOOTPRINT: return new DRC_ITEM( extraFootprint ); - case DRCE_UNRESOLVED_VARIABLE: return new DRC_ITEM( unresolvedVariable ); + case DRCE_UNCONNECTED_ITEMS: item = new DRC_ITEM( unconnectedItems ); break; + case DRCE_SHORTING_ITEMS: item = new DRC_ITEM( shortingItems ); break; + case DRCE_ALLOWED_ITEMS: item = new DRC_ITEM( itemsNotAllowed ); break; + case DRCE_CLEARANCE: item = new DRC_ITEM( clearance ); break; + case DRCE_TRACKS_CROSSING: item = new DRC_ITEM( tracksCrossing ); break; + case DRCE_COPPER_EDGE_CLEARANCE: item = new DRC_ITEM( copperEdgeClearance ); break; + case DRCE_ZONES_INTERSECT: item = new DRC_ITEM( zonesIntersect ); break; + case DRCE_ZONE_HAS_EMPTY_NET: item = new DRC_ITEM( zoneHasEmptyNet ); break; + case DRCE_DANGLING_VIA: item = new DRC_ITEM( viaDangling ); break; + case DRCE_DANGLING_TRACK: item = new DRC_ITEM( trackDangling ); break; + 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_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; + case DRCE_TOO_SMALL_MICROVIA: item = new DRC_ITEM( microviaTooSmall ); break; + case DRCE_TOO_SMALL_MICROVIA_DRILL: item = new DRC_ITEM( microviaDrillTooSmall ); break; + case DRCE_KEEPOUT: item = new DRC_ITEM( keepout ); break; + case DRCE_OVERLAPPING_FOOTPRINTS: item = new DRC_ITEM( courtyardsOverlap ); break; + case DRCE_MISSING_COURTYARD: item = new DRC_ITEM( missingCourtyard ); break; + case DRCE_MALFORMED_COURTYARD: item = new DRC_ITEM( malformedCourtyard ); break; + case DRCE_PTH_IN_COURTYARD: item = new DRC_ITEM( pthInsideCourtyard ); break; + case DRCE_NPTH_IN_COURTYARD: item = new DRC_ITEM( npthInsideCourtyard ); break; + case DRCE_DISABLED_LAYER_ITEM: item = new DRC_ITEM( itemOnDisabledLayer ); break; + case DRCE_INVALID_OUTLINE: item = new DRC_ITEM( invalidOutline ); break; + case DRCE_MISSING_FOOTPRINT: item = new DRC_ITEM( duplicateFootprints ); break; + case DRCE_DUPLICATE_FOOTPRINT: item = new DRC_ITEM( missingFootprint ); break; + case DRCE_EXTRA_FOOTPRINT: item = new DRC_ITEM( extraFootprint ); break; + case DRCE_UNRESOLVED_VARIABLE: item = new DRC_ITEM( unresolvedVariable ); break; default: wxFAIL_MSG( wxString::Format( "Unknown DRC error code %d", aErrorCode ) ); return nullptr; } + return std::shared_ptr( item ); } -test::DRC_ITEM* test::DRC_ITEM::Create( const wxString& aErrorKey ) +std::shared_ptr test::DRC_ITEM::Create( const wxString& aErrorKey ) { for( const RC_ITEM& item : allItemTypes ) { if( aErrorKey == item.GetSettingsKey() ) - return new DRC_ITEM( static_cast( item ) ); + return std::shared_ptr( new DRC_ITEM( static_cast( item ) ) ); } // This can happen if a project has old-format exclusions. Just drop these items. diff --git a/qa/drc_proto/drc_item.h b/qa/drc_proto/drc_item.h index bfc6dc27de..0e485e2229 100644 --- a/qa/drc_proto/drc_item.h +++ b/qa/drc_proto/drc_item.h @@ -46,7 +46,7 @@ public: * Constructs a DRC_ITEM for the given error code * @see DRCE_T */ - static DRC_ITEM* Create( int aErrorCode ); + static std::shared_ptr Create( int aErrorCode ); /** * Constructs a DRC item from a given error settings key @@ -54,7 +54,7 @@ public: * to represent a given error code in settings files and for storing ignored DRC items) * @return the created item */ - static DRC_ITEM* Create( const wxString& aErrorKey ); + static std::shared_ptr Create( const wxString& aErrorKey ); static std::vector> GetItemsWithSeverities() { diff --git a/qa/drc_proto/drc_rule.cpp b/qa/drc_proto/drc_rule.cpp index 813a0bc720..fce5a95f38 100644 --- a/qa/drc_proto/drc_rule.cpp +++ b/qa/drc_proto/drc_rule.cpp @@ -77,9 +77,9 @@ bool test::DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOAR } -bool test::DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset ) +bool test::DRC_RULE_CONDITION::Compile( ) { - PCB_EXPR_COMPILER compiler( aReporter, aSourceLine, aSourceOffset ); + PCB_EXPR_COMPILER compiler; if (!m_ucode) m_ucode = new PCB_EXPR_UCODE; diff --git a/qa/drc_proto/drc_rule.h b/qa/drc_proto/drc_rule.h index 3b0516e67c..d4026f3afb 100644 --- a/qa/drc_proto/drc_rule.h +++ b/qa/drc_proto/drc_rule.h @@ -34,6 +34,7 @@ class BOARD_ITEM; namespace LIBEVAL { class UCODE; +class ERROR_STATUS; }; class PCB_EXPR_UCODE; @@ -48,9 +49,8 @@ enum class DRC_RULE_ID_T DRC_RULE_ID_HOLE_CLEARANCE, DRC_RULE_ID_EDGE_CLEARANCE, DRC_RULE_ID_HOLE_SIZE, - DRC_RULE_ID_ANNULUS, - DRC_RULE_ID_TRACK, - DRC_RULE_ID_DISALLOW + DRC_RULE_ID_COURTYARD_CLEARANCE, + DRC_RULE_ID_SILK_TO_PAD }; enum class DRC_RULE_SEVERITY_T @@ -85,10 +85,9 @@ private: bool m_hasMax = false; }; - class DRC_CONSTRAINT { -public: + public: DRC_CONSTRAINT() : m_Type( DRC_RULE_ID_T::DRC_RULE_ID_UNKNOWN ), m_DisallowFlags( 0 ), @@ -99,34 +98,15 @@ public: const MINOPTMAX& GetValue() const { return m_Value; } bool Allowed() const { return m_Allow; } -public: - DRC_RULE_ID_T m_Type; - MINOPTMAX m_Value; - int m_DisallowFlags; - LSET m_LayerCondition; + public: + DRC_RULE_ID_T m_Type; + MINOPTMAX m_Value; + int m_DisallowFlags; + LSET m_LayerCondition; - bool m_Allow; + bool m_Allow; }; - -class DRC_RULE_CONDITION - { - public: - DRC_RULE_CONDITION(); - ~DRC_RULE_CONDITION(); - - bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer ); - bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 ); - - public: - wxString m_Expression; - wxString m_TargetRuleName; - - private: - PCB_EXPR_UCODE* m_ucode; - }; - - class DRC_RULE { public: @@ -151,9 +131,9 @@ public: public: bool m_Unary; - wxString m_Name; + wxString m_Name; LSET m_LayerCondition; - wxString m_TestProviderName; + wxString m_TestProviderName; DRC_RULE_CONDITION m_Condition; std::vector m_Constraints; @@ -161,13 +141,29 @@ public: bool m_Enabled; bool m_Conditional; int m_Priority; // 0 indicates automatic priority generation - - DRC_CONSTRAINT m_Constraint; // FIXME: move to m_Constraints }; -//const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, -// int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName ); +class DRC_RULE_CONDITION +{ +public: + DRC_RULE_CONDITION(); + ~DRC_RULE_CONDITION(); + + bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB ); + bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 ); + +public: + LSET m_LayerCondition; + wxString m_Expression; + wxString m_TargetRuleName; + +private: + PCB_EXPR_UCODE* m_ucode; +}; + + +//DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint ); }; // namespace test diff --git a/qa/drc_proto/drc_rule_parser.cpp b/qa/drc_proto/drc_rule_parser.cpp index 7c2f0ce113..d16a1490a1 100644 --- a/qa/drc_proto/drc_rule_parser.cpp +++ b/qa/drc_proto/drc_rule_parser.cpp @@ -342,9 +342,20 @@ test::DRC_RULE* test::DRC_RULES_PARSER::parseRULE() void test::DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult ) { - PCB_EXPR_EVALUATOR evaluator( m_reporter, CurLineNumber(), CurOffset() ); + PCB_EXPR_EVALUATOR evaluator; evaluator.Evaluate( aExpr ); + + if( evaluator.IsErrorPending() ) + { + auto err = evaluator.GetError(); + wxString str; + str.Printf( "Error: %s (line %d, offset %d)", err.message, CurLineNumber(), err.srcPos + CurOffset() ); + + m_reporter->Report( str, RPT_SEVERITY_ERROR ); + return; + } + aResult = evaluator.Result(); }; diff --git a/qa/drc_proto/drc_test_provider.cpp b/qa/drc_proto/drc_test_provider.cpp index f4b18a2879..7d1bb5397b 100644 --- a/qa/drc_proto/drc_test_provider.cpp +++ b/qa/drc_proto/drc_test_provider.cpp @@ -22,23 +22,25 @@ bool test::DRC_TEST_PROVIDER::IsEnabled() const const wxString test::DRC_TEST_PROVIDER::GetName() const { return ""; } const wxString test::DRC_TEST_PROVIDER::GetDescription() const { return ""; } -void test::DRC_TEST_PROVIDER::Report( DRC_ITEM* item ) +void test::DRC_TEST_PROVIDER::Report( std::shared_ptr item ) { item->SetViolatingTest( this ); m_drcEngine->Report( item, nullptr ); } -void test::DRC_TEST_PROVIDER::ReportWithMarker( DRC_ITEM* item, VECTOR2I aMarkerPos ) +void test::DRC_TEST_PROVIDER::ReportWithMarker( std::shared_ptr item, VECTOR2I aMarkerPos ) { item->SetViolatingTest( this ); - m_drcEngine->Report( item, nullptr ); // fixme: create marker + MARKER_PCB* marker = new MARKER_PCB( item, wxPoint( aMarkerPos.x, aMarkerPos.y) ); + m_drcEngine->Report( item, marker ); } -void test::DRC_TEST_PROVIDER::ReportWithMarker( DRC_ITEM* item, wxPoint aMarkerPos ) +void test::DRC_TEST_PROVIDER::ReportWithMarker( std::shared_ptr item, wxPoint aMarkerPos ) { item->SetViolatingTest( this ); - m_drcEngine->Report( item, nullptr ); // fixme: create marker + MARKER_PCB* marker = new MARKER_PCB( item, wxPoint( aMarkerPos.x, aMarkerPos.y) ); + m_drcEngine->Report( item, marker ); // fixme: create marker } void test::DRC_TEST_PROVIDER::ReportProgress( double aProgress ) @@ -90,3 +92,130 @@ void test::DRC_TEST_PROVIDER::reportRuleStatistics() m_drcEngine->ReportAux( wxString::Format( " - rule '%s': %d hits ", stat.first->GetName().c_str(), stat.second ) ); } } + +int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector aTypes, const LSET aLayers, std::function aFunc ) +{ + BOARD *brd = m_drcEngine->GetBoard(); + std::bitset typeMask; + int n = 0; + + if( aTypes.size() == 0 ) + { + for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ ) + { + typeMask[i] = true; + } + } + else + { + for( int i = 0; i < aTypes.size(); i++ ) + { + typeMask[ aTypes[i] ] = 1; + } + } + + /* case PCB_TRACE_T: + case PCB_VIA_T: + case PCB_ARC_T:*/ + for ( auto item : brd->Tracks() ) + { + if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T ) + { + aFunc( item ); + n++; + } + else if( typeMask[ PCB_VIA_T ] && item->Type() == PCB_VIA_T ) + { + aFunc( item ); + n++; + } + else if( typeMask[ PCB_ARC_T ] && item->Type() == PCB_ARC_T ) + { + aFunc( item ); + n++; + } + } + + /* case PCB_DIMENSION_T: + case PCB_LINE_T: + case PCB_TEXT_T: + case PCB_TARGET_T: + */ + for( auto item : brd->Drawings() ) + { + if( typeMask[ PCB_DIMENSION_T ] && item->Type() == PCB_DIMENSION_T ) + { + aFunc( item ); + n++; + } + else if( typeMask[ PCB_LINE_T ] && item->Type() == PCB_LINE_T ) + { + aFunc( item ); + n++; + } + else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T ) + { + aFunc( item ); + n++; + } + else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T ) + { + aFunc( item ); + n++; + } + } + + for( auto item : brd->Zones() ) + { + if( typeMask[ PCB_ZONE_AREA_T ] && item->Type() == PCB_ZONE_AREA_T ) + { + aFunc( item ); + n++; + } + } + + for( auto mod : brd->Modules() ) + { + if( typeMask[ PCB_MODULE_TEXT_T ] ) + { + aFunc( &mod->Reference() ); + n++; + aFunc( &mod->Value() ); + n++; + } + + for( auto pad : mod->Pads() ) + { + if( typeMask[ PCB_PAD_T ] && pad->Type() == PCB_PAD_T ) + { + aFunc( pad ); + n++; + } + } + + for( auto dwg : mod->GraphicalItems() ) + { + if( typeMask[ PCB_MODULE_TEXT_T ] && dwg->Type() == PCB_MODULE_TEXT_T ) + { + aFunc( dwg ); + n++; + } + else if( typeMask[ PCB_MODULE_EDGE_T ] && dwg->Type() == PCB_MODULE_EDGE_T ) + { + aFunc( dwg ); + n++; + } + } + + for( auto zone : mod->Zones() ) + { + if( typeMask[ PCB_MODULE_ZONE_AREA_T ] && zone->Type() == PCB_MODULE_ZONE_AREA_T ) + { + aFunc( zone ); + n++; + } + } + } + + return n; +} diff --git a/qa/drc_proto/drc_test_provider.h b/qa/drc_proto/drc_test_provider.h index 0aefa4133c..788faf186c 100644 --- a/qa/drc_proto/drc_test_provider.h +++ b/qa/drc_proto/drc_test_provider.h @@ -97,9 +97,9 @@ public: virtual const wxString GetDescription() const; virtual void ReportAux( const wxString fmt, ... ); - virtual void Report( DRC_ITEM* item ); - virtual void ReportWithMarker( DRC_ITEM* item, wxPoint aMarkerPos ); - virtual void ReportWithMarker( DRC_ITEM* item, VECTOR2I aMarkerPos ); + virtual void Report( std::shared_ptr item ); + virtual void ReportWithMarker( std::shared_ptr item, wxPoint aMarkerPos ); + virtual void ReportWithMarker( std::shared_ptr item, VECTOR2I aMarkerPos ); virtual void ReportProgress( double aProgress ); virtual void ReportStage ( const wxString& aStageName, int index, int total ); @@ -108,6 +108,8 @@ public: protected: + int forEachGeometryItem( const std::vector aTypes, const LSET aLayers, std::function aFunc ); + virtual void reportRuleStatistics(); virtual void accountCheck( test::DRC_RULE* ruleToTest ); virtual bool isErrorLimitExceeded( int error_code ); diff --git a/qa/drc_proto/drc_test_provider_copper_clearance.cpp b/qa/drc_proto/drc_test_provider_copper_clearance.cpp index 14683c3889..66bdd20b9a 100644 --- a/qa/drc_proto/drc_test_provider_copper_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_copper_clearance.cpp @@ -178,7 +178,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a else if( textItem ) { bbox = textItem->GetTextBox(); - itemShape = textItem->GetEffectiveShape(); + itemShape = textItem->GetEffectiveTextShape(); } else { @@ -215,7 +215,8 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a if( actual < INT_MAX ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); + wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), @@ -258,7 +259,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a if( actual < INT_MAX ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); wxString msg; @@ -363,7 +364,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK if( padShape->Collide( &refSeg, minClearance - bds.GetDRCEpsilon(), &actual ) ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), @@ -434,7 +435,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK if( OPT_VECTOR2I intersection = refSeg.GetSeg().Intersect( trackSeg.GetSeg() ) ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TRACKS_CROSSING ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_TRACKS_CROSSING ); // fixme drcItem->SetErrorMessage( "FIXME" ); @@ -449,7 +450,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK else if( refSeg.Collide( &trackSeg, minClearance, &actual ) ) { wxPoint pos = getLocation( aRefSeg, trackSeg.GetSeg() ); - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); wxString msg; @@ -507,7 +508,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK if( zone->GetFilledPolysList( layer ).Collide( testSeg, allowedDist, &actual ) ) { actual = std::max( 0, actual - widths ); - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), @@ -606,7 +607,7 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D // and have the same pad number ( equivalent pads ) if( pad->PadNameEqual( aRefPad ) ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_SHORTING_ITEMS ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_SHORTING_ITEMS ); wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (nets %s and %s)" ), pad->GetNetCode(), aRefPad->GetNetCode() ); @@ -639,7 +640,7 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D if( refPadShape->Collide( pad->GetEffectiveShape().get(), clearanceAllowed, &actual ) ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), /*m_clearanceSource fixme*/ "", @@ -726,7 +727,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones() if( smoothed_polys[ia2].Contains( currentVertex ) ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT ); drcItem->SetItems( zoneRef, zoneToTest ); drcItem->SetViolatingRule( rule ); @@ -742,7 +743,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones() if( smoothed_polys[ia].Contains( currentVertex ) ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT ); drcItem->SetItems( zoneToTest, zoneRef ); drcItem->SetViolatingRule( rule ); @@ -797,7 +798,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones() for( const std::pair& conflict : conflictPoints ) { int actual = conflict.second; - DRC_ITEM* drcItem; + std::shared_ptr drcItem; if( actual <= 0 ) { diff --git a/qa/drc_proto/drc_test_provider_edge_clearance.cpp b/qa/drc_proto/drc_test_provider_edge_clearance.cpp index 6e1bcc3405..dc9904dda4 100644 --- a/qa/drc_proto/drc_test_provider_edge_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_edge_clearance.cpp @@ -44,7 +44,9 @@ Errors generated: - DRCE_COPPER_EDGE_CLEARANCE - TODO: holes to edge check + TODO: + - separate holes to edge check + - tester only looks for edge crossings. it doesn't check if items are inside/outside the board area. */ namespace test { @@ -70,7 +72,7 @@ public: virtual const wxString GetDescription() const override { - return "Tests copper item vs board edge clearance"; + return "Tests items vs board edge clearance"; } virtual std::set GetMatchingRuleIds() const override; @@ -83,76 +85,71 @@ private: bool test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() { - auto bds = m_drcEngine->GetDesignSettings(); m_board = m_drcEngine->GetBoard(); + DRC_CONSTRAINT worstClearanceConstraint; m_largestClearance = 0; - for( auto rule : m_drcEngine->QueryRulesById( test::DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE ) ) + if( m_drcEngine->QueryWorstConstraint( test::DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE, worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) { - if( rule->GetConstraint().m_Value.HasMin() ) - { - m_largestClearance = std::max( m_largestClearance, rule->GetConstraint().m_Value.Min() ); - } + m_largestClearance = worstClearanceConstraint.m_Value.Min(); } ReportAux( "Worst clearance : %d nm", m_largestClearance ); - - //m_largestClearance = - ReportStage( ("Testing all items <> Board Edge clearance"), 0, 2 ); std::vector boardOutline; std::vector boardItems; - for( auto item : m_board->Drawings() ) + auto queryBoardOutlineItems = [&] ( BOARD_ITEM *item ) -> int { - if( auto dseg = dyn_cast( item ) ) - { - drc_dbg(10,"L %d\n", dseg->GetLayer() ); - if( dseg->GetLayer() == Edge_Cuts ) - { - drc_dbg(10, "dseg ec %p\n", dseg); - boardOutline.push_back( dseg ); - } - } - } + boardOutline.push_back( dyn_cast( item ) ); + }; - for ( auto trk : m_board->Tracks() ) + auto queryBoardGeometryItems = [&] ( BOARD_ITEM *item ) -> int { - boardItems.push_back( trk ); - } + boardItems.push_back( item ); + }; - for ( auto zone : m_board->Zones() ) - { - boardItems.push_back( zone ); - } + - for ( auto zone : m_board->Zones() ) - { - boardItems.push_back( zone ); - } + forEachGeometryItem( { PCB_LINE_T }, LSET( Edge_Cuts ), queryBoardOutlineItems ); + forEachGeometryItem( {}, LSET::AllTechMask() | LSET::AllCuMask(), queryBoardGeometryItems ); - for ( auto mod : m_board->Modules() ) - { - for ( auto dwg : mod->GraphicalItems() ) - boardItems.push_back( dwg ); - for ( auto pad : mod->Pads() ) - boardItems.push_back( pad ); - } 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(); - (void) shape; - (void) refShape; + test::DRC_RULE* rule = m_drcEngine->EvalRulesForItems( test::DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE, outlineItem, boardItem ); + int minClearance = rule->GetConstraint().GetValue().Min(); + int actual; + + if( refShape->Collide( shape.get(), minClearance, &actual ) ) + { + std::shared_ptr 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() ); + } } } diff --git a/qa/drc_proto/drc_test_provider_hole_clearance.cpp b/qa/drc_proto/drc_test_provider_hole_clearance.cpp index 0e2dc0fbbd..6bb460a597 100644 --- a/qa/drc_proto/drc_test_provider_hole_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_hole_clearance.cpp @@ -280,7 +280,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, // fixme: pad stacks... if( refPadShape->Collide( pad->GetEffectiveHoleShape(), minClearance, &actual ) ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE ); wxString msg; @@ -312,7 +312,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, auto padShape = pad->GetEffectiveShape(); if( padShape->Collide( aRefPad->GetEffectiveHoleShape(), minClearance, &actual ) ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE ); wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), @@ -393,7 +393,7 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::testHoles2Holes() if( actual < minClearance ) { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE ); wxString msg; msg.Printf( drcItem->GetErrorText() + _( " (clearance %s; actual %s)" ), diff --git a/qa/drc_proto/drc_test_provider_hole_size.cpp b/qa/drc_proto/drc_test_provider_hole_size.cpp index 5e1566da63..7109ec75b5 100644 --- a/qa/drc_proto/drc_test_provider_hole_size.cpp +++ b/qa/drc_proto/drc_test_provider_hole_size.cpp @@ -141,7 +141,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( D_PAD* aPad ) if( holeSize < minHole ) { wxString msg; - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL ); + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL ); msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ), MessageTextFromValue( userUnits(), minHole, true ), @@ -173,7 +173,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkVia( VIA* via ) int errorCode = via->GetViaType() == VIATYPE::MICROVIA ? DRCE_TOO_SMALL_MICROVIA_DRILL : DRCE_TOO_SMALL_DRILL; - DRC_ITEM* drcItem = DRC_ITEM::Create( errorCode ); + std::shared_ptr drcItem = DRC_ITEM::Create( errorCode ); msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ), MessageTextFromValue( userUnits(), minHole, true ), diff --git a/qa/drc_proto/footprint_tester.cpp b/qa/drc_proto/footprint_tester.cpp index 14a2f70193..cbbf1377bf 100644 --- a/qa/drc_proto/footprint_tester.cpp +++ b/qa/drc_proto/footprint_tester.cpp @@ -25,7 +25,7 @@ #include #include -void TestFootprints( NETLIST& aNetlist, BOARD* aBoard, std::vector& aDRCList ) +void TestFootprints( NETLIST& aNetlist, BOARD* aBoard, std::vector >& aDRCList ) { wxString msg;