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