substrate/types/
layout.rsuse super::{FlatLen, Flatten, Unflatten};
use crate::error::Result;
use crate::layout::error::LayoutError;
use crate::layout::schema::Schema;
use arcstr::ArcStr;
use geometry::point::Point;
use geometry::prelude::{Bbox, Transformation};
use geometry::rect::Rect;
use geometry::transform::{TransformRef, TranslateRef};
use geometry::union::BoundingUnion;
use layir::Shape;
use std::collections::HashMap;
use tracing::Level;
#[derive(Clone, Debug, Eq, PartialEq)]
#[allow(dead_code)]
pub struct PortGeometry<L> {
pub primary: Shape<L>,
pub unnamed_shapes: Vec<Shape<L>>,
pub named_shapes: HashMap<ArcStr, Shape<L>>,
}
impl<L> PortGeometry<L> {
pub fn new(primary: impl Into<Shape<L>>) -> Self {
Self {
primary: primary.into(),
unnamed_shapes: Default::default(),
named_shapes: Default::default(),
}
}
pub fn shapes(&self) -> impl Iterator<Item = &Shape<L>> {
std::iter::once(&self.primary)
.chain(self.unnamed_shapes.iter())
.chain(self.named_shapes.values())
}
#[allow(dead_code)]
pub(crate) fn merge(&mut self, other: impl Into<PortGeometry<L>>) {
let mut other = other.into();
std::mem::swap(&mut self.primary, &mut other.primary);
self.unnamed_shapes.push(other.primary);
self.unnamed_shapes.extend(other.unnamed_shapes);
for (name, shape) in other.named_shapes {
if let Some(old_shape) = self.named_shapes.insert(name, shape) {
self.unnamed_shapes.push(old_shape);
}
}
}
}
impl<L> Bbox for PortGeometry<L> {
fn bbox(&self) -> Option<Rect> {
self.shapes().fold(None, |a, b| a.bounding_union(&b.bbox()))
}
}
impl<L> Unflatten<super::Signal, PortGeometry<L>> for PortGeometry<L> {
fn unflatten<I>(_data: &super::Signal, source: &mut I) -> Option<Self>
where
I: Iterator<Item = PortGeometry<L>>,
{
source.next()
}
}
impl<L: Send + Sync> super::HasBundleKind for PortGeometry<L> {
type BundleKind = super::Signal;
fn kind(&self) -> Self::BundleKind {
super::Signal
}
}
pub trait LayoutBundle<S: Schema>:
super::HasBundleKind
+ Flatten<PortGeometry<S::Layer>>
+ Unflatten<Self::BundleKind, PortGeometry<S::Layer>>
+ TransformRef
+ Send
+ Sync
{
}
impl<S, T> LayoutBundle<S> for T
where
S: Schema,
T: super::HasBundleKind
+ FlatLen
+ Flatten<PortGeometry<S::Layer>>
+ Unflatten<Self::BundleKind, PortGeometry<S::Layer>>
+ TransformRef
+ Send
+ Sync,
{
}
#[derive(Clone, Debug)]
pub struct PortGeometryBuilder<L> {
primary: Option<Shape<L>>,
unnamed_shapes: Vec<Shape<L>>,
named_shapes: HashMap<ArcStr, Shape<L>>,
}
impl<L> Default for PortGeometryBuilder<L> {
fn default() -> Self {
Self {
primary: None,
unnamed_shapes: Vec::new(),
named_shapes: HashMap::new(),
}
}
}
impl<L: Clone> PortGeometryBuilder<L> {
pub fn push(&mut self, shape: Shape<L>) {
if self.primary.is_none() {
self.primary = Some(shape.clone());
} else {
self.unnamed_shapes.push(shape);
}
}
}
impl<L> PortGeometryBuilder<L> {
#[inline]
pub fn new() -> Self {
Self::default()
}
pub fn build(self) -> Result<PortGeometry<L>> {
Ok(PortGeometry {
primary: self.primary.ok_or_else(|| {
tracing::event!(
Level::ERROR,
"primary shape in port geometry was not specified"
);
LayoutError::IoDefinition
})?,
unnamed_shapes: self.unnamed_shapes,
named_shapes: self.named_shapes,
})
}
pub fn merge(&mut self, other: impl Into<PortGeometry<L>>) {
let other = other.into();
if let Some(old_primary) = self.primary.take() {
self.unnamed_shapes.push(old_primary);
}
self.primary = Some(other.primary);
self.unnamed_shapes.extend(other.unnamed_shapes);
for (name, shape) in other.named_shapes {
if let Some(old_shape) = self.named_shapes.insert(name, shape) {
self.unnamed_shapes.push(old_shape);
}
}
}
pub fn set_primary(&mut self, shape: Shape<L>) {
let old_primary = self.primary.take();
self.primary = Some(shape);
if let Some(old_primary) = old_primary {
self.unnamed_shapes.push(old_primary);
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct OptionBuilder<T>(Option<T>);
impl<T> Default for OptionBuilder<T> {
fn default() -> Self {
Self(None)
}
}
impl<T> OptionBuilder<T> {
#[inline]
pub fn new() -> Self {
Self::default()
}
pub fn set(&mut self, inner: T) {
let _ = self.0.insert(inner);
}
pub fn build(self) -> Result<T> {
Ok(self.0.ok_or(LayoutError::IoDefinition)?)
}
}
impl<L> FlatLen for Shape<L> {
fn len(&self) -> usize {
1
}
}
impl<L: Clone> Flatten<PortGeometry<L>> for Shape<L> {
fn flatten<E>(&self, output: &mut E)
where
E: Extend<PortGeometry<L>>,
{
output.extend(std::iter::once(PortGeometry {
primary: self.clone(),
unnamed_shapes: Vec::new(),
named_shapes: HashMap::new(),
}));
}
}
impl<L> FlatLen for PortGeometry<L> {
fn len(&self) -> usize {
1
}
}
impl<L: Clone> Flatten<PortGeometry<L>> for PortGeometry<L> {
fn flatten<E>(&self, output: &mut E)
where
E: Extend<PortGeometry<L>>,
{
output.extend(std::iter::once(self.clone()));
}
}
impl<L: Clone> TranslateRef for PortGeometry<L> {
fn translate_ref(&self, p: Point) -> Self {
Self {
primary: self.primary.translate_ref(p),
unnamed_shapes: self.unnamed_shapes.translate_ref(p),
named_shapes: self
.named_shapes
.iter()
.map(|(k, v)| (k.clone(), v.translate_ref(p)))
.collect(),
}
}
}
impl<L: Clone> TransformRef for PortGeometry<L> {
fn transform_ref(&self, trans: Transformation) -> Self {
Self {
primary: self.primary.transform_ref(trans),
unnamed_shapes: self.unnamed_shapes.transform_ref(trans),
named_shapes: self
.named_shapes
.iter()
.map(|(k, v)| (k.clone(), v.transform_ref(trans)))
.collect(),
}
}
}
impl<L> FlatLen for PortGeometryBuilder<L> {
fn len(&self) -> usize {
1
}
}
impl<L> Flatten<PortGeometry<L>> for () {
fn flatten<E>(&self, _output: &mut E)
where
E: Extend<PortGeometry<L>>,
{
}
}