substrate/types/
layout.rs1use 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#[derive(Clone, Debug, Eq, PartialEq)]
19#[allow(dead_code)]
20pub struct PortGeometry<L> {
21 pub primary: Shape<L>,
25 pub unnamed_shapes: Vec<Shape<L>>,
27 pub named_shapes: HashMap<ArcStr, Shape<L>>,
29}
30
31impl<L> PortGeometry<L> {
32 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 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 #[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
100pub 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#[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 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 #[inline]
163 pub fn new() -> Self {
164 Self::default()
165 }
166
167 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 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 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#[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 #[inline]
228 pub fn new() -> Self {
229 Self::default()
230 }
231
232 pub fn set(&mut self, inner: T) {
234 let _ = self.0.insert(inner);
235 }
236
237 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}