use libreda_db::prelude as db;
use std::collections::HashMap;
pub trait RoutingProblem<C: db::L2NBase> {
fn fused_layout_netlist(&self) -> &C;
fn top_cell(&self) -> C::CellId;
fn nets(&self) -> Box<dyn Iterator<Item=C::NetId> + '_>;
fn net_weight(&self, _net: &C::NetId) -> f64 {
1.0
}
fn arc_weight(&self, _signal_source: &db::TerminalId<C>, _signal_destination: &db::TerminalId<C>) -> f64 {
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>>;
}
pub trait GlobalRoutingProblem<C: db::L2NBase>: RoutingProblem<C> {}
pub trait DetailRoutingProblem<C: db::L2NBase>: RoutingProblem<C> {
type RoutingGuide: RoutingGuide<C>;
fn routing_guide(&self, net: &C::NetId) -> Option<&Self::RoutingGuide>;
}
pub trait RoutingGuide<C: db::L2NBase> {
fn contains_point(&self, layer: &C::LayerId, p: db::Point<C::Coord>) -> bool;
fn to_rectangles(&self) -> Vec<(db::Rect<C::Coord>, C::LayerId)>;
}
#[derive(Clone)]
pub struct SimpleRoutingProblem<'a, LN, RoutingGuide = ()>
where LN: db::L2NBase {
pub chip: &'a LN,
pub top_cell: LN::CellId,
pub nets: Vec<LN::NetId>,
pub net_weights: HashMap<LN::NetId, f64>,
pub boundary: Option<db::SimpleRPolygon<LN::Coord>>,
pub routing_guides: HashMap<LN::NetId, RoutingGuide>,
}
impl<'a, LN: db::L2NBase, RG> SimpleRoutingProblem<'a, LN, RG> {
pub fn new(chip: &'a LN, top_cell: LN::CellId) -> Self {
Self {
chip,
top_cell,
nets: Default::default(),
net_weights: Default::default(),
boundary: Default::default(),
routing_guides: Default::default(),
}
}
pub fn with_routing_guides(mut self, routing_guides: HashMap<LN::NetId, RG>) -> Self {
self.routing_guides = routing_guides;
self
}
}
impl<'a, LN, RG> RoutingProblem<LN> for SimpleRoutingProblem<'a, LN, RG>
where LN: db::L2NBase {
fn fused_layout_netlist(&self) -> &LN {
self.chip
}
fn top_cell(&self) -> LN::CellId {
self.top_cell.clone()
}
fn nets(&self) -> Box<dyn Iterator<Item=LN::NetId> + '_> {
Box::new(self.nets.iter().cloned())
}
fn net_weight(&self, net: &LN::NetId) -> f64 {
self.net_weights.get(net)
.copied()
.unwrap_or(1.0)
}
fn blockages(&self) -> Box<dyn Iterator<Item=(LN::LayerId, db::SimpleRPolygon<LN::Coord>)>> {
Box::new(std::iter::empty())
}
fn boundary(&self) -> Option<db::SimpleRPolygon<LN::Coord>> {
self.boundary.clone()
}
}
impl<'a, LN: db::L2NBase, RG> GlobalRoutingProblem<LN> for SimpleRoutingProblem<'a, LN, RG> {}
impl<'a, LN: db::L2NBase, RG> DetailRoutingProblem<LN> for SimpleRoutingProblem<'a, LN, RG>
where RG: RoutingGuide<LN> {
type RoutingGuide = RG;
fn routing_guide(&self, net: &LN::NetId) -> Option<&Self::RoutingGuide> {
self.routing_guides.get(net)
}
}