ASIC place & route framework. This crate contains interface definitions of the core parts of the place & route flow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
4.2 KiB

/*
* Copyright (c) 2020-2021 Thomas Kramer.
*
* This file is part of LibrEDA
* (see https://codeberg.org/libreda).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! Air wire router for visualizing component connectivity. Does not create a legal routing.
use libreda_db::layout::types::{SInt};
use crate::route::simple_router::{SimpleRouter, SimpleRoutedNet};
use libreda_db::prelude::{SimpleRPolygon, Point, Path, Rect, TryBoundingBox};
use std::collections::HashMap;
/// Router that creates air wires between routing terminals in a star-topology.
/// This does not produce a legal routing and has
/// the only purpose to visualize the connectivity of components.
pub struct AirWireRouter {
/// Layer for the air wires.
air_wire_layer: u8,
/// Wire thickness.
wire_thickness: SInt,
/// Draw a full mesh instead of a star network.
full_mesh: bool,
}
impl AirWireRouter {
/// Create a default router.
pub fn new(air_wire_layer: u8, wire_thickness: SInt, full_mesh: bool) -> Self {
Self {
air_wire_layer,
wire_thickness,
full_mesh,
}
}
}
impl SimpleRouter for AirWireRouter {
fn name(&self) -> &str {
"AirWireRouter"
}
fn compute_routes_impl(&self,
_boundary: Rect<SInt>,
net_terminals: &HashMap<usize, Vec<Vec<(SimpleRPolygon<SInt>, u8)>>>,
_obstacles: &Vec<(SimpleRPolygon<SInt>, u8)>,
) -> HashMap<usize, SimpleRoutedNet> {
let mut result = HashMap::new();
for (net, pins) in net_terminals {
let mut net_wires = Vec::new();
// Of each pin take the first terminal shape.
let terminals: Vec<_> = pins.iter()
.filter_map(|t| t.first())
.collect();
// Compute the center of the terminals.
let center = {
let mut num_elements = 0;
let sum: Point<_> = terminals.iter()
.filter_map(|(t, _)| t.try_bounding_box())
.map(|b| b.center())
.inspect(|_| num_elements += 1)
.sum();
sum / num_elements
};
// Get some representative points of the terminals.
let terminal_points: Vec<_> = terminals.iter()
// Get a point close to the center of all terminal shapes.
.filter_map(|(t, _layer)| t.points()
.min_by_key(|&p| (p-center).norm1()))
.collect();
if self.full_mesh {
for (i, a) in terminal_points.iter().enumerate() {
for b in &terminal_points[i..] {
let ray = Path::new(vec![*a, *b], self.wire_thickness);
net_wires.push((self.air_wire_layer, ray.into()))
}
}
} else {
// Draw star-network.
// Get the center of weight to create a star topology.
let sum: Point<_> = terminal_points.iter().copied().sum();
let center = sum / terminal_points.len() as SInt;
// Draw star network.
for p in terminal_points {
let ray = Path::new(vec![p, center], self.wire_thickness);
net_wires.push((self.air_wire_layer, ray.into()))
}
}
let routed_net = SimpleRoutedNet {
routes: net_wires,
vias: Default::default(),
};
result.insert(*net, routed_net);
}
result
}
}