libreda_pnr/route/
routing_problem.rs

1// Copyright (c) 2020-2022 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! Representation of routing problems
7
8use libreda_db::prelude as db;
9use std::collections::HashMap;
10
11// pub trait RoutingDesignRules<C: db::L2NBase> {
12//
13//     /// Metal routing layers, starting from the one closest to silicon.
14//     fn routing_layers(&self) -> Vec<C::LayerId>;
15//
16//     /// Via routing layers.
17//     fn via_layers(&self) -> Vec<C::LayerId>;
18//
19// }
20
21/// Representation of the routing problem.
22///
23/// This excludes information directly related to the technology such as design rules.
24pub trait RoutingProblem<C: db::L2NBase> {
25    /// Get the base layout/netlist structure.
26    fn fused_layout_netlist(&self) -> &C;
27
28    /// Get the top cell whose content should be placed.
29    fn top_cell(&self) -> C::CellId;
30
31    /// Return the nets which should be routed.
32    fn nets(&self) -> Box<dyn Iterator<Item=C::NetId> + '_>;
33
34    /// Get the weight of a net. Default is `1.0`.
35    /// When optimizing the wire-length, the *weighted* wire-length should be used.
36    /// For example a weight `0.0` means that the net should not be considered for wire-length optimization.
37    /// Place and route algorithms may or may not use the net weight.
38    fn net_weight(&self, _net: &C::NetId) -> f64 {
39        1.0
40    }
41
42    /// Weight of an 'arc', i.e. a net segment which starts at `signal_source` and ends at `signal_destination.
43    /// Default weight is `1.0`.
44    /// Place and route algorithms may or may not use the arc weight.
45    fn arc_weight(&self, _signal_source: &db::TerminalId<C>, _signal_destination: &db::TerminalId<C>) -> f64 {
46        1.0
47    }
48
49    /// Shapes where routes should not pass.
50    fn blockages(&self) -> Box<dyn Iterator<Item=(C::LayerId, db::SimpleRPolygon<C::Coord>)>> {
51        Box::new(std::iter::empty())
52    }
53
54    /// Routes must remain within this boundary.
55    fn boundary(&self) -> Option<db::SimpleRPolygon<C::Coord>>;
56}
57
58/// Inputs for global routing algorithms.
59pub trait GlobalRoutingProblem<C: db::L2NBase>: RoutingProblem<C> {}
60
61/// Inputs for detail routing algorithms.
62pub trait DetailRoutingProblem<C: db::L2NBase>: RoutingProblem<C> {
63    /// Representation of a global route which guides a single net.
64    type RoutingGuide: RoutingGuide<C>;
65
66    /// Get the routing guide for this net.
67    fn routing_guide(&self, net: &C::NetId) -> Option<&Self::RoutingGuide>;
68}
69
70/// Routing guide for a single net.
71pub trait RoutingGuide<C: db::L2NBase> {
72    /// Test if a point on a layer is included in the routing guide.
73    fn contains_point(&self, layer: &C::LayerId, p: db::Point<C::Coord>) -> bool;
74
75    /// Represent the routing guide as a collection of rectangles.
76    fn to_rectangles(&self) -> Vec<(db::Rect<C::Coord>, C::LayerId)>;
77}
78
79
80/// Simple representation of the global and detail routing problems.
81/// Implements the `RoutingProblem` traits.
82#[derive(Clone)]
83pub struct SimpleRoutingProblem<'a, LN, RoutingGuide = ()>
84    where LN: db::L2NBase {
85    /// A fused layout-netlist structure.
86    pub chip: &'a LN,
87    /// The ID of the top cell to be routed.
88    pub top_cell: LN::CellId,
89    /// The IDs of the nets to be routed.
90    pub nets: Vec<LN::NetId>,
91    /// Weights of nets for optimizing the total wire-length.
92    /// Default weight is `1.0`. A net with weight `0.0` will not be optimized for length
93    /// while a net with a high weight will be optimized for wiring length much more aggressively.
94    pub net_weights: HashMap<LN::NetId, f64>,
95    /// All routes should be contained within this boundary, if it is specified.
96    pub boundary: Option<db::SimpleRPolygon<LN::Coord>>,
97    /// Global routes.
98    pub routing_guides: HashMap<LN::NetId, RoutingGuide>,
99}
100
101impl<'a, LN: db::L2NBase, RG> SimpleRoutingProblem<'a, LN, RG> {
102    /// Create a new routing problem. By default, no nets are included.
103    /// Nets which should be routed need to be added to the `nets` field.
104    pub fn new(chip: &'a LN, top_cell: LN::CellId) -> Self {
105        Self {
106            chip,
107            top_cell,
108            nets: Default::default(),
109            net_weights: Default::default(),
110            boundary: Default::default(),
111            routing_guides: Default::default(),
112        }
113    }
114
115    /// Set global routes.
116    pub fn with_routing_guides(mut self, routing_guides: HashMap<LN::NetId, RG>) -> Self {
117        self.routing_guides = routing_guides;
118        self
119    }
120}
121
122impl<'a, LN, RG> RoutingProblem<LN> for SimpleRoutingProblem<'a, LN, RG>
123    where LN: db::L2NBase {
124    fn fused_layout_netlist(&self) -> &LN {
125        self.chip
126    }
127
128    fn top_cell(&self) -> LN::CellId {
129        self.top_cell.clone()
130    }
131
132    fn nets(&self) -> Box<dyn Iterator<Item=LN::NetId> + '_> {
133        Box::new(self.nets.iter().cloned())
134    }
135
136    fn net_weight(&self, net: &LN::NetId) -> f64 {
137        self.net_weights.get(net)
138            .copied()
139            .unwrap_or(1.0)
140    }
141
142    fn blockages(&self) -> Box<dyn Iterator<Item=(LN::LayerId, db::SimpleRPolygon<LN::Coord>)>> {
143        Box::new(std::iter::empty())
144    }
145
146    fn boundary(&self) -> Option<db::SimpleRPolygon<LN::Coord>> {
147        self.boundary.clone()
148    }
149}
150
151impl<'a, LN: db::L2NBase, RG> GlobalRoutingProblem<LN> for SimpleRoutingProblem<'a, LN, RG> {}
152
153
154impl<'a, LN: db::L2NBase, RG> DetailRoutingProblem<LN> for SimpleRoutingProblem<'a, LN, RG>
155    where RG: RoutingGuide<LN> {
156    type RoutingGuide = RG;
157
158    fn routing_guide(&self, net: &LN::NetId) -> Option<&Self::RoutingGuide> {
159        self.routing_guides.get(net)
160    }
161}