TraceMaker
C++ API of the engine
Loading...
Searching...
No Matches
tmk::place Namespace Reference

Namespaces

namespace  detail

Classes

struct  AnnealOptions
struct  AnnealResult
struct  LnsResult
 Large-neighbourhood search from start (legal): windows LNS windows (sizes and seeds from o; the stream is o.seed). More...
struct  WindowResult
 Exact window (doc 04 §3 F, without CP-SAT): the best placement of parts (others fixed) over a candidate set per part (its own spot, the other window parts' spots, its HPWL-optimal spot; four rotations each), by branch and bound with an HPWL bound. More...
struct  CongestionOptions
struct  CongestionMap
struct  SpreadStats
struct  Placement
class  Legality
class  Raster
 Conservative occupancy raster per side (cell 0.05–0.1 mm). More...
struct  Violations
 Every conflict in a placement (for the final report and tests): movable-involved pairs and parts outside. More...
struct  LegaliseStats
class  MinCostFlow
 Min-cost flow on a small graph (exposed for tests). More...
struct  PlaceOptions
struct  Metrics
struct  PlaceReport
struct  CopperShape
 A piece of copper with what KiCad's clearance check needs: layers, net and the clearance it asks for (its net class, local overrides and board minimum; pair clearance = max of the two). More...
struct  PartGeom
struct  Part
struct  Pin
struct  PNet
struct  Keepout
struct  Problem
struct  PadAffinity
 A design-intent pseudo-net between two board pads (doc 15 P1): pad_a belongs to the part that should sit near pad_b (an ESD part near its connector, a crystal near its IC's oscillator pins, ...). More...
struct  EdgePull
 An objective-only pull of a part toward the board outline (doc 15 CONN-01, opt-in): the body point nearest to the outline in the input becomes a one-pin pseudo-net anchored on the nearest outline segment's axis (x for a mostly vertical segment, y for a mostly horizontal one), so the pull is exact in the annealer's integer cost and rotating the part away from the edge costs too. More...
struct  ExtractOptions
struct  RouteEval
 What the router reports for one placement. More...
struct  Candidate
struct  EcoMemory
 Failure memory (doc 04 §4 step 4): moves already routed without improvement, by part, target and rotation. More...
struct  EcoOptions
struct  EcoResult
struct  LoopOptions
struct  LoopResult
struct  Seg
struct  Box
struct  Point
struct  Shape

Typedefs

using RouteFn = std::function<RouteEval(const Placement&)>

Enumerations

enum class  RotationModel { Fixed , Any }

Functions

double trace_now ()
 Recording clock (video timelapse): steady-clock seconds. Only ever written to recordings.
AnnealResult anneal (const Problem &p, const Placement &start, const AnnealOptions &o)
 start must be legal for every movable part.
std::int64_t anneal_cost (const Problem &p, const Placement &pl, double alpha_cross_mm, double beta=0, const CongestionMap *m=nullptr, double via_mm=0)
 Cost used by the annealer, from scratch (reference path): weighted HPWL + α·crossings + β·RUDY overflow, all in the annealer's integer units.
LnsResult lns_improve (const Problem &p, const Placement &start, const AnnealOptions &o, int windows)
WindowResult solve_window (const Problem &p, Placement &pl, const std::vector< int > &parts, const AnnealOptions &o, bool prune=true, long max_leaves=200 '000)
CongestionMap make_congestion_map (const Problem &p, const CongestionOptions &o={})
bool rudy_net (const Problem &p, int net)
 True if the net contributes RUDY demand (signal nets with at least two pins).
Box net_box (const Problem &p, const Placement &pl, int net)
 Pin bounding box of one net.
template<class Touch>
void add_box_demand (const CongestionMap &m, const Box &b, int sign, std::vector< std::int64_t > &demand, Touch &&touch)
 Adds sign × the RUDY demand of a net with pin bounding box b to demand.
std::vector< std::int64_t > rudy_demand (const Problem &p, const Placement &pl, const CongestionMap &m)
 From-scratch demand of a placement (reference path for the annealer's incremental bookkeeping).
std::int64_t bin_overflow (std::int64_t demand, std::int64_t cap)
std::int64_t total_overflow (const CongestionMap &m, const std::vector< std::int64_t > &demand)
std::int64_t rudy_overflow (const Problem &p, const Placement &pl, const CongestionMap &m)
void scale_bins (CongestionMap &m, const std::vector< Point > &pts, Coord radius, double factor)
 Multiplies the capacity of the bins within radius of each point by factor (once per bin per call).
void quadratic_place (const Problem &p, Placement &pl, int relinearise, const std::vector< Point > *anchor=nullptr, const std::vector< double > *anchor_w=nullptr)
 (A) Solves the B2B quadratic program for the movable parts (rotations taken from pl), relinearise times.
SpreadStats spread (const Problem &p, Placement &pl, int max_iterations=40, double target_overflow=0.10, std::vector< Placement > *trace=nullptr)
 (B) SimPL loop starting from a quadratic placement pl; on return pl holds the spread (upper-bound) placement.
double density_overflow (const Problem &p, const Placement &pl)
 Bin density overflow of a placement: Σ max(0, demand − capacity) / Σ demand over a bin grid per side.
std::array< double, 2 > utilisation (const Problem &p)
 Movable courtyard area (incl. clearance) / free board area, per side.
int optimise_rotations (const Problem &p, Placement &pl, int max_passes=20)
 (C) Rotation coordinate descent over the movable parts (HPWL of each part's nets).
std::vector< std::vector< int > > part_nets (const Problem &p)
 Nets touching each part (sorted, unique).
bool closer (const Shape &a, Point da, const Shape &b, Point db, Coord clearance)
 Exact test with translation (no copies): same semantics as geom::closer_than(a + da, b + db, clearance).
bool copper_conflict (const CopperShape &a, Point pa, const CopperShape &b, Point pb)
 Copper clearance violation between two copper shapes (different nets, shared layer, max of the two needs).
Violations check_all (const Problem &p, const Placement &pl)
LegaliseStats legalise (const Problem &p, Placement &pl, bool only_illegal, Coord cell=0, const std::vector< int > *first=nullptr)
 only_illegal: parts that are already legal (inside the board, conflict-free) stay where they are and only the others are re-placed (refine mode).
std::int64_t hpwl_lower_bound (const Problem &p, const Placement &pl, RotationModel model)
 Minimum weighted HPWL (Σ weight · HPWL, nm) over all positions of the movable parts with overlaps and the board outline ignored.
Metrics measure (const Problem &p, const Placement &pl, const Placement *reference=nullptr)
std::optional< Placement > repaired (const Problem &p, const Placement &pl, int *moved=nullptr)
 Minimal repair: re-place only conflicting movable parts at the nearest legal spot (refine's legaliser).
PlaceReport place (const Problem &p, Placement &pl, const PlaceOptions &o)
nlohmann::json report_json (const Problem &p, const PlaceReport &r)
std::size_t z (int i)
bool flipped (int state)
std::uint8_t with_turn (int state, int r)
 State with the same side as state and r quarter turns.
Point mirror_y (Point p)
std::uint8_t swap_state (int b_state, int dk)
 Exchanging two interchangeable parts a and b (same footprint and input side; angle0_b − angle0_a = 90° dk): the state that gives a the absolute pose b has in b_state.
Problem extract (const model::Board &b, const model::DesignRules &rules, const std::string &board_path, const ExtractOptions &opt={})
 Builds the problem. rules and board_path give the courtyard clearance (custom rules or .kicad_pro).
Shape translated (const Shape &s, Point d)
 Geometry helpers.
Shape mirrored (const Shape &s)
 Mirror in y about the origin (polygon winding kept).
model::LayerMask flip_layers (model::LayerMask m, int n)
 Copper layer mask of the other side: bit i <-> bit n−1−i for n copper layers (KiCad FlipLayerMask).
Point rot90 (Point p, int r)
 KiCad rotation by r * 90 degrees.
std::vector< Point > convex_hull (std::vector< Point > pts)
Shape inset_convex (const Shape &s, Coord t)
 Inner parallel polygon of a convex polygon at distance t; a point at the centroid if it is thinner than 2t.
bool power_like_name (const std::string &name)
bool ground_like_name (const std::string &name)
bool better (const Candidate &a, const Candidate &b)
 Better routed result: fewer unrouted connections, then shorter wirelength.
EcoResult eco_place (const Problem &p, const Placement &start, const RouteEval &start_eval, const EcoOptions &o, const RouteFn &route)
 Small moves of movable parts near the failed connections of start (shift, rotate, swap with an identical part), ranked by a geometric estimate (annealing cost with boosted failed nets, penalised congestion bins and a displacement charge), the top ones routed; the best strictly improving move is committed per round.
LoopResult routability_loop (const Problem &p, std::vector< Candidate > seeds, const LoopOptions &o, const RouteFn &route)
 Routes the seeds (those without a result), keeps the best, then for up to rounds rounds re-places around the failed connections (refine annealing with β·RUDY over a capacity map shrunk where the router failed, boosted weights for the failed nets, LNS windows centred on their parts) and tries ECO moves; a candidate replaces the incumbent only if it leaves fewer connections unrouted.
Coord net_hpwl (const Problem &p, const Placement &pl, int net)
 HPWL of one net (unweighted, nm).
std::int64_t weighted_hpwl (const Problem &p, const Placement &pl)
 Σ weight · HPWL over all nets (weights kSignalWeight / kPowerWeight).
std::int64_t total_hpwl (const Problem &p, const Placement &pl)
 Σ HPWL over all nets, unweighted (nm).
std::int64_t side_vias (const Problem &p, const Placement &pl, bool weighted)
 Via estimate of the side assignment (doc 04 §3 C, D48): a net whose surface-mount pins sit on both sides needs at least one via per pin on its minority side, so it counts min(front, back) such pins.
std::array< int, 2 > side_counts (const Problem &p, const Placement &pl, int net)
 Front/back surface-mount pin counts of one net in pl (as used by side_vias).
void net_mst (const std::vector< Point > &pts, int net, std::vector< Seg > &out)
 Minimum spanning tree of the pins (Prim, Manhattan metric, ties by pin order) appended to out.
bool proper_cross (const Seg &s, const Seg &t)
 True if the two segments cross at a single interior point (touching or collinear overlap does not count).
std::vector< Seg > airwires (const Problem &p, const Placement &pl)
 MST airwires of every signal net.
std::int64_t count_crossings (const Problem &p, const Placement &pl)
 Number of crossing pairs of airwires that belong to different signal nets (reference: O(n²)).

Variables

constexpr Coord kThroughMargin = 100'000
 through obstacle vs courtyard on the other side
constexpr Coord kThroughThrough = 250'000
 through obstacle vs through obstacle
constexpr int kSignalWeight = 10
 Net weights are small integers so every cost is an exact integer (CLAUDE.md rule 2).
constexpr int kPowerWeight = 1
constexpr Coord kEdgeTolerance = 250'000
 courtyard may extend this far past the board edge
constexpr int kStates = 8
 Orientation state of a part (Placement::rot): bits 0–1 = quarter turns r, bit 2 = flipped to the other side.
constexpr std::uint8_t kFlipBit = 4

Typedef Documentation

◆ RouteFn

using tmk::place::RouteFn = std::function<RouteEval(const Placement&)>

Definition at line 32 of file routable.hpp.

Enumeration Type Documentation

◆ RotationModel

enum class tmk::place::RotationModel
strong
Enumerator
Fixed 

movable parts keep the rotations in the given placement: the exact relaxed optimum for them

Any 

valid for every rotation of the movable parts (each pin may take its most favourable offset

Definition at line 17 of file lower_bound.hpp.

Function Documentation

◆ add_box_demand()

template<class Touch>
void tmk::place::add_box_demand ( const CongestionMap & m,
const Box & b,
int sign,
std::vector< std::int64_t > & demand,
Touch && touch )

Adds sign × the RUDY demand of a net with pin bounding box b to demand.

touch(bin) is called before a bin is changed (for incremental bookkeeping); pass a no-op lambda when not needed.

Bins at the grid border absorb everything beyond it.

Definition at line 83 of file congestion.hpp.

◆ airwires()

std::vector< Seg > tmk::place::airwires ( const Problem & p,
const Placement & pl )

MST airwires of every signal net.

◆ anneal()

AnnealResult tmk::place::anneal ( const Problem & p,
const Placement & start,
const AnnealOptions & o )

start must be legal for every movable part.

◆ anneal_cost()

std::int64_t tmk::place::anneal_cost ( const Problem & p,
const Placement & pl,
double alpha_cross_mm,
double beta = 0,
const CongestionMap * m = nullptr,
double via_mm = 0 )

Cost used by the annealer, from scratch (reference path): weighted HPWL + α·crossings + β·RUDY overflow, all in the annealer's integer units.

◆ better()

bool tmk::place::better ( const Candidate & a,
const Candidate & b )

Better routed result: fewer unrouted connections, then shorter wirelength.

◆ bin_overflow()

std::int64_t tmk::place::bin_overflow ( std::int64_t demand,
std::int64_t cap )
inline

Definition at line 55 of file congestion.hpp.

◆ check_all()

Violations tmk::place::check_all ( const Problem & p,
const Placement & pl )

◆ closer()

bool tmk::place::closer ( const Shape & a,
Point da,
const Shape & b,
Point db,
Coord clearance )

Exact test with translation (no copies): same semantics as geom::closer_than(a + da, b + db, clearance).

◆ convex_hull()

std::vector< Point > tmk::place::convex_hull ( std::vector< Point > pts)

◆ copper_conflict()

bool tmk::place::copper_conflict ( const CopperShape & a,
Point pa,
const CopperShape & b,
Point pb )

Copper clearance violation between two copper shapes (different nets, shared layer, max of the two needs).

◆ count_crossings()

std::int64_t tmk::place::count_crossings ( const Problem & p,
const Placement & pl )

Number of crossing pairs of airwires that belong to different signal nets (reference: O(n²)).

◆ density_overflow()

double tmk::place::density_overflow ( const Problem & p,
const Placement & pl )

Bin density overflow of a placement: Σ max(0, demand − capacity) / Σ demand over a bin grid per side.

◆ eco_place()

EcoResult tmk::place::eco_place ( const Problem & p,
const Placement & start,
const RouteEval & start_eval,
const EcoOptions & o,
const RouteFn & route )

Small moves of movable parts near the failed connections of start (shift, rotate, swap with an identical part), ranked by a geometric estimate (annealing cost with boosted failed nets, penalised congestion bins and a displacement charge), the top ones routed; the best strictly improving move is committed per round.

Moves that failed are remembered and not tried again.

◆ extract()

Problem tmk::place::extract ( const model::Board & b,
const model::DesignRules & rules,
const std::string & board_path,
const ExtractOptions & opt = {} )

Builds the problem. rules and board_path give the courtyard clearance (custom rules or .kicad_pro).

◆ flip_layers()

model::LayerMask tmk::place::flip_layers ( model::LayerMask m,
int n )

Copper layer mask of the other side: bit i <-> bit n−1−i for n copper layers (KiCad FlipLayerMask).

◆ flipped()

bool tmk::place::flipped ( int state)
inline

Definition at line 55 of file problem.hpp.

◆ ground_like_name()

bool tmk::place::ground_like_name ( const std::string & name)

◆ hpwl_lower_bound()

std::int64_t tmk::place::hpwl_lower_bound ( const Problem & p,
const Placement & pl,
RotationModel model )

Minimum weighted HPWL (Σ weight · HPWL, nm) over all positions of the movable parts with overlaps and the board outline ignored.

Fixed parts are taken from pl.

◆ inset_convex()

Shape tmk::place::inset_convex ( const Shape & s,
Coord t )

Inner parallel polygon of a convex polygon at distance t; a point at the centroid if it is thinner than 2t.

◆ legalise()

LegaliseStats tmk::place::legalise ( const Problem & p,
Placement & pl,
bool only_illegal,
Coord cell = 0,
const std::vector< int > * first = nullptr )

only_illegal: parts that are already legal (inside the board, conflict-free) stay where they are and only the others are re-placed (refine mode).

cell is the raster cell (0 = automatic, 0.05–0.1 mm). first: parts to place before all others (e.g. the failures of an earlier attempt).

◆ lns_improve()

LnsResult tmk::place::lns_improve ( const Problem & p,
const Placement & start,
const AnnealOptions & o,
int windows )

◆ make_congestion_map()

CongestionMap tmk::place::make_congestion_map ( const Problem & p,
const CongestionOptions & o = {} )

◆ measure()

Metrics tmk::place::measure ( const Problem & p,
const Placement & pl,
const Placement * reference = nullptr )

◆ mirror_y()

Point tmk::place::mirror_y ( Point p)
inline

Definition at line 58 of file problem.hpp.

◆ mirrored()

Shape tmk::place::mirrored ( const Shape & s)

Mirror in y about the origin (polygon winding kept).

◆ net_box()

Box tmk::place::net_box ( const Problem & p,
const Placement & pl,
int net )

Pin bounding box of one net.

◆ net_hpwl()

Coord tmk::place::net_hpwl ( const Problem & p,
const Placement & pl,
int net )

HPWL of one net (unweighted, nm).

◆ net_mst()

void tmk::place::net_mst ( const std::vector< Point > & pts,
int net,
std::vector< Seg > & out )

Minimum spanning tree of the pins (Prim, Manhattan metric, ties by pin order) appended to out.

◆ optimise_rotations()

int tmk::place::optimise_rotations ( const Problem & p,
Placement & pl,
int max_passes = 20 )

(C) Rotation coordinate descent over the movable parts (HPWL of each part's nets).

Returns the number of rotation changes; terminates because every change strictly lowers the weighted HPWL.

◆ part_nets()

std::vector< std::vector< int > > tmk::place::part_nets ( const Problem & p)

Nets touching each part (sorted, unique).

◆ place()

PlaceReport tmk::place::place ( const Problem & p,
Placement & pl,
const PlaceOptions & o )

◆ power_like_name()

bool tmk::place::power_like_name ( const std::string & name)

◆ proper_cross()

bool tmk::place::proper_cross ( const Seg & s,
const Seg & t )

True if the two segments cross at a single interior point (touching or collinear overlap does not count).

◆ quadratic_place()

void tmk::place::quadratic_place ( const Problem & p,
Placement & pl,
int relinearise,
const std::vector< Point > * anchor = nullptr,
const std::vector< double > * anchor_w = nullptr )

(A) Solves the B2B quadratic program for the movable parts (rotations taken from pl), relinearise times.

Optional anchors pull part i towards anchor[i] with weight anchor_w[i] × (the part's net weight in the current linearisation); 0 = no anchor.

◆ repaired()

std::optional< Placement > tmk::place::repaired ( const Problem & p,
const Placement & pl,
int * moved = nullptr )

Minimal repair: re-place only conflicting movable parts at the nearest legal spot (refine's legaliser).

Empty if no legal repair is found; moved returns the number of parts re-placed.

◆ report_json()

nlohmann::json tmk::place::report_json ( const Problem & p,
const PlaceReport & r )

◆ rot90()

Point tmk::place::rot90 ( Point p,
int r )

KiCad rotation by r * 90 degrees.

◆ routability_loop()

LoopResult tmk::place::routability_loop ( const Problem & p,
std::vector< Candidate > seeds,
const LoopOptions & o,
const RouteFn & route )

Routes the seeds (those without a result), keeps the best, then for up to rounds rounds re-places around the failed connections (refine annealing with β·RUDY over a capacity map shrunk where the router failed, boosted weights for the failed nets, LNS windows centred on their parts) and tries ECO moves; a candidate replaces the incumbent only if it leaves fewer connections unrouted.

◆ rudy_demand()

std::vector< std::int64_t > tmk::place::rudy_demand ( const Problem & p,
const Placement & pl,
const CongestionMap & m )

From-scratch demand of a placement (reference path for the annealer's incremental bookkeeping).

◆ rudy_net()

bool tmk::place::rudy_net ( const Problem & p,
int net )

True if the net contributes RUDY demand (signal nets with at least two pins).

◆ rudy_overflow()

std::int64_t tmk::place::rudy_overflow ( const Problem & p,
const Placement & pl,
const CongestionMap & m )

◆ scale_bins()

void tmk::place::scale_bins ( CongestionMap & m,
const std::vector< Point > & pts,
Coord radius,
double factor )

Multiplies the capacity of the bins within radius of each point by factor (once per bin per call).

◆ side_counts()

std::array< int, 2 > tmk::place::side_counts ( const Problem & p,
const Placement & pl,
int net )

Front/back surface-mount pin counts of one net in pl (as used by side_vias).

◆ side_vias()

std::int64_t tmk::place::side_vias ( const Problem & p,
const Placement & pl,
bool weighted )

Via estimate of the side assignment (doc 04 §3 C, D48): a net whose surface-mount pins sit on both sides needs at least one via per pin on its minority side, so it counts min(front, back) such pins.

Through-hole pins reach both sides and do not count; pseudo-nets never count. weighted: Σ weight · min(...), else Σ min(...).

◆ solve_window()

WindowResult tmk::place::solve_window ( const Problem & p,
Placement & pl,
const std::vector< int > & parts,
const AnnealOptions & o,
bool prune = true,
long max_leaves = 200 '000 )

◆ spread()

SpreadStats tmk::place::spread ( const Problem & p,
Placement & pl,
int max_iterations = 40,
double target_overflow = 0.10,
std::vector< Placement > * trace = nullptr )

(B) SimPL loop starting from a quadratic placement pl; on return pl holds the spread (upper-bound) placement.

trace (optional) receives the spread placement of every iteration.

◆ swap_state()

std::uint8_t tmk::place::swap_state ( int b_state,
int dk )
inline

Exchanging two interchangeable parts a and b (same footprint and input side; angle0_b − angle0_a = 90° dk): the state that gives a the absolute pose b has in b_state.

Flipping negates angle0, so dk changes sign there. (b takes a's pose with swap_state(a_state, −dk).)

Definition at line 62 of file problem.hpp.

◆ total_hpwl()

std::int64_t tmk::place::total_hpwl ( const Problem & p,
const Placement & pl )

Σ HPWL over all nets, unweighted (nm).

◆ total_overflow()

std::int64_t tmk::place::total_overflow ( const CongestionMap & m,
const std::vector< std::int64_t > & demand )

◆ trace_now()

double tmk::place::trace_now ( )
inline

Recording clock (video timelapse): steady-clock seconds. Only ever written to recordings.

Definition at line 37 of file anneal.hpp.

◆ translated()

Shape tmk::place::translated ( const Shape & s,
Point d )

Geometry helpers.

◆ utilisation()

std::array< double, 2 > tmk::place::utilisation ( const Problem & p)

Movable courtyard area (incl. clearance) / free board area, per side.

◆ weighted_hpwl()

std::int64_t tmk::place::weighted_hpwl ( const Problem & p,
const Placement & pl )

Σ weight · HPWL over all nets (weights kSignalWeight / kPowerWeight).

◆ with_turn()

std::uint8_t tmk::place::with_turn ( int state,
int r )
inline

State with the same side as state and r quarter turns.

Definition at line 57 of file problem.hpp.

◆ z()

std::size_t tmk::place::z ( int i)
inline

Definition at line 21 of file problem.hpp.

Variable Documentation

◆ kEdgeTolerance

Coord tmk::place::kEdgeTolerance = 250'000
inlineconstexpr

courtyard may extend this far past the board edge

Definition at line 26 of file problem.hpp.

◆ kFlipBit

std::uint8_t tmk::place::kFlipBit = 4
inlineconstexpr

Definition at line 54 of file problem.hpp.

◆ kPowerWeight

int tmk::place::kPowerWeight = 1
inlineconstexpr

Definition at line 25 of file problem.hpp.

◆ kSignalWeight

int tmk::place::kSignalWeight = 10
inlineconstexpr

Net weights are small integers so every cost is an exact integer (CLAUDE.md rule 2).

Definition at line 24 of file problem.hpp.

◆ kStates

int tmk::place::kStates = 8
inlineconstexpr

Orientation state of a part (Placement::rot): bits 0–1 = quarter turns r, bit 2 = flipped to the other side.

State r means angle0 + 90 r on the input side; state 4 + r means the KiCad flip (top/bottom about the origin: offsets mirrored in y, orientation −angle0) followed by r quarter turns, i.e. −angle0 + 90 r on the other side.

Definition at line 53 of file problem.hpp.

◆ kThroughMargin

Coord tmk::place::kThroughMargin = 100'000
inlineconstexpr

through obstacle vs courtyard on the other side

Definition at line 29 of file legality.hpp.

◆ kThroughThrough

Coord tmk::place::kThroughThrough = 250'000
inlineconstexpr

through obstacle vs through obstacle

Definition at line 30 of file legality.hpp.