50 virtual bool Run()
override;
52 virtual const wxString
GetName()
const override {
return wxT(
"length" ); };
61 const std::vector<CONNECTION>& aMatchedConnections );
63 const std::vector<CONNECTION>& aMatchedConnections );
65 const std::vector<CONNECTION>& aMatchedConnections );
73 const std::vector<CONNECTION>& aMatchedConnections )
77 bool minViolation =
false;
78 bool maxViolation =
false;
112 if( ( minViolation || maxViolation ) )
118 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s min length %s; actual %s)" ),
126 else if( maxViolation )
128 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s max length %s; actual %s)" ),
137 for(
auto offendingTrack : ent.items )
138 drcItem->AddItem( offendingTrack );
142 reportViolation( drcItem, ( *ent.items.begin() )->GetPosition(), ( *ent.items.begin() )->GetLayer() );
148 const std::vector<CONNECTION>& aMatchedConnections )
150 auto checkSkewsImpl = [
this, &aConstraint](
const std::vector<CONNECTION>& connections )
155 double maxLength = 0;
162 if( ent.total > maxLength )
164 maxLength = ent.total;
165 maxNetname = ent.netname;
173 if( ent.totalDelay > maxLength )
175 maxLength = ent.totalDelay;
176 maxNetname = ent.netname;
183 int skew = isTimeDomain ?
KiROUND( ent.totalDelay - maxLength )
184 :
KiROUND( ent.total - maxLength );
186 bool fail_min =
false;
187 bool fail_max =
false;
194 if( fail_min || fail_max )
199 double reportTotal = isTimeDomain ? ent.totalDelay : ent.total;
203 msg.Printf(
_(
"(%s min skew %s; actual %s; target net length %s (from %s); actual %s)" ),
213 msg.Printf(
_(
"(%s max skew %s; actual %s; target net length %s (from %s); actual %s)" ),
222 drcItem->SetErrorDetail( msg );
225 drcItem->SetItems( offendingTrack );
229 reportViolation( drcItem, ( *ent.items.begin() )->GetPosition(), ( *ent.items.begin() )->GetLayer() );
237 std::map<int, CONNECTION> netcodeMap;
240 netcodeMap[ent.netcode] = ent;
242 std::vector<std::vector<CONNECTION>> matchedDiffPairs;
244 for(
auto& [netcode, connection] : netcodeMap )
250 int matchedNetcode = matchedNet->
GetNetCode();
252 if( netcodeMap.count( matchedNetcode ) )
254 std::vector<CONNECTION> pair{ connection, netcodeMap[matchedNetcode] };
255 matchedDiffPairs.emplace_back( std::move( pair ) );
256 netcodeMap.erase( matchedNetcode );
262 for(
const std::vector<CONNECTION>& matchedDiffPair : matchedDiffPairs )
263 checkSkewsImpl( matchedDiffPair );
268 checkSkewsImpl( aMatchedConnections );
274 const std::vector<CONNECTION>& aMatchedConnections )
276 for(
const auto& ent : aMatchedConnections )
278 std::shared_ptr<DRC_ITEM> drcItem =
nullptr;
283 wxString msg = wxString::Format(
_(
"(%s max count %d; actual %d)" ),
288 drcItem->SetErrorMessage(
_(
"Too many vias on a connection" ) + wxS(
" " ) + msg );
293 wxString msg = wxString::Format(
_(
"(%s min count %d; actual %d)" ),
298 drcItem->SetErrorMessage(
_(
"Too few vias on a connection" ) + wxS(
" " ) + msg );
304 drcItem->SetItems( offendingTrack );
308 reportViolation( drcItem, ( *ent.items.begin() )->GetPosition(), ( *ent.items.begin() )->GetLayer() );
325 if( !aDelayReportMode )
327 if( !
reportPhase(
_(
"Gathering length-constrained connections..." ) ) )
332 std::map<DRC_RULE*, std::set<BOARD_CONNECTED_ITEM*> > itemSets;
334 std::shared_ptr<FROM_TO_CACHE> ftCache =
m_board->GetConnectivity()->GetFromToCache();
338 const size_t progressDelta = 100;
372 std::map< DRC_RULE*, std::vector<CONNECTION> > matches;
374 for(
const auto& [rule, ruleItems] : itemSets )
376 std::map<int, std::set<BOARD_CONNECTED_ITEM*> > netMap;
379 netMap[item->GetNetCode()].insert( item );
381 for(
const auto& [netCode, netItems] : netMap )
383 std::vector<LENGTH_DELAY_CALCULATION_ITEM> lengthItems;
384 lengthItems.reserve( netItems.size() );
387 ent.
items = netItems;
403 if( lengthItem.
Type() != LENGTH_DELAY_CALCULATION_ITEM::TYPE::UNKNOWN )
404 lengthItems.emplace_back( lengthItem );
408 .OptimiseViaLayers =
true, .MergeTracks =
true, .OptimiseTracesInPads =
true, .InferViaInPad =
false
410 LENGTH_DELAY_STATS details = calc->CalculateLengthDetails( lengthItems, opts,
nullptr,
nullptr,
427 ent.
from = ftPath->fromName;
428 ent.
to = ftPath->toName;
432 ent.
from = ent.
to =
_(
"<unconstrained>" );
436 matches[rule].push_back( ent );
440 if( !aDelayReportMode )
442 if( !
reportPhase(
_(
"Checking length constraints..." ) ) )
446 count = matches.size();
448 for( std::pair<
DRC_RULE*
const, std::vector<CONNECTION> > it : matches )
451 auto& matchedConnections = it.second;
456 std::sort( matchedConnections.begin(), matchedConnections.end(),
459 return a.netname < b.netname;
464 REPORT_AUX( wxString::Format( wxT(
"Length-constrained traces for rule '%s':" ),
465 it.first->m_Name ) );
469 REPORT_AUX( wxString::Format( wxT(
" - net: %s, from: %s, to: %s, %d matching items, "
470 "total: %s (tracks: %s, vias: %s, pad-to-die: %s), "
474 static_cast<int>( ent.items.size() ),
491 checkSkews( *skewConstraint, matchedConnections );
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Information pertinent to a Pcbnew printed circuit board.
const MINOPTMAX< int > & GetValue() const
bool GetOption(OPTIONS option) const
DRC_RULE * GetParentRule() const
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
std::optional< DRC_CONSTRAINT > FindConstraint(DRC_CONSTRAINT_T aType)
bool runInternal(bool aDelayReportMode=false)
virtual const wxString GetName() const override
void checkSkews(const DRC_CONSTRAINT &aConstraint, const std::vector< CONNECTION > &aMatchedConnections)
virtual ~DRC_TEST_PROVIDER_MATCHED_LENGTH()=default
void checkViaCounts(const DRC_CONSTRAINT &aConstraint, const std::vector< CONNECTION > &aMatchedConnections)
DRC_LENGTH_REPORT m_report
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
DRC_TEST_PROVIDER_MATCHED_LENGTH()
DRC_LENGTH_REPORT::ENTRY CONNECTION
void checkLengths(const DRC_CONSTRAINT &aConstraint, const std::vector< CONNECTION > &aMatchedConnections)
virtual bool reportPhase(const wxString &aStageName)
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, const LSET &aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator=[](PCB_MARKER *){})
REPORTER * getLogReporter() const
wxString formatMsg(const wxString &aFormatString, const wxString &aSource, double aConstraint, double aActual, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
virtual bool reportProgress(size_t aCount, size_t aSize, size_t aDelta=1)
Lightweight class which holds a pad, via, or a routed trace outline.
TYPE Type() const
Gets the routing item type.
Class which calculates lengths (and associated routing statistics) in a BOARD context.
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Handle the data for a net.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
@ DRCE_LENGTH_OUT_OF_RANGE
@ DRCE_VIA_COUNT_OUT_OF_RANGE
EDA_DATA_TYPE
The type of unit.
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
BOARD_CONNECTED_ITEM * fromItem
BOARD_CONNECTED_ITEM * toItem
std::set< BOARD_CONNECTED_ITEM * > items
int64_t totalPadToDieDelay
Holds length measurement result details and statistics.
Struct to control which optimisations the length calculation code runs on the given path objects.
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)