TraceMaker
C++ API of the engine
Loading...
Searching...
No Matches
rule_engine.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2#pragma once
3// Resolves KiCad constraints for pairs of copper items (design doc 03 §6): net-class clearances, local pad
4// overrides, board minimums and custom .kicad_dru rules with their conditions.
5#include <tuple>
6#include <mutex>
7#include <map>
8#include <memory>
9#include <optional>
10#include <string>
11#include <vector>
12
13#include "drc/copper.hpp"
14#include "drc/rule_geometry.hpp"
15#include "model/board.hpp"
16#include "model/rules.hpp"
17
18namespace tmk::drc {
19
20class Condition; // compiled custom-rule condition
21
23 public:
26
27 // Required copper-to-copper clearance between two items on a copper layer.
28 Coord clearance(const CopperItem& a, const CopperItem& b, int layer) const;
29 // Required clearance between a hole and a copper item.
30 Coord hole_clearance(const CopperItem* hole_owner, const CopperItem& other, int layer) const;
31 Coord hole_to_hole(const CopperItem* a, const CopperItem* b) const;
32 Coord edge_clearance(const CopperItem& a, int layer) const;
33 // Minimum and maximum track width (max = 0: none).
34 std::pair<Coord, Coord> track_width(const CopperItem& t, int layer) const;
37 Coord hole_size_min(const CopperItem* owner) const;
38 // Largest clearance any pair could need (for spatial-index inflation).
39 Coord max_clearance() const { return max_clearance_; }
40 // KiCad applies a copper zone's own clearance to its fill (ZONE::GetLocalClearance): the larger of it and the
41 // net-class clearance, unless a pad override or custom rule decides. The DRC enables it; the router does not
42 // yet (D51: changing it needs a routing benchmark run).
44
45 const model::NetClass& netclass(const CopperItem& it) const;
46 // True if the two nets are the P/N (or +/-) halves of one differential pair.
48 // Length constraint (min, max) of the last custom rule whose condition matches a track of `net`, if any.
49 std::pair<std::optional<Coord>, std::optional<Coord>> length_constraint(model::NetId net) const;
50 // Maximum skew of the last custom rule with a `skew` constraint matching a track of `net`, if any.
51 std::optional<Coord> skew_constraint(model::NetId net) const;
52 // Last custom constraint of `type` (e.g. diff_pair_gap, diff_pair_uncoupled) whose rule matches a track of `net`.
53 std::optional<model::Constraint> net_constraint(model::NetId net, const std::string& type) const;
54
55 // Name of the last rule disallowing `it` on `layer`, if any (KiCad: items_not_allowed).
56 std::optional<std::string> disallowed(const CopperItem& it, int layer) const;
57 // Router fast paths for a new track or via of `net`, from rules whose conditions do not depend on the
58 // item's position, size or footprint (per-net layer and via-type masks).
59 bool track_allowed(model::NetId net, int layer) const;
60 // `Blind` router probes have no span yet, so either blind/buried keyword conservatively forbids them.
61 // Board items are distinguished exactly by whether their span touches an outer copper layer.
63 // A disallow rule on tracks or vias depends on position, size or footprint: the router asks probe_disallowed.
64 bool positional_disallow() const { return positional_disallow_; }
65 // A new track or via (index -1, actual shape, width and layers; a via's layers are its span, which tells
66 // blind from buried) is disallowed on one of its layers, every custom rule applied in order as in disallowed().
68 // Hole-to-copper clearance on `layer`, any net; -1 when no rule matches (KiCad: hole_clearance).
69 Coord physical_hole_clearance(const CopperItem* hole_owner, const CopperItem& other, int layer) const;
70 bool any_physical_hole_clearance() const { return max_physical_hole_ > 0; }
71 // True when a physical_hole_clearance rule holds between a via of `net` and a track of the same net: the
72 // tracks that end in a via touch its hole, so every via of that net would break the rule.
74 Coord max_physical_hole_clearance() const { return max_physical_hole_; }
75 // Custom rules that the per-class obstacle cache cannot represent require exact per-point checks.
76 bool needs_exact_routing() const { return needs_exact_; }
77 const std::vector<std::string>& warnings() const { return warnings_; }
78
79 private:
80 // Keyword bits of a rule's disallow constraints.
81 enum : std::uint16_t {
82 kTrack = 1, kVia = 2, kThroughVia = 4, kMicroVia = 8, kBlindVia = 16, kBuriedVia = 32, kPad = 64, kZone = 128, kGraphic = 256,
83 kRouted = kTrack | kVia | kThroughVia | kMicroVia | kBlindVia | kBuriedVia,
84 };
85 struct Compiled {
86 const model::CustomRule* rule;
87 std::unique_ptr<Condition> cond; // null = always
88 bool valid = true;
89 bool positional = false; // position, size, footprint or pad condition: evaluated per item, not per net
90 std::uint16_t words = 0; // disallow keywords
91 };
92 bool words_match(std::uint16_t words, const CopperItem& it, const model::ViaType* via_type, bool span) const;
93 // Item type, layer and condition all match a disallow constraint.
94 bool disallow_hit(const Compiled& c, const CopperItem& it, int layer, const model::ViaType* via_type = nullptr, bool span = false) const;
95 // Value of the last matching custom constraint of `type` (min field), trying (a,b) and (b,a).
96 std::optional<Coord> custom_min(const char* type, const CopperItem* a, const CopperItem* b, int layer) const;
97 bool layer_matches(const std::string& sel, int layer) const;
98
99 const model::Board& b_;
100 const model::DesignRules& r_;
101 std::vector<Compiled> rules_;
102 std::vector<std::string> warnings_;
103 Coord max_clearance_ = 0;
104 std::vector<const model::NetClass*> net_class_; // by net id (nets created later fall back to a lookup)
105 std::vector<model::NetId> dp_partner_; // by net id: the other half of a P/N pair, or 0
106 // Area and courtyard functions of a zone fill, by (condition node, zone, fill): a fill has tens of thousands
107 // of points and is asked again for every pair it is in (vme-wren: 80 s of a DRC).
108 mutable std::map<std::tuple<const void*, int, int>, bool> area_cache_;
109 mutable std::mutex area_mutex_;
110 CourtyardCache courtyards_;
111 std::vector<geom::Box> zone_box_; // outline box of every zone, for area functions
112 bool positional_disallow_ = false;
113 bool any_custom_clearance_ = false;
114 bool zone_overrides_ = false;
115 bool needs_exact_ = false;
116 Coord max_physical_hole_ = 0;
117 friend class Condition;
118};
119
120} // namespace tmk::drc
The board model (design doc 02 §3): every object TraceMaker reads from a .kicad_pcb,...
bool track_allowed(model::NetId net, int layer) const
Router fast paths for a new track or via of net, from rules whose conditions do not depend on the ite...
Coord max_clearance() const
Largest clearance any pair could need (for spatial-index inflation).
bool needs_exact_routing() const
Custom rules that the per-class obstacle cache cannot represent require exact per-point checks.
std::optional< std::string > disallowed(const CopperItem &it, int layer) const
Name of the last rule disallowing it on layer, if any (KiCad: items_not_allowed).
bool via_allowed(model::NetId net, model::ViaType type=model::ViaType::Through) const
Blind router probes have no span yet, so either blind/buried keyword conservatively forbids them.
bool via_hole_rule_hits_own_tracks(model::NetId net) const
True when a physical_hole_clearance rule holds between a via of net and a track of the same net: the ...
void use_zone_clearance_overrides()
KiCad applies a copper zone's own clearance to its fill (ZONE::GetLocalClearance): the larger of it a...
const std::vector< std::string > & warnings() const
Coord hole_clearance(const CopperItem *hole_owner, const CopperItem &other, int layer) const
Required clearance between a hole and a copper item.
Coord max_physical_hole_clearance() const
bool positional_disallow() const
A disallow rule on tracks or vias depends on position, size or footprint: the router asks probe_disal...
std::pair< Coord, Coord > track_width(const CopperItem &t, int layer) const
Minimum and maximum track width (max = 0: none).
std::optional< Coord > skew_constraint(model::NetId net) const
Maximum skew of the last custom rule with a skew constraint matching a track of net,...
Coord annular_width_min(const CopperItem &v) const
bool coupled_diff_pair(model::NetId a, model::NetId b) const
True if the two nets are the P/N (or +/-) halves of one differential pair.
std::pair< std::optional< Coord >, std::optional< Coord > > length_constraint(model::NetId net) const
Length constraint (min, max) of the last custom rule whose condition matches a track of net,...
Coord clearance(const CopperItem &a, const CopperItem &b, int layer) const
Required copper-to-copper clearance between two items on a copper layer.
bool any_physical_hole_clearance() const
Coord physical_hole_clearance(const CopperItem *hole_owner, const CopperItem &other, int layer) const
Hole-to-copper clearance on layer, any net; -1 when no rule matches (KiCad: hole_clearance).
Coord hole_size_min(const CopperItem *owner) const
std::optional< model::Constraint > net_constraint(model::NetId net, const std::string &type) const
Last custom constraint of type (e.g. diff_pair_gap, diff_pair_uncoupled) whose rule matches a track o...
bool probe_disallowed(const CopperItem &it, model::ViaType type=model::ViaType::Through) const
A new track or via (index -1, actual shape, width and layers; a via's layers are its span,...
Coord hole_to_hole(const CopperItem *a, const CopperItem *b) const
Coord edge_clearance(const CopperItem &a, int layer) const
RuleEngine(const model::Board &b, const model::DesignRules &r)
Coord via_diameter_min(const CopperItem &v) const
const model::NetClass & netclass(const CopperItem &it) const
Copper items with exact shapes, built from the board model, for DRC and routing obstacles.
std::int32_t NetId
0 = no net
Definition board.hpp:21
std::int64_t Coord
Engine coordinate: signed 64-bit nanometres.
Definition units.hpp:12
Positional custom-rule predicates.
Design rules as KiCad defines them (design doc 08 §3–4): board minimums and net classes from the ....