libreda_pnr/
design.rs

1// Copyright (c) 2020-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! A `Design` structure collects information necessary for the place and route steps.
7//! This includes the netlist and layout, properties of cell instances, etc.
8//! Between `Design` structures and place & route engines lies an abstraction layer
9//! made by traits such as [`PlacementProblem`].
10//!
11//! [`SimpleDesign`] is an example of how place & route information can be encapsulated.
12
13use libreda_db::prelude as db;
14
15use std::collections::HashMap;
16
17use super::place::placement_problem::{PlacementProblem, PlacementStatus};
18use super::route::routing_problem::{RoutingProblem, GlobalRoutingProblem};
19use db::{SimpleRPolygon, Rect, SimpleTransform};
20
21/// Collection of data representing the chip during the place & route flow.
22/// This struct owns the data. In contrast, [`SimpleDesignRef`] does only borrow
23/// the data.
24pub struct SimpleDesign<C: db::L2NBase> {
25    /// Base layout and netlist data-structure.
26    pub fused_layout_netlist: C,
27    /// Cell which contains the instances to be placed.
28    pub top_cell: C::CellId,
29    /// Outline shapes of the cells to be placed.
30    pub cell_outlines: HashMap<C::CellId, db::Rect<C::Coord>>,
31    /// Regions where cells are allowed to be placed.
32    pub placement_region: Vec<SimpleRPolygon<C::Coord>>,
33    /// Placement status of the cell instances. Default is `Movable`.
34    pub placement_status: HashMap<C::CellInstId, PlacementStatus>
35}
36
37impl<C: db::L2NBase> SimpleDesign<C> {
38    /// Set the placement status of a cell instance.
39    pub fn set_placement_status(&mut self, cell_inst: C::CellInstId, placement_status: PlacementStatus) {
40        self.placement_status.insert(cell_inst, placement_status);
41    }
42}
43
44
45impl<C: db::L2NBase> PlacementProblem<C> for SimpleDesign<C> {
46    fn fused_layout_netlist(&self) -> &C {
47        &self.fused_layout_netlist
48    }
49
50    fn top_cell(&self) -> C::CellId {
51        self.top_cell.clone()
52    }
53
54    fn placement_region(&self) -> Vec<SimpleRPolygon<C::Coord>> {
55        self.placement_region.clone()
56    }
57
58    fn initial_position(&self, cell_instance: &C::CellInstId) -> SimpleTransform<C::Coord> {
59        self.fused_layout_netlist.get_transform(cell_instance)
60    }
61
62    fn placement_status(&self, cell_instance: &C::CellInstId) -> PlacementStatus {
63        self.placement_status.get(cell_instance)
64            .copied()
65            .unwrap_or(PlacementStatus::Ignore)
66    }
67
68    fn cell_outline(&self, cell: &C::CellId) -> Option<Rect<C::Coord>> {
69        self.cell_outlines.get(cell).copied()
70    }
71}
72
73/// Collection of data representing the chip during the place & route flow.
74/// This struct borrows the data. In contrast, [`SimpleDesign`] owns
75/// the data.
76pub struct SimpleDesignRef<'a, C: db::L2NBase> {
77    /// Base layout and netlist data-structure.
78    pub fused_layout_netlist: &'a C,
79    /// Cell which contains the instances to be placed.
80    pub top_cell: C::CellId,
81    /// Outline shapes of the cells to be placed.
82    pub cell_outlines: &'a HashMap<C::CellId, db::Rect<C::Coord>>,
83    /// Regions where cells are allowed to be placed.
84    pub placement_region: &'a Vec<SimpleRPolygon<C::Coord>>,
85    /// Placement status of the cell instances. Default is `Movable`.
86    pub placement_status: &'a HashMap<C::CellInstId, PlacementStatus>,
87    /// Net weights. Default for nets which are not in the hash map is `1.0`.
88    pub net_weights: &'a HashMap<C::NetId, f64>,
89    /// Overwrite the location information from the `fused_layout_netlist`.
90    pub placement_location: &'a HashMap<C::CellInstId, db::SimpleTransform<C::Coord>>
91}
92
93
94impl<'a, C: db::L2NBase> PlacementProblem<C> for SimpleDesignRef<'a, C> {
95    fn fused_layout_netlist(&self) -> &C {
96        self.fused_layout_netlist
97    }
98
99    fn top_cell(&self) -> C::CellId {
100        self.top_cell.clone()
101    }
102
103    fn placement_region(&self) -> Vec<SimpleRPolygon<C::Coord>> {
104        self.placement_region.to_vec()
105    }
106
107    fn initial_position(&self, cell_instance: &C::CellInstId) -> SimpleTransform<C::Coord> {
108        self.placement_location.get(cell_instance)
109            .cloned()
110            .unwrap_or_else(|| self.fused_layout_netlist.get_transform(cell_instance))
111    }
112
113    fn placement_status(&self, cell_instance: &C::CellInstId) -> PlacementStatus {
114        self.placement_status.get(cell_instance)
115            .copied()
116            .unwrap_or(PlacementStatus::Ignore)
117    }
118
119    fn cell_outline(&self, cell: &C::CellId) -> Option<Rect<C::Coord>> {
120        self.cell_outlines.get(cell).copied()
121    }
122
123    fn net_weight(&self, net_id: &C::NetId) -> f64 {
124        self.net_weights.get(net_id).copied().unwrap_or(1.0)
125    }
126}
127
128
129impl<'a, C: db::L2NBase> RoutingProblem<C> for SimpleDesignRef<'a, C> {
130    fn fused_layout_netlist(&self) -> &C {
131        self.fused_layout_netlist
132    }
133
134    fn top_cell(&self) -> C::CellId {
135        self.top_cell.clone()
136    }
137
138    fn nets(&self) -> Box<dyn Iterator<Item=C::NetId> + '_> {
139        Box::new(self.fused_layout_netlist.each_internal_net(&self.top_cell))
140    }
141
142    fn net_weight(&self, net: &C::NetId) -> f64 {
143        self.net_weights.get(net).copied().unwrap_or(1.0)
144    }
145
146    fn blockages(&self) -> Box<dyn Iterator<Item=(C::LayerId, db::SimpleRPolygon<C::Coord>)>> {
147        Box::new(std::iter::empty())
148    }
149
150
151    fn boundary(&self) -> Option<db::SimpleRPolygon<C::Coord>> {
152        unimplemented!("boundary")
153    }
154}
155
156impl<'a, C: db::L2NBase> GlobalRoutingProblem<C> for SimpleDesignRef<'a, C> {
157
158}