pcb_new: CONNECTIVITY_DATA now keeps a cache of DRC from-tos
This commit is contained in:
parent
bc7369d70c
commit
7b7c3bde88
|
@ -509,6 +509,7 @@ set( PCB_COMMON_SRCS
|
|||
${CMAKE_SOURCE_DIR}/pcbnew/connectivity/connectivity_algo.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/connectivity/connectivity_items.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/connectivity/connectivity_data.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/connectivity/from_to_cache.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/convert_drawsegment_list_to_polygon.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_engine.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_item.cpp
|
||||
|
|
|
@ -11,6 +11,7 @@ set( PCBNEW_CONN_SRCS
|
|||
connectivity_algo.cpp
|
||||
connectivity_data.cpp
|
||||
connectivity_items.cpp
|
||||
from_to_cache.cpp
|
||||
)
|
||||
|
||||
add_library( connectivity STATIC ${PCBNEW_CONN_SRCS} )
|
||||
|
|
|
@ -33,12 +33,15 @@
|
|||
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <connectivity/connectivity_algo.h>
|
||||
#include <connectivity/from_to_cache.h>
|
||||
|
||||
#include <ratsnest/ratsnest_data.h>
|
||||
|
||||
CONNECTIVITY_DATA::CONNECTIVITY_DATA()
|
||||
{
|
||||
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO );
|
||||
m_progressReporter = nullptr;
|
||||
m_fromToCache.reset( new FROM_TO_CACHE );
|
||||
}
|
||||
|
||||
|
||||
|
@ -47,6 +50,7 @@ CONNECTIVITY_DATA::CONNECTIVITY_DATA( const std::vector<BOARD_ITEM*>& aItems, bo
|
|||
{
|
||||
Build( aItems );
|
||||
m_progressReporter = nullptr;
|
||||
m_fromToCache.reset( new FROM_TO_CACHE );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <geometry/shape_poly_set.h>
|
||||
#include <class_zone.h>
|
||||
|
||||
class FROM_TO_CACHE;
|
||||
class CN_CLUSTER;
|
||||
class CN_CONNECTIVITY_ALGO;
|
||||
class CN_EDGE;
|
||||
|
@ -269,6 +270,11 @@ public:
|
|||
const std::vector<CN_EDGE> GetRatsnestForComponent( MODULE* aComponent, bool aSkipInternalConnections = false );
|
||||
#endif
|
||||
|
||||
std::shared_ptr<FROM_TO_CACHE> GetFromToCache()
|
||||
{
|
||||
return m_fromToCache;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void updateRatsnest();
|
||||
|
@ -282,7 +288,7 @@ private:
|
|||
void addRatsnestCluster( const std::shared_ptr<CN_CLUSTER>& aCluster );
|
||||
|
||||
std::shared_ptr<CN_CONNECTIVITY_ALGO> m_connAlgo;
|
||||
|
||||
std::shared_ptr<FROM_TO_CACHE> m_fromToCache;
|
||||
std::vector<RN_DYNAMIC_LINE> m_dynamicRatsnest;
|
||||
std::vector<RN_NET*> m_nets;
|
||||
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <reporter.h>
|
||||
#include <class_board.h>
|
||||
#include <class_track.h>
|
||||
|
||||
#include <pcb_expr_evaluator.h>
|
||||
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <connectivity/connectivity_algo.h>
|
||||
|
||||
#include <connectivity/from_to_cache.h>
|
||||
|
||||
void FROM_TO_CACHE::buildEndpointList( )
|
||||
{
|
||||
m_ftEndpoints.clear();
|
||||
|
||||
for( auto mod : m_board->Modules() )
|
||||
{
|
||||
for( auto pad : mod->Pads() )
|
||||
{
|
||||
FT_ENDPOINT ent;
|
||||
ent.name = mod->GetReference() + "-" + pad->GetName();
|
||||
ent.parent = pad;
|
||||
m_ftEndpoints.push_back( ent );
|
||||
ent.name = mod->GetReference();
|
||||
ent.parent = pad;
|
||||
m_ftEndpoints.push_back( ent );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum PATH_STATUS {
|
||||
PS_OK = 0,
|
||||
PS_MULTIPLE_PATHS = -1,
|
||||
PS_NO_PATH = -2
|
||||
};
|
||||
|
||||
|
||||
static bool isVertexVisited( CN_ITEM* v, const std::vector<CN_ITEM*>& path )
|
||||
{
|
||||
for( auto u : path )
|
||||
{
|
||||
if ( u == v )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static PATH_STATUS uniquePathBetweenNodes( CN_ITEM* u, CN_ITEM* v, std::vector<CN_ITEM*>& outPath )
|
||||
{
|
||||
using Path = std::vector<CN_ITEM*>;
|
||||
std::deque<Path> Q;
|
||||
|
||||
Path p;
|
||||
int pathFound = false;
|
||||
p.push_back( u );
|
||||
Q.push_back( p );
|
||||
|
||||
while( Q.size() )
|
||||
{
|
||||
Path path = Q.front();
|
||||
Q.pop_front();
|
||||
CN_ITEM *last = path.back();
|
||||
|
||||
if( last == v )
|
||||
{
|
||||
outPath = path;
|
||||
if( pathFound )
|
||||
return PS_MULTIPLE_PATHS;
|
||||
pathFound = true;
|
||||
}
|
||||
|
||||
for( auto ci : last->ConnectedItems() )
|
||||
{
|
||||
bool vertexVisited = isVertexVisited(ci, path);
|
||||
|
||||
for( auto &p : Q )
|
||||
if (isVertexVisited(ci, p))
|
||||
{
|
||||
vertexVisited = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!vertexVisited) {
|
||||
Path newpath(path);
|
||||
newpath.push_back(ci);
|
||||
Q.push_back(newpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pathFound ? PS_OK : PS_NO_PATH;
|
||||
};
|
||||
|
||||
|
||||
int FROM_TO_CACHE::cacheFromToPaths( const wxString& aFrom, const wxString& aTo )
|
||||
{
|
||||
std::vector<FT_PATH> paths;
|
||||
auto connectivity = m_board->GetConnectivity();
|
||||
auto cnAlgo = connectivity->GetConnectivityAlgo();
|
||||
|
||||
for( auto& endpoint : m_ftEndpoints )
|
||||
{
|
||||
if( WildCompareString( aFrom, endpoint.name, false ) )
|
||||
{
|
||||
FT_PATH p;
|
||||
p.net = endpoint.parent->GetNetCode();
|
||||
p.from = endpoint.parent;
|
||||
p.to = nullptr;
|
||||
paths.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
for( auto &path : paths )
|
||||
{
|
||||
int count = 0;
|
||||
auto netName = path.from->GetNetname();
|
||||
|
||||
wxString fromName = path.from->GetParent()->GetReference() + "-" + path.from->GetName();
|
||||
|
||||
const KICAD_T onlyRouting[] = { PCB_PAD_T, PCB_ARC_T, PCB_VIA_T, PCB_TRACE_T, EOT };
|
||||
|
||||
auto padCandidates = connectivity->GetConnectedItems( path.from, onlyRouting );
|
||||
D_PAD* toPad = nullptr;
|
||||
|
||||
for( auto pitem : padCandidates )
|
||||
{
|
||||
if( pitem == path.from )
|
||||
continue;
|
||||
|
||||
if( pitem->Type() != PCB_PAD_T )
|
||||
continue;
|
||||
|
||||
D_PAD *pad = static_cast<D_PAD*>( pitem );
|
||||
|
||||
wxString toName = pad->GetParent()->GetReference() + "-" + pad->GetName();
|
||||
|
||||
|
||||
for ( auto& endpoint : m_ftEndpoints )
|
||||
{
|
||||
if( pad == endpoint.parent )
|
||||
{
|
||||
if( WildCompareString( aTo, endpoint.name, false ) )
|
||||
{
|
||||
count++;
|
||||
toPad = endpoint.parent;
|
||||
|
||||
path.to = toPad;
|
||||
path.fromName = fromName;
|
||||
path.toName = toName;
|
||||
path.fromWildcard = aFrom;
|
||||
path.toWildcard = aTo;
|
||||
|
||||
if( count >= 2 )
|
||||
{
|
||||
// fixme: report this somewhere?
|
||||
//printf("Multiple targets found, aborting...\n");
|
||||
path.to = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int newPaths = 0;
|
||||
|
||||
for( auto &path : paths )
|
||||
{
|
||||
if( !path.from || !path.to )
|
||||
continue;
|
||||
|
||||
|
||||
CN_ITEM *cnFrom = cnAlgo->ItemEntry( path.from ).GetItems().front();
|
||||
CN_ITEM *cnTo = cnAlgo->ItemEntry( path.to ).GetItems().front();
|
||||
CN_ITEM::CONNECTED_ITEMS upath;
|
||||
|
||||
auto result = uniquePathBetweenNodes( cnFrom, cnTo, upath );
|
||||
|
||||
if( result == PS_OK )
|
||||
path.isUnique = true;
|
||||
else
|
||||
path.isUnique = false;
|
||||
|
||||
|
||||
//printf( "%s\n", (const char *) wxString::Format( _("Check path: %s -> %s (net %s)"), path.fromName, path.toName, cnFrom->Parent()->GetNetname() ) );
|
||||
|
||||
if( result == PS_NO_PATH )
|
||||
continue;
|
||||
|
||||
for( auto item : upath )
|
||||
{
|
||||
path.pathItems.insert( item->Parent() );
|
||||
}
|
||||
|
||||
m_ftPaths.push_back(path);
|
||||
newPaths++;
|
||||
}
|
||||
|
||||
//reportAux( _("Cached %d paths\n"), newPaths );
|
||||
|
||||
return newPaths;
|
||||
}
|
||||
|
||||
bool FROM_TO_CACHE::IsOnFromToPath( BOARD_CONNECTED_ITEM* aItem, const wxString& aFrom, const wxString& aTo )
|
||||
{
|
||||
int nFromTosFound = 0;
|
||||
|
||||
if( !m_board )
|
||||
return false;
|
||||
|
||||
//printf("Check %d cached paths [%p]\n", m_ftPaths.size(), aItem );
|
||||
for( int attempt = 0; attempt < 2; attempt++ )
|
||||
{
|
||||
// item already belongs to path
|
||||
for( auto& ftPath : m_ftPaths )
|
||||
{
|
||||
if( aFrom == ftPath.fromWildcard &&
|
||||
aTo == ftPath.toWildcard )
|
||||
{
|
||||
nFromTosFound++;
|
||||
|
||||
if( ftPath.pathItems.count( aItem ) )
|
||||
{
|
||||
// printf("Found cached path for %p [%s->%s]\n", aItem, (const char *)ftPath.fromName, (const char *) ftPath.toName );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !nFromTosFound )
|
||||
cacheFromToPaths( aFrom, aTo );
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FROM_TO_CACHE::Rebuild( BOARD* aBoard )
|
||||
{
|
||||
m_board = aBoard;
|
||||
buildEndpointList();
|
||||
m_ftPaths.clear();
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FROM_TO_CACHE_H
|
||||
#define __FROM_TO_CACHE_H
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <common.h>
|
||||
|
||||
class D_PAD;
|
||||
class BOARD_CONNECTED_ITEM;
|
||||
|
||||
class FROM_TO_CACHE
|
||||
{
|
||||
public:
|
||||
|
||||
struct FT_ENDPOINT
|
||||
{
|
||||
wxString name;
|
||||
D_PAD* parent;
|
||||
};
|
||||
|
||||
struct FT_PATH
|
||||
{
|
||||
int net;
|
||||
D_PAD *from;
|
||||
D_PAD *to;
|
||||
wxString fromName, toName;
|
||||
wxString fromWildcard, toWildcard;
|
||||
bool isUnique;
|
||||
std::set<BOARD_CONNECTED_ITEM*> pathItems;
|
||||
};
|
||||
|
||||
FROM_TO_CACHE( BOARD* aBoard = nullptr ) :
|
||||
m_board( aBoard )
|
||||
{
|
||||
}
|
||||
|
||||
~FROM_TO_CACHE()
|
||||
{
|
||||
}
|
||||
|
||||
void Rebuild( BOARD* aBoard );
|
||||
bool IsOnFromToPath( BOARD_CONNECTED_ITEM* aItem, const wxString& aFrom, const wxString& aTo );
|
||||
|
||||
private:
|
||||
|
||||
int cacheFromToPaths( const wxString& aFrom, const wxString& aTo );
|
||||
void buildEndpointList();
|
||||
|
||||
std::vector<FT_ENDPOINT> m_ftEndpoints;
|
||||
std::vector<FT_PATH> m_ftPaths;
|
||||
|
||||
BOARD* m_board;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -27,8 +27,55 @@
|
|||
#include <reporter.h>
|
||||
#include <class_board.h>
|
||||
#include <class_track.h>
|
||||
|
||||
#include <pcb_expr_evaluator.h>
|
||||
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <connectivity/connectivity_algo.h>
|
||||
#include <connectivity/from_to_cache.h>
|
||||
|
||||
|
||||
|
||||
bool exprFromTo( LIBEVAL::CONTEXT* aCtx, void* self )
|
||||
{
|
||||
PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
|
||||
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
|
||||
LIBEVAL::VALUE* result = aCtx->AllocValue();
|
||||
|
||||
LIBEVAL::VALUE* argTo = aCtx->Pop();
|
||||
LIBEVAL::VALUE* argFrom = aCtx->Pop();
|
||||
|
||||
result->Set(0.0);
|
||||
aCtx->Push( result );
|
||||
|
||||
if(!item)
|
||||
return false;
|
||||
|
||||
auto ftCache = item->GetBoard()->GetConnectivity()->GetFromToCache();
|
||||
|
||||
if( !ftCache )
|
||||
{
|
||||
wxLogWarning( "Attempting to call fromTo() with non-existent from-to cache, aborting...");
|
||||
return true;
|
||||
}
|
||||
|
||||
int r =0 ;
|
||||
|
||||
if( ftCache->IsOnFromToPath( static_cast<BOARD_CONNECTED_ITEM*>( item ),
|
||||
argFrom->AsString(), argTo->AsString() ) )
|
||||
{
|
||||
result->Set(1.0);
|
||||
r = 1;
|
||||
|
||||
}
|
||||
|
||||
/*printf("isonfromto %p %s %s -> %d\n", static_cast<BOARD_CONNECTED_ITEM*>( item ),
|
||||
(const char *)argFrom->AsString(),
|
||||
(const char *)argTo->AsString(), r );*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void onLayer( LIBEVAL::CONTEXT* aCtx, void *self )
|
||||
{
|
||||
|
@ -286,8 +333,6 @@ static void isBlindBuriedVia( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
|
||||
}
|
||||
|
||||
extern void exprFromTo( LIBEVAL::CONTEXT* aCtx, void* self );
|
||||
|
||||
PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS()
|
||||
{
|
||||
RegisterAllFunctions();
|
||||
|
@ -305,6 +350,7 @@ void PCB_EXPR_BUILTIN_FUNCTIONS::RegisterAllFunctions()
|
|||
RegisterFunc( "isBlindBuriedVia()", isBlindBuriedVia );
|
||||
RegisterFunc( "memberOf('x')", memberOf );
|
||||
RegisterFunc( "fromTo('x','y')", exprFromTo );
|
||||
//RegisterFunc( "isDiffPair()", exprFromTo );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -142,7 +142,6 @@ public:
|
|||
wxString funcName = funcSignature.BeforeFirst( '(' );
|
||||
m_funcs[std::string( funcName.Lower() )] = std::move( funcPtr );
|
||||
m_funcSigs.Add( funcSignature );
|
||||
printf("Register '%s'\n", (const char *) funcName.Lower() );
|
||||
}
|
||||
|
||||
void RegisterAllFunctions();
|
||||
|
|
Loading…
Reference in New Issue