use log;
use crate::common::Orient;
use crate::lef_ast;
use crate::lef_ast::{Layer, RoutingDirection, TechnologyLef, LEF};
use db::traits::*;
use libreda_db::prelude as db;
use libreda_db::technology::layerstack;
use libreda_db::technology::layerstack::{RoutingLayer, RoutingLayerStack, RoutingLayerType};
use libreda_db::technology::rules;
use libreda_db::technology::rules::RuleBase;
use num_traits::{FromPrimitive, ToPrimitive};
use std::collections::HashMap;
use std::marker::PhantomData;
pub struct LEFDesignRuleAdapter<'a, L: db::LayoutBase> {
lef: &'a LEF,
dbu: f64,
layer_mapping: HashMap<L::LayerId, &'a lef_ast::Layer>,
layer_stack: Vec<(L::LayerId, &'a lef_ast::Layer)>,
ty: PhantomData<L>,
}
impl<'a, L> LEFDesignRuleAdapter<'a, L>
where
L: db::LayoutBase,
L::Coord: ToPrimitive, {
fn db_distance_to_lef(&self, db_distance: L::Coord) -> f64 {
let dbu = self.dbu;
db_distance
.to_f64()
.expect("Conversion from LEF distance unit to database distance unit failed.")
/ dbu
}
}
impl<'a, L> LEFDesignRuleAdapter<'a, L>
where
L: db::LayoutBase,
L::Coord: FromPrimitive, {
fn lef_distance_to_db(&self, lef_distance: f64) -> L::Coord {
let dbu = self.dbu;
L::Coord::from_f64(lef_distance * dbu)
.expect("Conversion from LEF distance unit to database distance unit failed.")
}
}
impl<'a, L> LEFDesignRuleAdapter<'a, L>
where
L: db::LayoutBase,
L::Coord: FromPrimitive + ToPrimitive, {
pub fn new(lef: &'a LEF, layout: &L) -> Self {
let dbu = layout
.dbu()
.to_f64()
.expect("failed to convert data-base unit from to f64");
Self::new_from_layer_mapping(lef, &Self::extract_layer_mapping_from_layout(layout), dbu)
}
pub fn new_from_layer_mapping(
lef: &'a LEF,
layer_ids_by_name: &HashMap<String, L::LayerId>,
dbu: f64,
) -> Self {
assert!(
dbu > 0.0,
"'data-base units per micron' must be larger than 0"
);
let mut new = Self {
lef,
dbu,
layer_mapping: Default::default(),
layer_stack: Default::default(),
ty: Default::default(),
};
new.create_layer_mapping(layer_ids_by_name);
new
}
fn extract_layer_mapping_from_layout(layout: &L) -> HashMap<String, L::LayerId> {
layout
.each_layer()
.filter_map(|layer_id| {
let layer_name = layout
.layer_info(&layer_id)
.name
.as_ref()
.map(|n| n.to_string());
layer_name.map(|name| (name, layer_id))
})
.collect()
}
fn create_layer_mapping(&mut self, layer_ids_by_name: &HashMap<String, L::LayerId>) {
let lef_layers_by_name = self
.lef
.technology
.layers
.iter()
.map(|layer| (layer.name(), layer));
let lef_layers_by_layer_id: Vec<_> = lef_layers_by_name
.filter_map(|(layer_name, layer)| {
let layer_id = layer_ids_by_name.get(layer_name);
layer_id.map(|id| (id.clone(), layer))
})
.collect();
self.layer_mapping = lef_layers_by_layer_id.iter().cloned().collect();
self.layer_stack = lef_layers_by_layer_id;
}
}
impl<'a, L: db::LayoutBase> layerstack::RoutingLayerStack for LEFDesignRuleAdapter<'a, L> {
fn layer_stack(&self) -> Vec<RoutingLayer<Self::LayerId>> {
self.layer_stack
.iter()
.filter_map(|(id, layer)| match layer {
Layer::MasterSlice(_) => None,
Layer::Cut(_) => Some(RoutingLayer::new(id.clone(), RoutingLayerType::Cut)),
Layer::Routing(_) => Some(RoutingLayer::new(id.clone(), RoutingLayerType::Routing)),
})
.collect()
}
}
impl<'a, L: db::LayoutBase> rules::RuleBase for LEFDesignRuleAdapter<'a, L> {
type LayerId = L::LayerId;
}
impl<'a, L: db::LayoutBase> rules::DistanceRuleBase for LEFDesignRuleAdapter<'a, L> {
type Distance = L::Coord;
type Area = L::Coord;
}
impl<'a, L: db::LayoutBase> rules::MinimumSpacing for LEFDesignRuleAdapter<'a, L>
where
L::Coord: ToPrimitive + FromPrimitive,
{
fn min_spacing_absolute(&self, layer_id: &Self::LayerId) -> Option<Self::Distance> {
self.layer_mapping
.get(layer_id)
.and_then(|layer| match layer {
Layer::MasterSlice(_) => unimplemented!("Min spacing for MASTERSLICE layers."),
Layer::Cut(_) => {
None
}
Layer::Routing(routing_layer) => {
get_absolute_min_spacing_of_routing_layer(routing_layer)
}
})
.map(|d| self.lef_distance_to_db(d))
}
fn min_spacing(
&self,
layer_id: &Self::LayerId,
run_length: Self::Distance,
width: Self::Distance,
) -> Option<Self::Distance> {
let run_length = self.db_distance_to_lef(run_length);
let width = self.db_distance_to_lef(width);
self.layer_mapping
.get(layer_id)
.and_then(|layer| match layer {
Layer::MasterSlice(_) => unimplemented!("Min spacing for MASTERSLICE layers."),
Layer::Cut(_) => {
None
}
Layer::Routing(routing_layer) => {
get_min_spacing_of_routing_layer(routing_layer, run_length, width)
}
})
.map(|d| self.lef_distance_to_db(d))
}
}
impl<'a, L: db::LayoutBase> rules::PreferredRoutingDirection for LEFDesignRuleAdapter<'a, L>
where
L::Coord: ToPrimitive + FromPrimitive,
{
fn preferred_routing_direction(&self, layer_id: &Self::LayerId) -> Option<db::Orientation2D> {
self.layer_mapping
.get(layer_id) .and_then(|layer| match layer {
Layer::Routing(routing_layer) => {
match routing_layer.direction {
RoutingDirection::Vertical => Some(db::Orientation2D::Vertical),
RoutingDirection::Horizontal => Some(db::Orientation2D::Horizontal),
RoutingDirection::Diag45 => {
None
}
RoutingDirection::Diag135 => {
None
}
}
}
_ => None, })
}
}
impl<'a, L> rules::RoutingRules for LEFDesignRuleAdapter<'a, L>
where
L: db::LayoutBase,
L::Coord: ToPrimitive + FromPrimitive,
{
fn default_pitch(&self, layer_id: &Self::LayerId) -> Option<(Self::Distance, Self::Distance)> {
self.layer_mapping
.get(layer_id)
.and_then(|layer| match layer {
Layer::MasterSlice(_) => unimplemented!("Default pitch for MASTERSLICE layers."),
Layer::Cut(_) => None, Layer::Routing(routing_layer) => Some(routing_layer.pitch),
})
.map(|(pitch_x, pitch_y)| {
(
self.lef_distance_to_db(pitch_x),
self.lef_distance_to_db(pitch_y),
)
})
}
}
fn get_absolute_min_spacing_of_routing_layer(routing_layer: &lef_ast::RoutingLayer) -> Option<f64> {
if let Some(spacing_table) = &routing_layer.spacing_table {
spacing_table
.spacings
.first()
.and_then(|spacings| spacings.first())
.copied()
.or(Some(0.))
} else {
routing_layer
.spacing
.iter()
.map(|spacing_rule| spacing_rule.min_spacing)
.reduce(|min, x| if x < min { x } else { min })
}
}
fn get_min_spacing_of_routing_layer(
routing_layer: &lef_ast::RoutingLayer,
parallel_runlength: f64,
width: f64,
) -> Option<f64> {
if let Some(spacing_table) = &routing_layer.spacing_table {
let row = spacing_table
.spacings
.iter()
.zip(&spacing_table.widths)
.filter(|(row, &w)| w <= width)
.last()
.map(|(row, _)| row);
row.and_then(|row| {
row.iter()
.zip(&spacing_table.parallel_run_lengths)
.filter(|(spacing, &run_length)| run_length <= parallel_runlength)
.last()
.map(|(&spacing, _)| spacing)
})
} else {
get_absolute_min_spacing_of_routing_layer(routing_layer)
}
}
impl<'a, L> rules::MinimumWidth for LEFDesignRuleAdapter<'a, L>
where
L: db::LayoutBase,
L::Coord: FromPrimitive,
{
fn min_width(
&self,
layer_id: &Self::LayerId,
shape_length: Option<Self::Distance>,
) -> Option<Self::Distance> {
self.layer_mapping
.get(layer_id)
.and_then(|layer| match layer {
Layer::MasterSlice(_) => {
unimplemented!("Minimum width for LEF 'masterslice' layers is not implemented.")
}
Layer::Cut(_) => {
None
}
Layer::Routing(routing_layer) => routing_layer.min_width,
})
.map(|d| self.lef_distance_to_db(d))
}
}
impl<'a, L> rules::DefaultWidth for LEFDesignRuleAdapter<'a, L>
where
L: db::LayoutBase,
L::Coord: FromPrimitive,
{
fn default_width(
&self,
layer_id: &Self::LayerId,
shape_length: Option<Self::Distance>,
) -> Option<Self::Distance> {
self.layer_mapping
.get(layer_id)
.and_then(|layer| match layer {
Layer::MasterSlice(_) => {
unimplemented!("Default width for LEF 'masterslice' layers is not implemented.")
}
Layer::Cut(_) => {
None
}
Layer::Routing(routing_layer) => Some(routing_layer.width),
})
.map(|d| self.lef_distance_to_db(d))
}
}
#[cfg(test)]
mod tests {
use crate::lef_parser::read_lef_chars;
use crate::lef_tech_adapter::LEFDesignRuleAdapter;
use db::technology::rules::*;
use db::traits::*;
use libreda_db::prelude as db;
const LEF_DATA: &'static str = r#"
VERSION 5.5 ;
NAMESCASESENSITIVE ON ;
BUSBITCHARS "[]" ;
DIVIDERCHAR "/" ;
PROPERTYDEFINITIONS
LAYER contactResistance REAL ;
END PROPERTYDEFINITIONS
UNITS
DATABASE MICRONS 1000 ;
END UNITS
MANUFACTURINGGRID 0.0025 ;
LAYER poly
TYPE MASTERSLICE ;
END poly
LAYER contact
TYPE CUT ;
SPACING 0.075 ;
PROPERTY contactResistance 10.5 ;
END contact
LAYER metal1
TYPE ROUTING ;
DIRECTION HORIZONTAL ;
PITCH 0.19 ;
WIDTH 0.065 ;
MINWIDTH 0.05 ;
SPACING 0.065 ;
RESISTANCE RPERSQ 0.38 ;
SPACINGTABLE
PARALLELRUNLENGTH 0.0 1.0
WIDTH 0.0 0.1 0.3
WIDTH 0.5 0.4 0.5
;
END metal1
LAYER via1
TYPE CUT ;
SPACING 0.075 ;
PROPERTY contactResistance 5.69 ;
END via1
LAYER metal2
TYPE ROUTING ;
DIRECTION VERTICAL ;
PITCH 0.19 ;
WIDTH 0.07 ;
SPACING 0.075 ;
END metal2
LAYER OVERLAP
TYPE OVERLAP ;
END OVERLAP
VIA M2_M1_via DEFAULT
LAYER metal1 ;
RECT -0.0675 -0.0325 0.0675 0.0325 ;
LAYER via1 ;
RECT -0.0325 -0.0325 0.0325 0.0325 ;
LAYER metal2 ;
RECT -0.035 -0.0675 0.035 0.0675 ;
END M2_M1_via
VIARULE M2_M1 GENERATE
LAYER metal1 ;
ENCLOSURE 0 0.035 ;
LAYER metal2 ;
ENCLOSURE 0 0.035 ;
LAYER via1 ;
RECT -0.0325 -0.0325 0.0325 0.0325 ;
SPACING 0.14 BY 0.14 ;
END M2_M1
VIARULE M1_POLY GENERATE
LAYER poly ;
ENCLOSURE 0 0 ;
LAYER metal1 ;
ENCLOSURE 0 0.035 ;
LAYER contact ;
RECT -0.0325 -0.0325 0.0325 0.0325 ;
SPACING 0.14 BY 0.14 ;
END M1_POLY
SPACING
SAMENET metal1 metal1 0.065 ;
SAMENET metal2 metal2 0.07 ;
SAMENET metal6 metal6 0.14 ;
SAMENET metal5 metal5 0.14 ;
SAMENET metal4 metal4 0.14 ;
SAMENET metal3 metal3 0.07 ;
SAMENET metal7 metal7 0.4 ;
SAMENET metal8 metal8 0.4 ;
SAMENET metal9 metal9 0.8 ;
SAMENET metal10 metal10 0.8 ;
END SPACING
END LIBRARY
"#;
fn create_empty_layout() -> (db::Chip, Vec<<db::Chip as db::LayoutIds>::LayerId>) {
let mut layout = db::Chip::new();
layout.set_dbu(1000);
let layer1 = layout.create_layer(1, 0);
layout.set_layer_name(&layer1, Some("metal1".into()));
let layer2 = layout.create_layer(2, 0);
layout.set_layer_name(&layer2, Some("metal2".into()));
(layout, vec![layer1, layer2])
}
#[test]
fn test_lef_rule_adapter_pitch() {
let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
let (layout, layers) = create_empty_layout();
let layer1 = &layers[0];
let rules = LEFDesignRuleAdapter::new(&lef, &layout);
dbg!(rules.layer_mapping[layer1]);
assert_eq!(rules.default_pitch(layer1), Some((190, 190)));
assert_eq!(rules.default_pitch_preferred_direction(layer1), Some(190));
}
#[test]
fn test_lef_rule_adapter_min_width() {
let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
let (layout, layers) = create_empty_layout();
let layer1 = &layers[0];
let rules = LEFDesignRuleAdapter::new(&lef, &layout);
dbg!(rules.layer_mapping[layer1]);
assert_eq!(rules.min_width(layer1, None), Some(50));
}
#[test]
fn test_lef_rule_adapter_default_width() {
let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
let (layout, layers) = create_empty_layout();
let layer1 = &layers[0];
let rules = LEFDesignRuleAdapter::new(&lef, &layout);
dbg!(rules.layer_mapping[layer1]);
assert_eq!(rules.default_width(layer1, None), Some(65));
}
#[test]
fn test_lef_rule_adapter_spacing_table() {
let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
let (layout, layers) = create_empty_layout();
let layer1 = &layers[0];
let layer2 = &layers[1];
let rules = LEFDesignRuleAdapter::new(&lef, &layout);
assert_eq!(rules.min_spacing_absolute(layer1), Some(100));
assert_eq!(rules.min_spacing(layer1, 0, 0), Some(100));
assert_eq!(rules.min_spacing(layer1, 999, 0), Some(100));
assert_eq!(rules.min_spacing(layer1, 1000, 0), Some(300));
assert_eq!(rules.min_spacing(layer1, 0, 499), Some(100));
assert_eq!(rules.min_spacing(&layer1, 0, 500), Some(400));
}
#[test]
fn test_lef_rule_adapter_min_spacing() {
let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
let (layout, layers) = create_empty_layout();
let layer1 = &layers[0];
let layer2 = &layers[1];
let rules = LEFDesignRuleAdapter::new(&lef, &layout);
dbg!(rules.layer_mapping[layer2]);
assert_eq!(rules.min_spacing(layer2, 0, 0), Some(75));
assert_eq!(rules.min_spacing_absolute(layer2), Some(75));
}
}