ASIC place & route framework. This crate contains interface definitions of the core parts of the place & route flow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
3.2 KiB

/*
* Copyright (c) 2020-2021 Thomas Kramer.
*
* This file is part of LibrEDA
* (see https://codeberg.org/libreda).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! 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 set_cell_dimensions(&mut self, cell_dimensions: HashMap<N::CellId, db::Rect<db::Coord>>) {
for placer in self.stages.iter_mut() {
placer.as_mut().set_cell_dimensions(cell_dimensions.clone());
}
}
fn find_cell_positions_impl(&self,
netlist: &N,
circuit_id: &N::CellId,
core_area: &SimplePolygon<i32>,
initial_positions: &HashMap<N::CellInstId, Point<i32>>,
fixed_instances: &HashSet<N::CellInstId>,
) -> 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,
);
// 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
}
}