libreda_pnr/place/placement_problem.rs
1// Copyright (c) 2020-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! Representation of the placement problem.
7//!
8//! A trait based representation gives more flexibility than passing naked arguments
9//! to the placement engine.
10
11use libreda_db::prelude as db;
12use std::collections::HashSet;
13
14/// Describe the placement status of a cell instance.
15#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
16pub enum PlacementStatus {
17 /// The instance location is fixed and must remain.
18 Fixed,
19 /// The instance can be put into another location by the placement engine.
20 Movable,
21 /// The instance should be ignored by the placement engine.
22 Ignore,
23}
24
25/// Representation of the placement task.
26pub trait PlacementProblem<C: db::L2NBase> {
27 /// Get the base layout/netlist structure.
28 fn fused_layout_netlist(&self) -> &C;
29
30 /// Get the top cell whose content should be placed.
31 fn top_cell(&self) -> C::CellId;
32
33 /// Get a list of polygons which describe where cells are allowed to be placed.
34 fn placement_region(&self) -> Vec<db::SimpleRPolygon<C::Coord>>;
35
36 /// Get regions which should not be used for placement but can if necessary.
37 /// Overlap of cells with this regions should be minimized.
38 fn soft_blockages(&self) -> Vec<db::SimpleRPolygon<C::Coord>> {
39 vec![]
40 }
41
42 /// Get the position of a cell instance which should be used as an initial value
43 /// for the optimization.
44 /// This is most likely the output of the previous placement step.
45 fn initial_position(&self, cell_instance: &C::CellInstId) -> db::SimpleTransform<C::Coord>;
46
47 /// Tell if the cell instance can be moved by the placement engine.
48 fn placement_status(&self, cell_instance: &C::CellInstId) -> PlacementStatus;
49
50 /// Get the abutment box / outline of the cell.
51 fn cell_outline(&self, cell: &C::CellId) -> Option<db::Rect<C::Coord>>;
52
53 /// Get the abutment box / outline of the cell instance.
54 fn cell_instance_outline(&self, cell_instance: &C::CellInstId) -> Option<db::Rect<C::Coord>> {
55 let template = self.fused_layout_netlist().template_cell(cell_instance);
56 self.cell_outline(&template)
57 }
58
59 /// Get the weight of a net. Default is `1.0`.
60 /// When optimizing the wire-length, the *weighted* wire-length should be used.
61 /// For example a weight `0.0` means that the net should not be considered for wire-length optimization.
62 fn net_weight(&self, _net: &C::NetId) -> f64 {
63 1.0
64 }
65
66 /// TODO: fn arc_weight(&self, arc: &ArcId<C>) -> f64;
67
68 /// Get the set of fixed instances.
69 fn get_fixed_instances(&self) -> HashSet<C::CellInstId> {
70 self.fused_layout_netlist()
71 .each_cell_instance(&self.top_cell())
72 .filter(|inst| self.placement_status(inst) == PlacementStatus::Fixed)
73 .collect()
74 }
75
76
77 /// Get the set of movable cell instances.
78 fn get_movable_instances(&self) -> HashSet<C::CellInstId> {
79 self.fused_layout_netlist()
80 .each_cell_instance(&self.top_cell())
81 .filter(|inst| self.placement_status(inst) == PlacementStatus::Movable)
82 .collect()
83 }
84}
85