1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

//! Trait definitions for mixed-size placement algorithms.
//! Mixed-size placers find positions for macro block and standard-cells.

use db::L2NBase;
pub use libreda_db::prelude as db;
pub use libreda_db::prelude::{SInt, TryCastCoord, UInt, WindingNumber};

use super::placement_problem::PlacementProblem;
pub use libreda_db::iron_shapes::prelude::{Point, SimpleRPolygon};
use std::collections::HashMap;

/// Error type used for global placement.
#[derive(Debug)]
pub enum PlacementError {
    /// Stopped placement algorithm because the maximal number of iterations was reached.
    ReachedMaxIterations,
    /// The solution diverges. This is likely a bug in the placement algorithm.
    Divergence,
    /// Other type of error. Defined by an error message string.
    Other(String),
}

impl std::fmt::Display for PlacementError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            PlacementError::ReachedMaxIterations => {
                write!(f, "Reached maximum number of iterations.")
            }
            PlacementError::Divergence => write!(f, "Placement diverges."),
            PlacementError::Other(s) => write!(f, "{}", s),
        }
    }
}

impl std::error::Error for PlacementError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

/// Interface definition for mixed-size placement engines (for macro blocks and standard cells).
pub trait MixedSizePlacer<C: L2NBase> {
    /// Get the name of the placement engine.
    fn name(&self) -> &str;

    /// Actual implementation of [`MixedSizePlacer::find_cell_positions`].
    fn find_cell_positions_impl(
        &self,
        placement_problem: &dyn PlacementProblem<C>,
    ) -> Result<HashMap<C::CellInstId, db::SimpleTransform<C::Coord>>, PlacementError>;

    /// Find the positions of all circuit instances inside `circuit`.
    ///
    /// # Parameters
    ///
    /// * `placement_problem`: [`PlacementProblem`] trait object. This object bundles the netlist, layout and
    /// other parameters relevant for placement such as cell-sizes, fixed/movable cells, net weights.
    ///
    /// # Returns
    ///
    /// Returns a `HashMap` which maps circuit instances to positions.
    fn find_cell_positions(
        &self,
        placement_problem: &dyn PlacementProblem<C>,
    ) -> Result<HashMap<C::CellInstId, db::SimpleTransform<C::Coord>>, PlacementError> {
        self.find_cell_positions_impl(placement_problem)
    }
}