TraceMaker
C++ API of the engine
Loading...
Searching...
No Matches
engine.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2#pragma once
3// From detected instances to effective rules and engine inputs (design doc 15 §3.5, §5.5, §7):
4// evaluate -> every catalogue rule of every instance, tagged applied / satisfied-by-board / not-applied(reason)
5// / advisory, with a measured value where TraceMaker can measure it;
6// compile -> placement pseudo-nets (pad pairs), keep-out rule areas for the router and DRC, and a sidecar
7// .kicad_dru with the generated custom rules;
8// report -> the text and JSON the user sees.
9// Everything is deterministic: instances in catalogue/reference order, rules in catalogue order.
10#include <optional>
11#include <string>
12#include <string_view>
13#include <vector>
14
15#include <nlohmann/json.hpp>
16
17#include "crules/catalogue.hpp"
18#include "crules/detect.hpp"
20#include "model/board.hpp"
21#include "model/rules.hpp"
22
23namespace tmk::crules {
24
25// --component-rules (doc 15 §3.5): off = nothing; report = detect and check only; soft = rules as costs, no hard
26// constraints; on = catalogue severities (generated keep-outs become router/DRC rule areas).
27enum class Mode : std::uint8_t { Off, Report, Soft, On };
28Mode parse_mode(std::string_view s); // throws std::invalid_argument
29const char* mode_name(Mode m);
30
31enum class Status : std::uint8_t { Applied, SatisfiedByBoard, NotApplied, Advisory };
32const char* status_name(Status s);
33
34struct Measure {
35 double value_mm = 0, limit_mm = 0;
36 bool met = false;
37 std::string what; // how it was measured
38};
39
41 int instance = -1; // index into Detection::instances
42 const RuleSpec* spec = nullptr;
43 Severity severity = Severity::Soft; // after confidence demotion (doc 15 §3.2)
45 std::string detail; // what was applied, or why not
46 std::optional<Measure> measure;
47 std::optional<ImpedancePlan> impedance; // impedance rules: widths/gaps from the stackup (P4, report only)
48 std::optional<CurrentPlan> current; // width_for_current rules that name a current (IPC-2221, report only)
49};
50
51struct Evaluation {
53 std::vector<EffectiveRule> rules;
54};
55
56// A proximity rule bound to pads (doc 15 §4 `proximity`): each pair is (pad of the part that should move close,
57// pad it should be close to). Shared by the measurement and the placement pseudo-nets so both agree.
59 const RuleSpec* spec = nullptr;
60 int instance = -1;
61 std::vector<std::pair<int, int>> pairs;
62 double limit_mm = 0;
63 int weight = 10; // placement pseudo-net weight (kSignalWeight; x2 for ESD to connector, doc 15 §5.2)
64 std::string unbound; // non-empty: a role it needs is missing
65};
66std::vector<ProximityPairs> proximity_pairs(const model::Board& b, const Catalogue& cat, const Detection& det);
67
68Evaluation evaluate(const model::Board& b, const model::DesignRules* rules, const Catalogue& cat, const Detection& det, Mode mode);
69
70// Placement pseudo-nets for every applicable proximity rule (mode soft or on; confidence >= suggest). A part is
71// tied by the first rule that claims it, in this priority: crystal, oscillator, ESD/protection, regulator, then
72// decoupling; later rules skip it.
74 int pad_a = -1, pad_b = -1, weight = 10;
75 std::string name, rule;
76};
77std::vector<PlacementAffinity> placement_affinities(const model::Board& b, const Catalogue& cat, const Detection& det, Mode mode);
78
79// Connector edge pull for the placer (doc 15 §5.2 `edge`; CONN-01, USB2-11, DISP-02), opt-in
80// (tracemaker-place --edge-attraction): the anchor of every instance with a connector edge rule (mode soft/on, not
81// advisory, not disabled by the user), once per footprint, never a locked part and never a pin header or socket
82// (board-to-board and jumper headers, CONN-01 note). `body` holds the courtyard outline points (else pad corners),
83// absolute; the placer pulls the body point nearest to the board outline toward the outline.
85 int footprint = -1;
86 std::vector<Point> body;
87 int weight = 20; // 2 x signal weight, like ESD-01 (doc 15 §5.2)
88 double max_mm = 0; // the rule's limit (report only)
89 std::string rule, name; // "CONN-01", "~CONN-01 J3 edge"
90};
91std::vector<EdgeAttraction> edge_attractions(const model::Board& b, const Catalogue& cat, const Detection& det, Mode mode);
92
93// Keep-out rule areas (doc 15 §5.5, P2) for instances at confidence >= apply: crystal + load caps (XTAL-04),
94// switching-regulator inductor (BUCK-06/BOOST-04), discrete Ethernet magnetics (ETH-05: tracks, vias and zones on
95// the magnetics' side and the adjacent layer only). The polygon is the convex hull of the parts' courtyards (and the
96// IC's oscillator pins for a crystal) grown by the rule margin, on the copper layers where none of those parts has
97// a pad, so the parts' own nets still reach their pads; tracks only (vias and zones stay allowed: ground stitching
98// under a crystal is good practice). Zones are named "tmk:<rule>:<ref>".
101 std::string rule, ref;
102 int instance = -1;
103};
104std::vector<GeneratedKeepout> generate_keepouts(const model::Board& b, const Catalogue& cat, const Detection& det,
105 std::vector<std::string>* not_generated = nullptr);
106// The same intent as KiCad custom rules with net exemptions (which rule areas cannot express), for the user to
107// review or merge: "<output>.tracemaker.kicad_dru". Never written into the user's own files (rule 8).
108std::string dru_sidecar(const model::Board& b, const Catalogue& cat, const Detection& det);
109
110// USB 2.0 D+/D- pairs to route coupled first (USB2-02, doc 15 P3): one (dp, dm) per usb2 instance whose dp and dm
111// roles each bind exactly one net, in instance order, without duplicates.
112std::vector<std::pair<model::NetId, model::NetId>> usb_pairs(const model::Board& b, const Catalogue& cat, const Detection& det);
113
114// Net classes from rules (doc 15 §5.3-5.4 and §16, P5): impedance rules with a computed width/gap, and width rules
115// with a current or a minimum width, become synthetic net classes for the nets bound to the rule's roles. Only for
116// instances at the apply threshold, only for nets the board leaves in its Default class (the board's own classes
117// always win, §3.5), and only ever wider than the class the net has (never looser than a board rule). The router
118// has one width per net: the outer-layer solution is used and `detail` says when inner layers would differ.
120 model::NetClass cls; // name "tmk_<RULE>_<anchor reference>"
121 std::vector<model::NetId> nets;
122 std::string rule, detail;
123};
124std::vector<SyntheticClass> synthetic_net_classes(const model::Board& b, const model::DesignRules& rules, const Catalogue& cat,
125 const Detection& det, const Evaluation& ev);
126// `rules` with the synthetic classes added and their nets assigned to them (in memory only, rule 8).
127model::DesignRules with_synthetic_classes(const model::Board& b, model::DesignRules rules, const std::vector<SyntheticClass>& sc);
128
129// Report (doc 15 §7).
130std::string report_text(const model::Board& b, const Catalogue& cat, const Detection& det, const Evaluation& ev);
131nlohmann::json report_json(const model::Board& b, const Catalogue& cat, const Detection& det, const Evaluation& ev);
132
133} // namespace tmk::crules
The board model (design doc 02 §3): every object TraceMaker reads from a .kicad_pcb,...
Component-rule catalogue (design doc 15 §6.1): categories of components with their detectors,...
Category detection and role binding (design doc 15 §3): each footprint is scored against every catego...
Impedance and current rules on a real board (design doc 15 §5.3-5.4, P4): the board stackup gives,...
std::vector< PlacementAffinity > placement_affinities(const model::Board &b, const Catalogue &cat, const Detection &det, Mode mode)
nlohmann::json report_json(const model::Board &b, const Catalogue &cat, const Detection &det, const Evaluation &ev)
std::vector< GeneratedKeepout > generate_keepouts(const model::Board &b, const Catalogue &cat, const Detection &det, std::vector< std::string > *not_generated=nullptr)
std::vector< SyntheticClass > synthetic_net_classes(const model::Board &b, const model::DesignRules &rules, const Catalogue &cat, const Detection &det, const Evaluation &ev)
std::string report_text(const model::Board &b, const Catalogue &cat, const Detection &det, const Evaluation &ev)
Report (doc 15 §7).
std::vector< EdgeAttraction > edge_attractions(const model::Board &b, const Catalogue &cat, const Detection &det, Mode mode)
std::vector< std::pair< model::NetId, model::NetId > > usb_pairs(const model::Board &b, const Catalogue &cat, const Detection &det)
USB 2.0 D+/D- pairs to route coupled first (USB2-02, doc 15 P3): one (dp, dm) per usb2 instance whose...
Evaluation evaluate(const model::Board &b, const model::DesignRules *rules, const Catalogue &cat, const Detection &det, Mode mode)
std::vector< ProximityPairs > proximity_pairs(const model::Board &b, const Catalogue &cat, const Detection &det)
Mode
–component-rules (doc 15 §3.5): off = nothing; report = detect and check only; soft = rules as costs,...
Definition engine.hpp:27
Mode parse_mode(std::string_view s)
throws std::invalid_argument
const char * mode_name(Mode m)
model::DesignRules with_synthetic_classes(const model::Board &b, model::DesignRules rules, const std::vector< SyntheticClass > &sc)
rules with the synthetic classes added and their nets assigned to them (in memory only,...
const char * status_name(Status s)
std::string dru_sidecar(const model::Board &b, const Catalogue &cat, const Detection &det)
The same intent as KiCad custom rules with net exemptions (which rule areas cannot express),...
Design rules as KiCad defines them (design doc 08 §3–4): board minimums and net classes from the ....
Connector edge pull for the placer (doc 15 §5.2 edge; CONN-01, USB2-11, DISP-02), opt-in (tracemaker-...
Definition engine.hpp:84
double max_mm
the rule's limit (report only)
Definition engine.hpp:88
std::vector< Point > body
Definition engine.hpp:86
std::string name
"CONN-01", "~CONN-01 J3 edge"
Definition engine.hpp:89
int weight
2 x signal weight, like ESD-01 (doc 15 §5.2)
Definition engine.hpp:87
Severity severity
after confidence demotion (doc 15 §3.2)
Definition engine.hpp:43
std::optional< ImpedancePlan > impedance
impedance rules: widths/gaps from the stackup (P4, report only)
Definition engine.hpp:47
const RuleSpec * spec
Definition engine.hpp:42
std::optional< Measure > measure
Definition engine.hpp:46
std::optional< CurrentPlan > current
width_for_current rules that name a current (IPC-2221, report only)
Definition engine.hpp:48
std::string detail
what was applied, or why not
Definition engine.hpp:45
int instance
index into Detection::instances
Definition engine.hpp:41
std::vector< EffectiveRule > rules
Definition engine.hpp:53
Keep-out rule areas (doc 15 §5.5, P2) for instances at confidence >= apply: crystal + load caps (XTAL...
Definition engine.hpp:99
std::string what
how it was measured
Definition engine.hpp:37
Placement pseudo-nets for every applicable proximity rule (mode soft or on; confidence >= suggest).
Definition engine.hpp:73
A proximity rule bound to pads (doc 15 §4 proximity): each pair is (pad of the part that should move ...
Definition engine.hpp:58
int weight
placement pseudo-net weight (kSignalWeight; x2 for ESD to connector, doc 15 §5.2)
Definition engine.hpp:63
std::string unbound
non-empty: a role it needs is missing
Definition engine.hpp:64
std::vector< std::pair< int, int > > pairs
Definition engine.hpp:61
const RuleSpec * spec
Definition engine.hpp:59
Net classes from rules (doc 15 §5.3-5.4 and §16, P5): impedance rules with a computed width/gap,...
Definition engine.hpp:119
model::NetClass cls
name "tmk_<RULE>_<anchor reference>"
Definition engine.hpp:120
std::vector< model::NetId > nets
Definition engine.hpp:121