TraceMaker
C++ API of the engine
Loading...
Searching...
No Matches
bus.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2#pragma once
3// Buses (design doc 05 §38): groups of nets that belong together (a data bus, an address bus, a parallel display
4// interface). This file holds what does not need the router: how a group is named on the command line, how groups
5// are found in the net names, which skew limit the board's rules give a group, and the measurement of a routed
6// group. The routing of a group lives in the router (route/router.cpp, "buses").
7#include <optional>
8#include <string>
9#include <string_view>
10#include <vector>
11
12#include "drc/rule_engine.hpp"
13#include "model/board.hpp"
14#include "model/rules.hpp"
15
16namespace tmk::route {
17
18struct BusGroup {
19 std::string name;
20 std::vector<model::NetId> members; // in bus order: natural sort of the net names (D2 before D10)
21 std::string source; // "option" (--bus) or "detected" (--buses)
22 Coord skew_limit = 0; // largest allowed difference in length between members; 0 = none
23 std::string skew_source; // "rule" (a custom skew rule of the board), "option" (--bus-skew-mm) or empty
24};
25
26// Natural order of two names: runs of digits compare as numbers, everything else byte by byte.
27bool natural_less(std::string_view a, std::string_view b);
28
29// Bus patterns select nets by their full name (KiCad's, with the sheet path: "/D0", "/MEM/DQ3").
30// [N-M] or [N..M], N <= M decimal numbers: an index range, matching any decimal number in it ("D[0-15]" matches
31// D0 .. D15, and D07 too). A range needs both bounds; "[[0-7]]" is a range in literal brackets,
32// for nets named A[0] .. A[7].
33// * and ?: as in KiCad's net-class patterns (any run of characters, any one character).
34// A pattern without an index range is matched exactly as a KiCad net-class pattern (model::pattern_match: wildcards,
35// or a full regular expression). In a pattern with a range everything outside the range and the wildcards is literal.
36bool bus_pattern_match(const std::string& pattern, const std::string& net_name);
37
38// "NAME=PATTERN" as given to --bus. Throws std::runtime_error when there is no '=', the name or pattern is empty, or
39// fewer than two nets with pads match.
40BusGroup bus_from_option(const model::Board& b, const std::string& spec);
41
42// Automatic detection (--buses), conservative: nets whose names differ only in a trailing decimal index ("D0", "A[3]",
43// "/MEM/DQ12"), at least `min_members` of them with pads on the same two components. KiCad's generated names
44// ("Net-(U1-Pad3)", "unconnected-...") are never grouped. One stem may give several groups (D0-7 to one memory,
45// D8-15 to another); they are then named STEM(REF-REF). Groups come in natural order of their names.
46std::vector<BusGroup> detect_buses(const model::Board& b, int min_members = 4);
47
48// The skew limit the board's custom rules give a group: every member must match a rule with a `skew` constraint
49// (the smallest maximum wins); rules restricted to differential pairs (`within_diff_pairs`) do not count.
50std::optional<Coord> bus_rule_skew(const drc::RuleEngine& re, const BusGroup& g);
51
52// The length a via adds to its net in KiCad's length calculation, which its `skew` check uses (KiCad 10,
53// BOARD_STACKUP::GetLayerDistance): the stackup between the two copper layers the via joins, with the copper of an
54// outer layer in full and of an inner layer by half. A board without a stackup block gets KiCad's default one
55// (35 um copper, 10 um per solder mask, the rest of the board thickness shared evenly between the dielectrics).
56// Empty (every via 0) when the project turns "use height for length calculations" off.
57struct ViaHeights {
58 std::vector<Coord> from, to; // per copper layer: where a via starting / ending on it begins / ends, nm from the top
59 Coord between(int a, int b) const; // copper indices, either order; 0 for a == b
60};
62// The via length of one net on the given copper, as KiCad sums it: each via counts between the outermost layers on
63// which a track of the net ends inside the via's pad, or a pad of the net touches the via (a surface pad's own
64// layer, its footprint's side for a through-hole pad); a via that joins nothing on a second layer adds nothing.
65double net_via_length(const model::Board& b, const ViaHeights& vh, model::NetId net, const std::vector<model::Track>& tracks,
66 const std::vector<model::ArcTrack>& arcs, const std::vector<model::Via>& vias);
67
68// A group as routed, measured on copper. Length is what KiCad's skew check compares: track length (arcs included)
69// plus the via length above, so a member with more vias than the others is longer by their height. KiCad also
70// adds pad-to-die lengths and shortens a track end inside a pad or via; neither is modelled (micrometres, or zero).
71struct BusMember {
73 bool routed = false; // every pad of the net is joined
74 double length = 0; // nm, tracks and vias
75 double via_length = 0; // nm, the vias' part of `length`
76 int vias = 0;
77 model::LayerMask layers = 0; // copper layers carrying tracks of the net
78 bool followed = false; // routed with the group's reference via count and layers
79};
80struct BusStats {
81 std::vector<BusMember> members; // group order
82 int routed = 0;
83 // The reference is the via count and layer set most members share (ties: the first member's in group order).
84 // `followed` members have exactly that; `left` are routed otherwise ("left the bus").
85 int followed = 0, left = 0;
86 int ref_vias = 0;
88 int vias_min = 0, vias_max = 0; // over routed members
89 double length_min = 0, length_max = 0;
90 double skew() const { return length_max - length_min; } // over routed members
91};
92// `net_routed[net]`: nets_joined() of the board the copper belongs to; `b` gives the pads, `vh` its via heights.
93BusStats measure_bus(const model::Board& b, const ViaHeights& vh, const std::vector<model::Track>& tracks, const std::vector<model::ArcTrack>& arcs, const std::vector<model::Via>& vias,
94 const std::vector<std::uint8_t>& net_routed, const BusGroup& g);
95
96// Per net: 1 when all its pads are joined by copper (the router's own connectivity; nets without pads count as joined).
97std::vector<std::uint8_t> nets_joined(const model::Board& b, const model::DesignRules& rules);
98
99} // namespace tmk::route
The board model (design doc 02 §3): every object TraceMaker reads from a .kicad_pcb,...
compiled custom-rule condition
std::int32_t NetId
0 = no net
Definition board.hpp:21
std::uint64_t LayerMask
bit i = copper layer i in stack order (0 = F.Cu, last = B.Cu)
Definition board.hpp:22
std::optional< Coord > bus_rule_skew(const drc::RuleEngine &re, const BusGroup &g)
The skew limit the board's custom rules give a group: every member must match a rule with a skew cons...
BusStats measure_bus(const model::Board &b, const ViaHeights &vh, const std::vector< model::Track > &tracks, const std::vector< model::ArcTrack > &arcs, const std::vector< model::Via > &vias, const std::vector< std::uint8_t > &net_routed, const BusGroup &g)
net_routed[net]: nets_joined() of the board the copper belongs to; b gives the pads,...
BusGroup bus_from_option(const model::Board &b, const std::string &spec)
"NAME=PATTERN" as given to –bus.
std::vector< BusGroup > detect_buses(const model::Board &b, int min_members=4)
Automatic detection (–buses), conservative: nets whose names differ only in a trailing decimal index ...
bool bus_pattern_match(const std::string &pattern, const std::string &net_name)
Bus patterns select nets by their full name (KiCad's, with the sheet path: "/D0", "/MEM/DQ3").
std::vector< std::uint8_t > nets_joined(const model::Board &b, const model::DesignRules &rules)
Per net: 1 when all its pads are joined by copper (the router's own connectivity; nets without pads c...
bool natural_less(std::string_view a, std::string_view b)
Natural order of two names: runs of digits compare as numbers, everything else byte by byte.
double net_via_length(const model::Board &b, const ViaHeights &vh, model::NetId net, const std::vector< model::Track > &tracks, const std::vector< model::ArcTrack > &arcs, const std::vector< model::Via > &vias)
The via length of one net on the given copper, as KiCad sums it: each via counts between the outermos...
ViaHeights via_heights(const model::Board &b, const model::DesignRules &rules)
std::int64_t Coord
Engine coordinate: signed 64-bit nanometres.
Definition units.hpp:12
Resolves KiCad constraints for pairs of copper items (design doc 03 §6): net-class clearances,...
Design rules as KiCad defines them (design doc 08 §3–4): board minimums and net classes from the ....
Coord skew_limit
largest allowed difference in length between members; 0 = none
Definition bus.hpp:22
std::string source
"option" (–bus) or "detected" (–buses)
Definition bus.hpp:21
std::string skew_source
"rule" (a custom skew rule of the board), "option" (–bus-skew-mm) or empty
Definition bus.hpp:23
std::string name
Definition bus.hpp:19
std::vector< model::NetId > members
in bus order: natural sort of the net names (D2 before D10)
Definition bus.hpp:20
A group as routed, measured on copper.
Definition bus.hpp:71
model::NetId net
Definition bus.hpp:72
model::LayerMask layers
copper layers carrying tracks of the net
Definition bus.hpp:77
bool routed
every pad of the net is joined
Definition bus.hpp:73
double via_length
nm, the vias' part of length
Definition bus.hpp:75
bool followed
routed with the group's reference via count and layers
Definition bus.hpp:78
double length
nm, tracks and vias
Definition bus.hpp:74
int followed
The reference is the via count and layer set most members share (ties: the first member's in group or...
Definition bus.hpp:85
double length_min
Definition bus.hpp:89
double length_max
Definition bus.hpp:89
int vias_max
over routed members
Definition bus.hpp:88
model::LayerMask ref_layers
Definition bus.hpp:87
double skew() const
Definition bus.hpp:90
std::vector< BusMember > members
group order
Definition bus.hpp:81
The length a via adds to its net in KiCad's length calculation, which its skew check uses (KiCad 10,...
Definition bus.hpp:57
Coord between(int a, int b) const
copper indices, either order; 0 for a == b
std::vector< Coord > from
Definition bus.hpp:58
std::vector< Coord > to
per copper layer: where a via starting / ending on it begins / ends, nm from the top
Definition bus.hpp:58