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
74
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

//! A cascade placer uses a chain of placement algorithms to subsequently refine
//! the placement. For example the first stage finds a rough initial placement that will
//! be used as the initial state for the optimization in the second stage.

use super::stdcell_placer::SimpleStdCellPlacer;
use std::collections::{HashMap, HashSet};
use libreda_db::prelude::{SimplePolygon, Point};
use libreda_db::prelude as db;
use log::debug;
use libreda_db::netlist::traits::NetlistBase;

/// A pipeline of placers. The result of the first stage is
/// used as the initial placement for the next stage.
pub struct SimpleStdCellPlacerCascade<N: NetlistBase> {
    stages: Vec<Box<dyn SimpleStdCellPlacer<N>>>
}

impl<N: NetlistBase> SimpleStdCellPlacerCascade<N> {
    /// Create a new placer cascade.
    pub fn new(placers: Vec<Box<dyn SimpleStdCellPlacer<N>>>) -> Self {
        SimpleStdCellPlacerCascade {
            stages: placers
        }
    }
}

impl<N: NetlistBase> SimpleStdCellPlacer<N> for SimpleStdCellPlacerCascade<N> {
    fn name(&self) -> &str {
        "SimpleCascadePlacer"
    }

    fn find_cell_positions_impl(&self,
                                netlist: &N,
                                circuit_id: &N::CellId,
                                core_area: &SimplePolygon<db::Coord>,
                                initial_positions: &HashMap<N::CellInstId, Point<db::Coord>>,
                                fixed_instances: &HashSet<N::CellInstId>,
                                cell_outlines: &HashMap<N::CellId, db::Rect<db::Coord>>,
                                net_weights: &HashMap<N::NetId, f64>,
    ) -> HashMap<N::CellInstId, Point<i32>> {
        debug!("Placer cascade contains {} placers.", self.stages.len());

        let mut initial_pos = initial_positions.clone();

        // Use each placer after the other.
        for placer in &self.stages {
            let mut result = placer.find_cell_positions(
                netlist,
                circuit_id,
                core_area,
                &initial_pos,
                fixed_instances,
                cell_outlines,
                net_weights
            );

            // Carry-on positions of fixed instances.
            for inst in fixed_instances {
                result.insert(inst.clone(), initial_positions[inst]);
            }

            // Update the initial positions.
            initial_pos = result;
        }

        // Return the last placement result.
        initial_pos
    }
}