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
// 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::mixed_size_placer::MixedSizePlacer;
use std::collections::HashMap;
use libreda_db::prelude as db;
use libreda_db::traits::*;
use log;
use crate::place::placement_problem::PlacementProblem;
use crate::place::mixed_size_placer::PlacementError;
use crate::place::placement_problem_overlay::PlacementProblemOverlay;

/// A pipeline of placers. The result of the first stage is
/// used as the initial placement for the next stage.
pub struct PlacerCascade<L: L2NBase> {
    stages: Vec<Box<dyn MixedSizePlacer<L>>>
}

impl<L: L2NBase> PlacerCascade<L> {
    /// Create a new placer cascade.
    pub fn new(placers: Vec<Box<dyn MixedSizePlacer<L>>>) -> Self {
        PlacerCascade {
            stages: placers
        }
    }
}

impl<C: L2NBase> MixedSizePlacer<C> for PlacerCascade<C> {
    fn name(&self) -> &str {
        "CascadePlacer"
    }

    fn find_cell_positions_impl(
        &self,
        placement_problem: &dyn PlacementProblem<C>
    ) -> Result<HashMap<C::CellInstId, db::SimpleTransform<C::Coord>>, PlacementError> {
        log::debug!("Run placer cascade with {} placers.", self.stages.len());

        // Wrap the placement problem such that the positions of the cells
        // can be updated incrementally.
        let mut placement_problem = PlacementProblemOverlay::new(placement_problem);

        // Run each placer.
        for (i, stage) in self.stages.iter().enumerate() {
            log::debug!("Run placement stage {}/{}.", i+1, self.stages.len());
            let solution = stage.find_cell_positions_impl(&placement_problem)?;

            // Update partial solution.
            for (inst, pos) in solution {
                placement_problem.initial_positions.insert(inst, pos);
            }
        }

        log::debug!("Done.");

        // Return solution of last stage.
        Ok(placement_problem.initial_positions)
    }


}