substrate/types/
layout.rs

1//! Traits and types for layout IOs.
2
3use super::{FlatLen, Flatten, Unflatten};
4use crate::error::Result;
5use crate::layout::error::LayoutError;
6use crate::layout::schema::Schema;
7use arcstr::ArcStr;
8use geometry::point::Point;
9use geometry::prelude::{Bbox, Transformation};
10use geometry::rect::Rect;
11use geometry::transform::{TransformRef, TranslateRef};
12use geometry::union::BoundingUnion;
13use layir::Shape;
14use std::collections::HashMap;
15use tracing::Level;
16
17/// A layout port with a generic set of associated geometry.
18#[derive(Clone, Debug, Eq, PartialEq)]
19#[allow(dead_code)]
20pub struct PortGeometry<L> {
21    /// The primary shape of the port.
22    ///
23    /// **Not** contained in `named_shapes` or `unnamed_shapes`.
24    pub primary: Shape<L>,
25    /// A set of unnamed shapes contained by the port.
26    pub unnamed_shapes: Vec<Shape<L>>,
27    /// A set of named shapes contained by the port.
28    pub named_shapes: HashMap<ArcStr, Shape<L>>,
29}
30
31impl<L> PortGeometry<L> {
32    /// Create a new [`PortGeometry`] with the given primary shape.
33    pub fn new(primary: impl Into<Shape<L>>) -> Self {
34        Self {
35            primary: primary.into(),
36            unnamed_shapes: Default::default(),
37            named_shapes: Default::default(),
38        }
39    }
40
41    /// Returns an iterator over all shapes in a [`PortGeometry`].
42    pub fn shapes(&self) -> impl Iterator<Item = &Shape<L>> {
43        std::iter::once(&self.primary)
44            .chain(self.unnamed_shapes.iter())
45            .chain(self.named_shapes.values())
46    }
47
48    /// Merges [`PortGeometry`] `other` into `self`, overwriting the primary and corresponding named shapes
49    /// and moving their old values to the collection of unnamed shapes.
50    #[allow(dead_code)]
51    pub(crate) fn merge(&mut self, other: impl Into<PortGeometry<L>>) {
52        let mut other = other.into();
53        std::mem::swap(&mut self.primary, &mut other.primary);
54        self.unnamed_shapes.push(other.primary);
55        self.unnamed_shapes.extend(other.unnamed_shapes);
56        for (name, shape) in other.named_shapes {
57            if let Some(old_shape) = self.named_shapes.insert(name, shape) {
58                self.unnamed_shapes.push(old_shape);
59            }
60        }
61    }
62}
63
64impl<L> Bbox for PortGeometry<L> {
65    fn bbox(&self) -> Option<Rect> {
66        self.shapes().fold(None, |a, b| a.bounding_union(&b.bbox()))
67    }
68}
69
70impl<L> Unflatten<super::Signal, PortGeometry<L>> for PortGeometry<L> {
71    fn unflatten<I>(_data: &super::Signal, source: &mut I) -> Option<Self>
72    where
73        I: Iterator<Item = PortGeometry<L>>,
74    {
75        source.next()
76    }
77}
78
79impl<L: Send + Sync> super::HasBundleKind for PortGeometry<L> {
80    type BundleKind = super::Signal;
81    fn kind(&self) -> Self::BundleKind {
82        super::Signal
83    }
84}
85
86impl<L: Clone> TryFrom<layir::Port<L>> for PortGeometry<L> {
87    type Error = LayoutError;
88    fn try_from(port: layir::Port<L>) -> std::result::Result<Self, Self::Error> {
89        let mut shapes = port.elements().filter_map(|elt| elt.get_shape().cloned());
90        let primary = shapes.next().ok_or(LayoutError::EmptyPort)?;
91        let unnamed_shapes = shapes.collect();
92        Ok(PortGeometry {
93            primary,
94            unnamed_shapes,
95            named_shapes: Default::default(),
96        })
97    }
98}
99
100/// A type that can be a bundle of layout ports.
101///
102/// Must have an associated bundle kind via [`HasBundleKind`](super::HasBundleKind).
103pub trait LayoutBundle<S: Schema>:
104    super::HasBundleKind
105    + Flatten<PortGeometry<S::Layer>>
106    + Unflatten<Self::BundleKind, PortGeometry<S::Layer>>
107    + TransformRef
108    + Send
109    + Sync
110{
111}
112
113impl<S, T> LayoutBundle<S> for T
114where
115    S: Schema,
116    T: super::HasBundleKind
117        + FlatLen
118        + Flatten<PortGeometry<S::Layer>>
119        + Unflatten<Self::BundleKind, PortGeometry<S::Layer>>
120        + TransformRef
121        + Send
122        + Sync,
123{
124}
125
126/// A set of geometry associated with a layout port.
127#[derive(Clone, Debug)]
128pub struct PortGeometryBuilder<L> {
129    primary: Option<Shape<L>>,
130    unnamed_shapes: Vec<Shape<L>>,
131    named_shapes: HashMap<ArcStr, Shape<L>>,
132}
133
134impl<L> Default for PortGeometryBuilder<L> {
135    fn default() -> Self {
136        Self {
137            primary: None,
138            unnamed_shapes: Vec::new(),
139            named_shapes: HashMap::new(),
140        }
141    }
142}
143
144impl<L: Clone> PortGeometryBuilder<L> {
145    /// Push an unnamed shape to the port.
146    ///
147    /// If the primary shape has not been set yet, sets the primary shape to the new shape
148    /// **instead** of adding to the unnamed shapes list.
149    ///
150    /// The primary shape can be overriden using [`PortGeometryBuilder::set_primary`].
151    pub fn push(&mut self, shape: Shape<L>) {
152        if self.primary.is_none() {
153            self.primary = Some(shape.clone());
154        } else {
155            self.unnamed_shapes.push(shape);
156        }
157    }
158}
159
160impl<L> PortGeometryBuilder<L> {
161    /// Create a new, empty [`PortGeometryBuilder`].
162    #[inline]
163    pub fn new() -> Self {
164        Self::default()
165    }
166
167    /// Builds a port geometry.
168    pub fn build(self) -> Result<PortGeometry<L>> {
169        Ok(PortGeometry {
170            primary: self.primary.ok_or_else(|| {
171                tracing::event!(
172                    Level::ERROR,
173                    "primary shape in port geometry was not specified"
174                );
175                LayoutError::IoDefinition
176            })?,
177            unnamed_shapes: self.unnamed_shapes,
178            named_shapes: self.named_shapes,
179        })
180    }
181
182    /// Merges [`PortGeometry`] `other` into `self`, overwriting the primary and corresponding named shapes
183    /// and moving their old values to the collection of unnamed shapes.
184    pub fn merge(&mut self, other: impl Into<PortGeometry<L>>) {
185        let other = other.into();
186        if let Some(old_primary) = self.primary.take() {
187            self.unnamed_shapes.push(old_primary);
188        }
189        self.primary = Some(other.primary);
190        self.unnamed_shapes.extend(other.unnamed_shapes);
191        for (name, shape) in other.named_shapes {
192            if let Some(old_shape) = self.named_shapes.insert(name, shape) {
193                self.unnamed_shapes.push(old_shape);
194            }
195        }
196    }
197
198    /// Sets the primary shape of this port, moving the current primary
199    /// to the set of unnamed shapes.
200    pub fn set_primary(&mut self, shape: Shape<L>) {
201        let old_primary = self.primary.take();
202        self.primary = Some(shape);
203        if let Some(old_primary) = old_primary {
204            self.unnamed_shapes.push(old_primary);
205        }
206    }
207}
208
209/// A simple builder that allows setting data at runtime.
210///
211/// ```
212/// # use substrate::types::layout::OptionBuilder;
213/// let mut builder = OptionBuilder::default();
214/// builder.set(5);
215/// assert_eq!(builder.build().unwrap(), 5);
216#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
217pub struct OptionBuilder<T>(Option<T>);
218
219impl<T> Default for OptionBuilder<T> {
220    fn default() -> Self {
221        Self(None)
222    }
223}
224
225impl<T> OptionBuilder<T> {
226    /// Constructs a new, empty `OptionBuilder`.
227    #[inline]
228    pub fn new() -> Self {
229        Self::default()
230    }
231
232    /// Set the value of the data contained by the builder.
233    pub fn set(&mut self, inner: T) {
234        let _ = self.0.insert(inner);
235    }
236
237    /// Returns the data contained by the builder.
238    pub fn build(self) -> Result<T> {
239        Ok(self.0.ok_or(LayoutError::IoDefinition)?)
240    }
241}
242impl<L> FlatLen for Shape<L> {
243    fn len(&self) -> usize {
244        1
245    }
246}
247
248impl<L: Clone> Flatten<PortGeometry<L>> for Shape<L> {
249    fn flatten<E>(&self, output: &mut E)
250    where
251        E: Extend<PortGeometry<L>>,
252    {
253        output.extend(std::iter::once(PortGeometry {
254            primary: self.clone(),
255            unnamed_shapes: Vec::new(),
256            named_shapes: HashMap::new(),
257        }));
258    }
259}
260
261impl<L> FlatLen for PortGeometry<L> {
262    fn len(&self) -> usize {
263        1
264    }
265}
266
267impl<L: Clone> Flatten<PortGeometry<L>> for PortGeometry<L> {
268    fn flatten<E>(&self, output: &mut E)
269    where
270        E: Extend<PortGeometry<L>>,
271    {
272        output.extend(std::iter::once(self.clone()));
273    }
274}
275
276impl<L: Clone> TranslateRef for PortGeometry<L> {
277    fn translate_ref(&self, p: Point) -> Self {
278        Self {
279            primary: self.primary.translate_ref(p),
280            unnamed_shapes: self.unnamed_shapes.translate_ref(p),
281            named_shapes: self
282                .named_shapes
283                .iter()
284                .map(|(k, v)| (k.clone(), v.translate_ref(p)))
285                .collect(),
286        }
287    }
288}
289
290impl<L: Clone> TransformRef for PortGeometry<L> {
291    fn transform_ref(&self, trans: Transformation) -> Self {
292        Self {
293            primary: self.primary.transform_ref(trans),
294            unnamed_shapes: self.unnamed_shapes.transform_ref(trans),
295            named_shapes: self
296                .named_shapes
297                .iter()
298                .map(|(k, v)| (k.clone(), v.transform_ref(trans)))
299                .collect(),
300        }
301    }
302}
303
304impl<L> FlatLen for PortGeometryBuilder<L> {
305    fn len(&self) -> usize {
306        1
307    }
308}
309
310impl<L> Flatten<PortGeometry<L>> for () {
311    fn flatten<E>(&self, _output: &mut E)
312    where
313        E: Extend<PortGeometry<L>>,
314    {
315    }
316}