libreda_db/technology/
layerstack.rs

1// Copyright (c) 2020-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! Definition of the metal layer stack as it is needed for routers.
7
8use super::rules::RuleBase;
9
10/// A routing layer is either a 'via' or 'routing/metal' layer.
11#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
12pub enum RoutingLayerType {
13    /// Via layer.
14    Cut,
15    /// Routing layer.
16    Routing,
17}
18
19/// Annotate a layer ID as 'via' or 'routing' layer.
20#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
21pub struct RoutingLayer<LayerId> {
22    /// ID of the layer. This identifies the layer in the data-base structures.
23    pub id: LayerId,
24    /// Type of the routing layer (via or metal).
25    pub layer_type: RoutingLayerType,
26}
27
28impl<LayerId> RoutingLayer<LayerId> {
29    /// Associate a layer ID with a layer type.
30    pub fn new(id: LayerId, layer_type: RoutingLayerType) -> Self {
31        Self { id, layer_type }
32    }
33
34    /// Get the a reference to the ID of the layer.
35    pub fn as_id(&self) -> &LayerId {
36        &self.id
37    }
38
39    /// Get the ID of the layer.
40    pub fn id(self) -> LayerId {
41        self.id
42    }
43
44    /// Type of the layer.
45    pub fn layer_type(&self) -> RoutingLayerType {
46        self.layer_type
47    }
48
49    /// Check if layer is a via/cut layer.
50    pub fn is_via_layer(&self) -> bool {
51        match self.layer_type() {
52            RoutingLayerType::Cut => true,
53            RoutingLayerType::Routing => false,
54        }
55    }
56
57    /// Check if layer is a metal layer.
58    pub fn is_metal_layer(&self) -> bool {
59        match self.layer_type() {
60            RoutingLayerType::Cut => false,
61            RoutingLayerType::Routing => true,
62        }
63    }
64}
65
66/// Define standardized access for routing and via layers.
67pub trait RoutingLayerStack: RuleBase {
68    /// Get the stack of routing and via layers in process order.
69    fn layer_stack(&self) -> Vec<RoutingLayer<Self::LayerId>>;
70
71    /// Get the layer ids of the layer stack (routing layers and via layers).
72    fn layer_stack_ids(&self) -> Vec<Self::LayerId> {
73        self.layer_stack().into_iter().map(|l| l.id).collect()
74    }
75
76    /// Get the stack of routing metal layers in process order.
77    fn routing_layer_stack(&self) -> Vec<Self::LayerId> {
78        self.layer_stack()
79            .into_iter()
80            .filter(|l| l.is_metal_layer())
81            .map(|l| l.id())
82            .collect()
83    }
84
85    /// Get the stack of via layers in process order.
86    fn via_layer_stack(&self) -> Vec<Self::LayerId> {
87        self.layer_stack()
88            .into_iter()
89            .filter(|l| l.is_via_layer())
90            .map(|l| l.id())
91            .collect()
92    }
93
94    /// Find the closest metal layer above the given layer.
95    fn get_upper_metal_layer(&self, layer: &Self::LayerId) -> Option<Self::LayerId> {
96        self.layer_stack()
97            .into_iter()
98            .skip_while(|l| l.as_id() != layer)
99            .skip(1)
100            .find(|l| l.is_metal_layer())
101            .map(|l| l.id())
102    }
103
104    /// Find the closest metal layer under the given layer.
105    fn get_lower_metal_layer(&self, layer: &Self::LayerId) -> Option<Self::LayerId> {
106        self.layer_stack()
107            .into_iter()
108            .rev()
109            .skip_while(|l| l.as_id() != layer)
110            .skip(1)
111            .find(|l| l.is_metal_layer())
112            .map(|l| l.id())
113    }
114}