libreda-pnr 0.0.4

Algorithm interface definitions of the LibrEDA place-and-route framework.
Documentation
// 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)
    }


}