use libreda_db::prelude as db;
use std::collections::HashMap;
use super::place::placement_problem::{PlacementProblem, PlacementStatus};
use super::route::routing_problem::{GlobalRoutingProblem, RoutingProblem};
use db::{Rect, SimpleRPolygon, SimpleTransform};
pub struct SimpleDesign<C: db::L2NBase> {
pub fused_layout_netlist: C,
pub top_cell: C::CellId,
pub cell_outlines: HashMap<C::CellId, db::Rect<C::Coord>>,
pub placement_region: Vec<SimpleRPolygon<C::Coord>>,
pub placement_status: HashMap<C::CellInstId, PlacementStatus>,
}
impl<C: db::L2NBase> SimpleDesign<C> {
pub fn set_placement_status(
&mut self,
cell_inst: C::CellInstId,
placement_status: PlacementStatus,
) {
self.placement_status.insert(cell_inst, placement_status);
}
}
impl<C: db::L2NBase> PlacementProblem<C> for SimpleDesign<C> {
fn fused_layout_netlist(&self) -> &C {
&self.fused_layout_netlist
}
fn top_cell(&self) -> C::CellId {
self.top_cell.clone()
}
fn placement_region(&self) -> Vec<SimpleRPolygon<C::Coord>> {
self.placement_region.clone()
}
fn initial_position(&self, cell_instance: &C::CellInstId) -> SimpleTransform<C::Coord> {
self.fused_layout_netlist.get_transform(cell_instance)
}
fn placement_status(&self, cell_instance: &C::CellInstId) -> PlacementStatus {
self.placement_status
.get(cell_instance)
.copied()
.unwrap_or(PlacementStatus::Ignore)
}
fn cell_outline(&self, cell: &C::CellId) -> Option<Rect<C::Coord>> {
self.cell_outlines.get(cell).copied()
}
}
pub struct SimpleDesignRef<'a, C: db::L2NBase> {
pub fused_layout_netlist: &'a C,
pub top_cell: C::CellId,
pub cell_outlines: &'a HashMap<C::CellId, db::Rect<C::Coord>>,
pub placement_region: &'a Vec<SimpleRPolygon<C::Coord>>,
pub placement_status: &'a HashMap<C::CellInstId, PlacementStatus>,
pub net_weights: &'a HashMap<C::NetId, f64>,
pub placement_location: &'a HashMap<C::CellInstId, db::SimpleTransform<C::Coord>>,
}
impl<'a, C: db::L2NBase> PlacementProblem<C> for SimpleDesignRef<'a, C> {
fn fused_layout_netlist(&self) -> &C {
self.fused_layout_netlist
}
fn top_cell(&self) -> C::CellId {
self.top_cell.clone()
}
fn placement_region(&self) -> Vec<SimpleRPolygon<C::Coord>> {
self.placement_region.to_vec()
}
fn initial_position(&self, cell_instance: &C::CellInstId) -> SimpleTransform<C::Coord> {
self.placement_location
.get(cell_instance)
.cloned()
.unwrap_or_else(|| self.fused_layout_netlist.get_transform(cell_instance))
}
fn placement_status(&self, cell_instance: &C::CellInstId) -> PlacementStatus {
self.placement_status
.get(cell_instance)
.copied()
.unwrap_or(PlacementStatus::Ignore)
}
fn cell_outline(&self, cell: &C::CellId) -> Option<Rect<C::Coord>> {
self.cell_outlines.get(cell).copied()
}
fn net_weight(&self, net_id: &C::NetId) -> f64 {
self.net_weights.get(net_id).copied().unwrap_or(1.0)
}
}
impl<'a, C: db::L2NBase> RoutingProblem<C> for SimpleDesignRef<'a, C> {
fn fused_layout_netlist(&self) -> &C {
self.fused_layout_netlist
}
fn top_cell(&self) -> C::CellId {
self.top_cell.clone()
}
fn nets(&self) -> Box<dyn Iterator<Item = C::NetId> + '_> {
Box::new(self.fused_layout_netlist.each_internal_net(&self.top_cell))
}
fn net_weight(&self, net: &C::NetId) -> f64 {
self.net_weights.get(net).copied().unwrap_or(1.0)
}
fn blockages(&self) -> Box<dyn Iterator<Item = (C::LayerId, db::SimpleRPolygon<C::Coord>)>> {
Box::new(std::iter::empty())
}
fn boundary(&self) -> Option<db::SimpleRPolygon<C::Coord>> {
unimplemented!("boundary")
}
}
impl<'a, C: db::L2NBase> GlobalRoutingProblem<C> for SimpleDesignRef<'a, C> {}