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,
    ) {
    }
}