1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Traits for layout data types.
#![allow(unused_variables)]
#![allow(missing_docs)] // Necessary because portrait does not generate docs.
use crate::layout::types::{LayerInfo, UInt};
use crate::prelude::PropertyValue;
use crate::prelude::{Geometry, Rect};
use crate::traits::{
HierarchyBase, HierarchyBaseMT, HierarchyEdit, HierarchyIds, IdType, IdTypeMT,
};
use iron_shapes::transform::SimpleTransform;
use iron_shapes::CoordinateType;
use num_traits::Num;
use std::hash::Hash;
/// Helper trait which constrains [`trait@LayoutBase`] for such that ID types
/// are [`Send`] and [`Sync`] as commonly used for parallel algorithms.
#[portrait::make]
pub trait LayoutBaseMT:
LayoutBase<LayerId = Self::LayerIdMT, ShapeId = Self::ShapeIdMT> + HierarchyBaseMT
{
/// Identifier for layers.
type LayerIdMT: IdTypeMT;
/// Identifier for shapes.
type ShapeIdMT: IdTypeMT;
}
impl<L> LayoutBaseMT for L
where
L: LayoutBase + HierarchyBaseMT,
L::LayerId: Send + Sync,
L::ShapeId: Send + Sync,
{
type LayerIdMT = L::LayerId;
type ShapeIdMT = L::ShapeId;
}
/// Define ID types used in layouts.
#[portrait::make(import(crate::prelude::*))]
pub trait LayoutIds: HierarchyIds {
/// Number type used for coordinates and distances.
type Coord: CoordinateType + std::fmt::Debug + std::fmt::Display + Hash + 'static + Send + Sync;
/// Number type for areas.
/// This is possibly another type then `Coord` for the following reasons:
/// * Distances and areas are semantically different.
/// * In practice `i32` is a good choice for coordinates. However, computing areas in `i32` might
/// easily lead to overflows. Hence a 64-bit integer type might be a better choice.
type Area: Num + Copy + PartialOrd + From<Self::Coord> + 'static + Send + Sync;
/// Layer identifier type.
type LayerId: IdType;
/// Shape identifier type.
type ShapeId: IdType;
}
/// Most basic trait of a layout.
///
/// This traits specifies methods for accessing the components of a layout.
#[portrait::make(import(crate::prelude::*))]
pub trait LayoutBase: LayoutIds + HierarchyBase {
/// Get the distance unit used in this layout in 'pixels per micron'.
fn dbu(&self) -> Self::Coord;
/// Iterate over all defined layers.
fn each_layer(&self) -> Box<dyn Iterator<Item = Self::LayerId> + '_>;
/// Get the `LayerInfo` data structure for this layer.
fn layer_info(&self, layer: &Self::LayerId) -> LayerInfo<Self::NameType>;
/// Find layer index by the (index, data type) tuple.
fn find_layer(&self, index: UInt, datatype: UInt) -> Option<Self::LayerId>;
/// Find layer index by the name.
fn layer_by_name(&self, name: &str) -> Option<Self::LayerId>;
/// Compute the bounding box of the shapes on one layer.
/// The bounding box also includes all child cell instances.
fn bounding_box_per_layer(
&self,
cell: &Self::CellId,
layer: &Self::LayerId,
) -> Option<Rect<Self::Coord>>;
/// Compute the bounding box of the cell over all layers.
/// The bounding box is not defined if the cell is empty. In this
/// case return `None`.
fn bounding_box(&self, cell: &Self::CellId) -> Option<Rect<Self::Coord>> {
self.each_layer()
.map(|layer| self.bounding_box_per_layer(cell, &layer))
.fold(None, |a, b| match (a, b) {
(None, None) => None,
(Some(a), None) | (None, Some(a)) => Some(a),
(Some(a), Some(b)) => Some(a.add_rect(&b)),
})
}
/// Iterate over the IDs of all shapes in the cell on a specific layer.
fn each_shape_id(
&self,
cell: &Self::CellId,
layer: &Self::LayerId,
) -> Box<dyn Iterator<Item = Self::ShapeId> + '_>;
/// Call a function for each shape on this layer.
fn for_each_shape<F>(&self, cell: &Self::CellId, layer: &Self::LayerId, f: F)
where
F: FnMut(&Self::ShapeId, &Geometry<Self::Coord>);
/// Access a shape by its ID.
fn with_shape<F, R>(&self, shape_id: &Self::ShapeId, f: F) -> R
where
F: FnMut(&Self::LayerId, &Geometry<Self::Coord>) -> R;
/// Get a clone of the shape geometry.
fn shape_geometry(&self, shape_id: &Self::ShapeId) -> Geometry<Self::Coord> {
self.with_shape(shape_id, |_, geo| geo.clone())
}
/// Get the layer of a shape.
fn shape_layer(&self, shape_id: &Self::ShapeId) -> Self::LayerId {
self.with_shape(shape_id, |layer, _| layer.clone())
}
/// Get the parent cell and the layer of a shape as a (cell, layer) tuple.
fn parent_of_shape(&self, shape_id: &Self::ShapeId) -> (Self::CellId, Self::LayerId);
/// Call a function `f` for each shape of this cell and its sub cells.
/// Along to the geometric shape `f` also gets a transformation as argument.
/// The transformation describes the actual position of the geometric shape relative to the `cell`.
fn for_each_shape_recursive<F>(&self, cell: &Self::CellId, layer: &Self::LayerId, mut f: F)
where
F: FnMut(SimpleTransform<Self::Coord>, &Self::ShapeId, &Geometry<Self::Coord>),
{
// This recursive iteration through the cells is implemented iteratively.
// A plain recursive implementation is more difficult to handle due to the type system.
// Stack for resolved recursion.
let mut stack = Vec::new();
stack.push((cell.clone(), SimpleTransform::identity()));
while let Some((cell, tf)) = stack.pop() {
// Push child instances.
self.for_each_cell_instance(&cell, |inst| {
let template = self.template_cell(&inst);
let transform = self.get_transform(&inst);
let tf2 = transform.then(&tf);
stack.push((template, tf2));
});
// Process shapes of this cell.
self.for_each_shape(&cell, layer, |id, g| f(tf, id, g));
}
}
/// Get the geometric transform that describes the location of a cell instance relative to its parent.
fn get_transform(&self, cell_inst: &Self::CellInstId) -> SimpleTransform<Self::Coord>;
/// Get a property of a shape.
fn get_shape_property(
&self,
shape: &Self::ShapeId,
key: &Self::NameType,
) -> Option<PropertyValue> {
None
}
}
/// Access shapes and instances in a layout based on their locations.
#[portrait::make]
pub trait RegionSearch: LayoutBase {
/// Iterate over the IDs of all shapes (on all layers) whose bounding-box overlaps with the `search_region`.
fn each_shape_in_region(
&self,
cell: &Self::CellId,
search_region: &Rect<Self::Coord>,
) -> Box<dyn Iterator<Item = Self::ShapeId> + '_> {
let cell = cell.clone(); // Get an owned ID.
let search_region = *search_region; // Get an owned rectangle.
Box::new(self.each_layer().flat_map(move |layer_id| {
self.each_shape_in_region_per_layer(&cell, &layer_id, &search_region)
}))
}
/// Iterate over the IDs of all shapes (on a specific layer) whose bounding-box overlaps with the `search_region`.
fn each_shape_in_region_per_layer(
&self,
cell: &Self::CellId,
layer_id: &Self::LayerId,
search_region: &Rect<Self::Coord>,
) -> Box<dyn Iterator<Item = Self::ShapeId> + '_>;
/// Iterate over the IDs of all instances within the `cell` whose bounding-box overlaps with the `search_region`.
fn each_cell_instance_in_region(
&self,
cell: &Self::CellId,
search_region: &Rect<Self::Coord>,
) -> Box<dyn Iterator<Item = Self::CellInstId> + '_>;
}
/// Trait for layouts that support editing.
#[portrait::make(import(crate::prelude::*))]
pub trait LayoutEdit: LayoutBase + HierarchyEdit {
/// Set the distance unit used in this layout in 'pixels per micron'.
fn set_dbu(&mut self, dbu: Self::Coord) {} // TODO: Remove default implementation.
/// Create a new layer.
/// Use `set_layer_name()` to define a name.
fn create_layer(&mut self, index: UInt, datatype: UInt) -> Self::LayerId;
/// Create a new layer with a specific ID. This is used to clone layer-stacks between layouts while preserving their IDs.
/// Returns an `Err` when the ID already exists.
fn create_layer_with_id(
&mut self,
layer_id: Self::LayerId,
index: UInt,
datatype: UInt,
) -> Result<(), ()>;
/// Set the name of a layer or clear the layer name when passing `None`.
/// This method should not change the ID of the layer.
/// Returns the previous name of the layer.
fn set_layer_name(
&mut self,
layer: &Self::LayerId,
name: Option<Self::NameType>,
) -> Option<Self::NameType>;
/// Insert a geometric shape into the parent cell.
fn insert_shape(
&mut self,
parent_cell: &Self::CellId,
layer: &Self::LayerId,
geometry: Geometry<Self::Coord>,
) -> Self::ShapeId;
/// Remove shape from the parent cell.
fn remove_shape(&mut self, shape_id: &Self::ShapeId) -> Option<Geometry<Self::Coord>>;
/// Replace the geometry of a shape.
fn replace_shape(
&mut self,
shape_id: &Self::ShapeId,
geometry: Geometry<Self::Coord>,
) -> Geometry<Self::Coord>;
/// Set the geometric transform that describes the location of a cell instance relative to its parent.
fn set_transform(&mut self, cell_inst: &Self::CellInstId, tf: SimpleTransform<Self::Coord>);
/// Set a property of a shape.
fn set_shape_property(
&mut self,
shape: &Self::ShapeId,
key: Self::NameType,
value: PropertyValue,
) {
}
}