Skip to content

Commit

Permalink
feat(bbox): implement LayerBbox trait
Browse files Browse the repository at this point in the history
The LayerBbox trait allows users to find bounding boxes
considering only the geometry on a specific LayerId.
  • Loading branch information
rahulk29 committed Dec 31, 2023
1 parent f25b0dd commit 78ab8c4
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 1 deletion.
2 changes: 1 addition & 1 deletion libs/geometry/src/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl Shape {
}
}

/// If this shape is a rectangle, returns the contained polygon.
/// If this shape is a polygon, returns the contained polygon.
/// Otherwise, returns [`None`].
pub fn polygon(&self) -> Option<&Polygon> {
match self {
Expand Down
11 changes: 11 additions & 0 deletions substrate/src/io/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use geometry::transform;
use geometry::transform::HasTransformedView;
use geometry::union::BoundingUnion;
use std::collections::HashMap;
use substrate::layout::bbox::LayerBbox;
use tracing::Level;

/// A layout hardware type.
Expand Down Expand Up @@ -129,6 +130,16 @@ impl Bbox for IoShape {
}
}

impl LayerBbox for IoShape {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
if self.layer.pin == layer || self.layer.drawing == layer {
self.shape.bbox()
} else {
None
}
}
}

impl IoShape {
/// Creates a new [`IoShape`] from a full specification of the layers on which it should be
/// drawn.
Expand Down
27 changes: 27 additions & 0 deletions substrate/src/layout/bbox.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//! Bounding box utilities.
use crate::pdk::layers::LayerId;
use geometry::prelude::*;
use geometry::union::BoundingUnion;

/// A trait representing functions available for multi-layered objects with bounding boxes.
pub trait LayerBbox: Bbox {
/// Compute the bounding box considering only objects occupying the given layer.
fn layer_bbox(&self, layer: LayerId) -> Option<Rect>;
}

impl<T: LayerBbox> LayerBbox for Vec<T> {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
let mut bbox = None;
for item in self {
bbox = bbox.bounding_union(&item.layer_bbox(layer));
}
bbox
}
}

impl<T: LayerBbox> LayerBbox for &T {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
(*self).layer_bbox(layer)
}
}
45 changes: 45 additions & 0 deletions substrate/src/layout/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use indexmap::IndexMap;
use serde::{Deserialize, Serialize};

use crate::io::layout::PortGeometry;
use crate::layout::bbox::LayerBbox;
use crate::{
error::{Error, Result},
io::NameBuf,
Expand Down Expand Up @@ -133,6 +134,12 @@ impl Bbox for RawCell {
}
}

impl LayerBbox for RawCell {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
self.elements.layer_bbox(layer)
}
}

impl HasTransformedView for RawCell {
type TransformedView = RawCell;

Expand Down Expand Up @@ -198,6 +205,14 @@ impl Bbox for RawInstance {
}
}

impl LayerBbox for RawInstance {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
self.cell
.layer_bbox(layer)
.map(|rect| rect.transform(self.trans))
}
}

impl<T: ExportsLayoutData> TryFrom<Instance<T>> for RawInstance {
type Error = Error;

Expand Down Expand Up @@ -270,6 +285,16 @@ impl Bbox for Shape {
}
}

impl LayerBbox for Shape {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
if self.layer == layer {
self.bbox()
} else {
None
}
}
}

impl<T: Bbox> BoundingUnion<T> for Shape {
type Output = Rect;

Expand Down Expand Up @@ -467,6 +492,16 @@ impl Bbox for Element {
}
}

impl LayerBbox for Element {
fn layer_bbox(&self, layer: LayerId) -> Option<geometry::rect::Rect> {
match self {
Element::Instance(inst) => inst.layer_bbox(layer),
Element::Shape(shape) => shape.layer_bbox(layer),
Element::Text(_) => None,
}
}
}

impl From<RawInstance> for Element {
fn from(value: RawInstance) -> Self {
Self::Instance(value)
Expand Down Expand Up @@ -530,6 +565,16 @@ impl Bbox for ElementRef<'_> {
}
}

impl LayerBbox for ElementRef<'_> {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
match self {
ElementRef::Instance(inst) => inst.layer_bbox(layer),
ElementRef::Shape(shape) => shape.layer_bbox(layer),
ElementRef::Text(_) => None,
}
}
}

impl<'a> From<&'a RawInstance> for ElementRef<'a> {
fn from(value: &'a RawInstance) -> Self {
Self::Instance(value)
Expand Down
42 changes: 42 additions & 0 deletions substrate/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use arcstr::ArcStr;
use cache::{error::TryInnerError, mem::TypeCache, CacheHandle};
pub use codegen::{Layout, LayoutData};
use examples::get_snippets;
use geometry::prelude::Rect;
use geometry::{
prelude::{Bbox, Point},
transform::{
Expand All @@ -24,12 +25,15 @@ use geometry::{
use once_cell::sync::OnceCell;

use crate::io::layout::{Builder, HardwareType};
use crate::layout::bbox::LayerBbox;
use crate::pdk::layers::LayerId;
use crate::pdk::Pdk;
use crate::{block::Block, error::Error};
use crate::{context::PdkContext, error::Result};

use self::element::{CellId, Element, RawCell, RawInstance, Shape};

pub mod bbox;
pub mod element;
pub mod error;
pub mod gds;
Expand Down Expand Up @@ -160,6 +164,12 @@ impl<T: ExportsLayoutData> Bbox for Cell<T> {
}
}

impl<T: ExportsLayoutData> LayerBbox for Cell<T> {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
self.raw.layer_bbox(layer)
}
}

/// A handle to a schematic cell that is being generated.
pub struct CellHandle<T: ExportsLayoutData> {
pub(crate) block: Arc<T>,
Expand Down Expand Up @@ -242,6 +252,12 @@ impl<T: ExportsLayoutData> Bbox for TransformedCell<T> {
}
}

impl<T: ExportsLayoutData> LayerBbox for TransformedCell<T> {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
self.raw.layer_bbox(layer).transform(self.trans)
}
}

/// A generic layout instance.
///
/// Stores a pointer to its underlying cell and its instantiated transformation.
Expand Down Expand Up @@ -378,6 +394,12 @@ impl<T: ExportsLayoutData> Bbox for Instance<T> {
}
}

impl<T: ExportsLayoutData> LayerBbox for Instance<T> {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
self.cell().layer_bbox(layer)
}
}

impl<T: ExportsLayoutData> TranslateMut for Instance<T> {
fn translate_mut(&mut self, p: Point) {
self.transform_mut(Transformation::from_offset(p))
Expand Down Expand Up @@ -495,6 +517,12 @@ impl<PDK: Pdk> Bbox for CellBuilder<PDK> {
}
}

impl<PDK: Pdk> LayerBbox for CellBuilder<PDK> {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
self.container.layer_bbox(layer)
}
}

/// A receiver for drawing layout objects.
///
/// Implements the primitive functions that layout objects need to implement [`Draw`].
Expand Down Expand Up @@ -618,6 +646,14 @@ impl<PDK> Bbox for DrawReceiver<PDK> {
}
}

impl<PDK> LayerBbox for DrawReceiver<PDK> {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
self.get_instances()
.layer_bbox(layer)
.bounding_union(&self.elements.layer_bbox(layer))
}
}

/// An object that can be drawn in a [`CellBuilder`].
pub trait Draw<PDK: Pdk>: DrawBoxed<PDK> {
/// Draws `self` inside `recv`.
Expand Down Expand Up @@ -717,6 +753,12 @@ impl<PDK> Bbox for Container<PDK> {
}
}

impl<PDK> LayerBbox for Container<PDK> {
fn layer_bbox(&self, layer: LayerId) -> Option<Rect> {
self.recvs.layer_bbox(layer).transform(self.trans)
}
}

impl<PDK: Pdk> Draw<PDK> for Container<PDK> {
fn draw(self, recv: &mut DrawReceiver<PDK>) -> Result<()> {
recv.draw_container(self);
Expand Down

0 comments on commit 78ab8c4

Please sign in to comment.