use libreda_db::prelude as db;
use std::collections::{HashMap, HashSet};
use log::{debug, info, warn};
use db::{L2NEdit, NetlistBase};
pub fn legalize<L, LN>(legalizer: &L,
chip: &mut LN,
top_cell: &LN::CellId,
core_area: &db::SimplePolygon<LN::Coord>,
cell_outlines: &HashMap<LN::CellId, db::Rect<LN::Coord>>,
movable_instances: &HashSet<LN::CellInstId>)
where L: SimpleStdCellLegalizer<LN>,
LN: L2NEdit<Coord=db::Coord>,
{
let initial_positions = chip.each_cell_instance(top_cell)
.map(|inst| {
let tf = chip.get_transform(&inst);
let point = tf.transform_point(db::Point::zero());
(inst, point)
})
.collect();
let legal_positions = legalizer.find_legal_positions(
chip,
top_cell,
core_area,
cell_outlines,
&initial_positions,
movable_instances,
);
let mut fixed_instance_moves = 0; for (inst, tf) in legal_positions {
if movable_instances.contains(&inst) {
chip.set_transform(&inst, tf);
} else {
fixed_instance_moves += 1;
}
}
if fixed_instance_moves > 0 {
log::warn!("Legalizer tried to move fixed instances: {}", fixed_instance_moves);
}
}
pub trait SimpleStdCellLegalizer<N: NetlistBase> {
fn find_legal_positions_impl(&self,
netlist: &N,
circuit: &N::CellId,
core_area: &db::SimplePolygon<db::SInt>,
cell_outlines: &HashMap<N::CellId, db::Rect<db::SInt>>,
global_positions: &HashMap<N::CellInstId, db::Point<db::SInt>>,
movable_instances: &HashSet<N::CellInstId>,
) -> HashMap<N::CellInstId, db::SimpleTransform<db::SInt>>;
fn find_legal_positions(&self,
netlist: &N,
circuit: &N::CellId,
core_area: &db::SimplePolygon<db::SInt>,
cell_outlines: &HashMap<N::CellId, db::Rect<db::SInt>>,
global_positions: &HashMap<N::CellInstId, db::Point<db::SInt>>,
movable_instances: &HashSet<N::CellInstId>,
) -> HashMap<N::CellInstId, db::SimpleTransform<db::SInt>> {
info!("Run legalization of the standard-cells.");
debug!("Check that all circuit instances have a global position.");
let without_position: Vec<_> = netlist.each_cell_instance(circuit)
.filter(|c| !global_positions.contains_key(c))
.collect();
if without_position.len() > 0 {
warn!("{} circuit instances have no global position.", without_position.len());
debug!("Circuit instances without global position: {:?}",
without_position.iter()
.map(|c| netlist.cell_instance_name(c)
.map(|n| n.into())
.unwrap_or(format!("ID={:?}", c))
).collect::<Vec<_>>()
)
}
let mut unknown_shapes: Vec<_> = netlist.each_cell_dependency(circuit)
.filter(|c| !cell_outlines.contains_key(c))
.map(|c| netlist.cell_name(&c))
.collect();
unknown_shapes.sort();
let unknown_shapes = unknown_shapes;
if !unknown_shapes.is_empty() {
warn!("Number of cells without known shape: {}", unknown_shapes.len());
warn!("Cells without known shape: {}", unknown_shapes.join(", "))
}
debug!("Call legalize_impl().");
let result = self.find_legal_positions_impl(
netlist,
circuit,
core_area,
cell_outlines,
global_positions,
movable_instances);
info!("Legalization finished.");
result
}
}