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
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Associate layout shapes with nets based on text labels.
use crate::db;
use db::{ToPolygon, WindingNumber};
use libreda_db::prelude::Geometry;
use log;
use std::collections::HashMap;
/// Find pin shapes based on a layer containing all polygon shapes and a layer containing text labels.
/// The text labels mark the shapes that belong to a pin. For each text label all this shapes are grouped together.
///
/// The naive algorithm used is very inefficient but good enough for standard-cells. Especially
/// if it is used in a pre-computation step which is not time-critical.
///
/// # Parameters
///
/// * `layout`: The layout data structure.
/// * `cell`: The cell of which pins should be found.
/// * `pin_shape_layer_id`: The layer which contains the pin shapes.
/// * `label_layer_id`: The layer which contains the text labels of the pins.
pub fn find_pin_geometries_from_text_labels<L: db::LayoutBase<Coord = db::Coord>>(
layout: &L,
cell: &L::CellId,
pin_shape_layer: &L::LayerId,
label_layer: &L::LayerId,
) -> HashMap<String, Vec<db::Geometry<L::Coord>>> {
let shape_ids = find_pin_shapes_from_text_labels(layout, cell, pin_shape_layer, label_layer);
shape_ids
.into_iter()
.map(|(name, ids)| {
let geometries = ids
.into_iter()
.map(|id| layout.with_shape(&id, |_layer, geo| geo.clone()))
.collect();
(name, geometries)
})
.collect()
}
/// Associate pins and shapes based on a layer containing all polygon shapes and a layer containing text labels.
/// The text labels mark the shapes that belong to a pin. For each text label all this shapes are grouped together.
///
/// The naive algorithm used is very inefficient but good enough for standard-cells. Especially
/// if it is used in a pre-computation step which is not time-critical.
///
/// # Parameters
///
/// * `layout`: The layout and netlist data structure.
/// * `cell`: The cell of which pins should be found.
/// * `pin_shape_layer_id`: The layer which contains the pin shapes.
/// * `label_layer_id`: The layer which contains the text labels of the pins.
pub fn assign_pin_shapes_from_text_labels<L: db::L2NEdit<Coord = db::Coord>>(
layout: &mut L,
cell: &L::CellId,
pin_shape_layer: &L::LayerId,
label_layer: &L::LayerId,
) {
// Find the shapes that are marked with a text label.
let pin_shapes = find_pin_shapes_from_text_labels(layout, cell, pin_shape_layer, label_layer);
// Create the links between shapes and pins.
for (pin_name, shapes) in pin_shapes {
if let Some(pin) = layout.pin_by_name(cell, &pin_name) {
for shape in &shapes {
let previous_pin = layout.set_pin_of_shape(shape, Some(pin.clone()));
if let Some(previous_pin) = previous_pin {
if previous_pin != pin {
log::debug!(
"Overwriting pin of shape: '{}' -> '{}'",
layout.pin_name(&previous_pin),
layout.pin_name(&pin)
);
}
}
}
} else {
// Found a label that does not correspond to any pin name in this cell.
let cell_name = layout.cell_name(cell);
log::warn!(
"No such pin in netlist view of cell '{}': '{}'",
cell_name,
&pin_name
);
}
}
}
/// Find pin shapes based on a layer containing all polygon shapes and a layer containing text labels.
/// The text labels mark the shapes that belong to a pin. For each text label all this shapes are grouped together.
///
/// The naive algorithm used is very inefficient but good enough for standard-cells. Especially
/// if it is used in a pre-computation step which is not time-critical.
///
/// # Parameters
///
/// * `layout`: The layout data structure.
/// * `cell`: The cell of which pins should be found.
/// * `pin_shape_layer_id`: The layer which contains the pin shapes.
/// * `label_layer_id`: The layer which contains the text labels of the pins.
pub fn find_pin_shapes_from_text_labels<L: db::LayoutBase<Coord = db::Coord>>(
layout: &L,
cell: &L::CellId,
pin_shape_layer: &L::LayerId,
label_layer: &L::LayerId,
) -> HashMap<String, Vec<L::ShapeId>> {
// Find all labels.
let mut labels = Vec::new();
layout.for_each_shape(cell, label_layer, |_id, geometry| match geometry {
Geometry::Text(t) => labels.push(t.clone()),
_ => {}
});
// For each label find all touching shapes.
let result = labels
.into_iter()
.filter_map(|label| {
// Find all shapes on the pin layer that touch the label.
let mut touching_shapes = Vec::new();
layout.for_each_shape(cell, pin_shape_layer, |shape_id, geometry| {
// TODO: Check if the label touches the shape without converting the shape to a polygon.
let touches = geometry.to_polygon().contains_point(label.location());
if touches {
touching_shapes.push(shape_id.clone())
}
});
if touching_shapes.is_empty() {
None
} else {
Some((label.text().clone(), touching_shapes))
}
})
.collect();
result
}