libreda_lefdef/
lef_tech_adapter.rs

1// Copyright (c) 2021-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6/// Implement the design rule traits from `libreda-db` for LEF.
7/// This allows standardized read access to design-rules and technology data.
8///
9/// [`LEFDesignRuleAdapter`] creates the mapping between the layers defined in a layout and the layers defined in a LEF file
10/// and then provides access to the LEF data via the technology traits.
11use log;
12
13use crate::common::Orient;
14use crate::lef_ast;
15use crate::lef_ast::{Layer, RoutingDirection, TechnologyLef, LEF};
16use db::traits::*;
17use libreda_db::prelude as db;
18use libreda_db::technology::layerstack;
19use libreda_db::technology::layerstack::{RoutingLayer, RoutingLayerStack, RoutingLayerType};
20use libreda_db::technology::rules;
21use libreda_db::technology::rules::RuleBase;
22use num_traits::{FromPrimitive, ToPrimitive};
23use std::collections::HashMap;
24use std::marker::PhantomData;
25
26/// Provides standardized read access to the design-rules defined in a LEF structure.
27pub struct LEFDesignRuleAdapter<'a, L: db::LayoutBase> {
28    /// Underlying LEF data.
29    lef: &'a LEF,
30    /// Data-base units per micron.
31    dbu: f64,
32    /// Mapping from layer IDs to actual LEF layer data.
33    layer_mapping: HashMap<L::LayerId, &'a lef_ast::Layer>,
34    /// Layers sorted by the processing order: Starts with layers close to the substrate, ends with top level metal layers.
35    layer_stack: Vec<(L::LayerId, &'a lef_ast::Layer)>,
36    ty: PhantomData<L>,
37}
38
39impl<'a, L> LEFDesignRuleAdapter<'a, L>
40where
41    L: db::LayoutBase,
42    L::Coord: ToPrimitive, // Need to be able to cast a float into Coord.
43{
44    /// Convert from a distance in data-base units into a LEF distance (f64).
45    fn db_distance_to_lef(&self, db_distance: L::Coord) -> f64 {
46        let dbu = self.dbu;
47
48        db_distance
49            .to_f64()
50            .expect("Conversion from LEF distance unit to database distance unit failed.")
51            / dbu
52    }
53}
54
55impl<'a, L> LEFDesignRuleAdapter<'a, L>
56where
57    L: db::LayoutBase,
58    L::Coord: FromPrimitive, // Need to be able to cast a float into Coord.
59{
60    /// Convert from a LEF distance (f64) into the correct unit used by the layout.
61    fn lef_distance_to_db(&self, lef_distance: f64) -> L::Coord {
62        let dbu = self.dbu;
63
64        L::Coord::from_f64(lef_distance * dbu)
65            .expect("Conversion from LEF distance unit to database distance unit failed.")
66    }
67}
68
69impl<'a, L> LEFDesignRuleAdapter<'a, L>
70where
71    L: db::LayoutBase,
72    L::Coord: FromPrimitive + ToPrimitive, // Need to be able to cast a float into Coord.
73{
74    /// Create a new design rule adapter for a LEF data structure.
75    /// Derives the mapping from layer IDs and LEF layers based on the layer names.
76    pub fn new(lef: &'a LEF, layout: &L) -> Self {
77        let dbu = layout
78            .dbu()
79            .to_f64()
80            .expect("failed to convert data-base unit from to f64");
81        Self::new_from_layer_mapping(lef, &Self::extract_layer_mapping_from_layout(layout), dbu)
82    }
83
84    /// Create a new design rule adapter for a LEF data structure
85    /// with a custom mapping between layer names and layer IDs.
86    pub fn new_from_layer_mapping(
87        lef: &'a LEF,
88        layer_ids_by_name: &HashMap<String, L::LayerId>,
89        dbu: f64,
90    ) -> Self {
91        assert!(
92            dbu > 0.0,
93            "'data-base units per micron' must be larger than 0"
94        );
95
96        let mut new = Self {
97            lef,
98            dbu,
99            layer_mapping: Default::default(),
100            layer_stack: Default::default(),
101            ty: Default::default(),
102        };
103
104        new.create_layer_mapping(layer_ids_by_name);
105
106        new
107    }
108
109    /// Find the mapping from layer names to layer IDs.
110    fn extract_layer_mapping_from_layout(layout: &L) -> HashMap<String, L::LayerId> {
111        layout
112            .each_layer()
113            .filter_map(|layer_id| {
114                let layer_name = layout
115                    .layer_info(&layer_id)
116                    .name
117                    .as_ref()
118                    .map(|n| n.to_string());
119                layer_name.map(|name| (name, layer_id))
120            })
121            .collect()
122    }
123
124    /// Initialize the mapping: layer ID -> LEF layer structure.
125    fn create_layer_mapping(&mut self, layer_ids_by_name: &HashMap<String, L::LayerId>) {
126        // Create look-up table: Layer name -> LEF layer
127        let lef_layers_by_name = self
128            .lef
129            .technology
130            .layers
131            .iter()
132            .map(|layer| (layer.name(), layer));
133
134        // Create look-up table: Layer ID -> LEF layer
135        let lef_layers_by_layer_id: Vec<_> = lef_layers_by_name
136            .filter_map(|(layer_name, layer)| {
137                let layer_id = layer_ids_by_name.get(layer_name);
138                layer_id.map(|id| (id.clone(), layer))
139            })
140            .collect();
141
142        self.layer_mapping = lef_layers_by_layer_id.iter().cloned().collect();
143
144        self.layer_stack = lef_layers_by_layer_id;
145    }
146}
147
148impl<'a, L: db::LayoutBase> layerstack::RoutingLayerStack for LEFDesignRuleAdapter<'a, L> {
149    fn layer_stack(&self) -> Vec<RoutingLayer<Self::LayerId>> {
150        self.layer_stack
151            .iter()
152            // Take routing and cut layers only.
153            .filter_map(|(id, layer)| match layer {
154                Layer::MasterSlice(_) => None,
155                Layer::Cut(_) => Some(RoutingLayer::new(id.clone(), RoutingLayerType::Cut)),
156                Layer::Routing(_) => Some(RoutingLayer::new(id.clone(), RoutingLayerType::Routing)),
157            })
158            .collect()
159    }
160}
161
162impl<'a, L: db::LayoutBase> rules::RuleBase for LEFDesignRuleAdapter<'a, L> {
163    type LayerId = L::LayerId;
164}
165
166impl<'a, L: db::LayoutBase> rules::DistanceRuleBase for LEFDesignRuleAdapter<'a, L> {
167    type Distance = L::Coord;
168    type Area = L::Coord;
169}
170
171impl<'a, L: db::LayoutBase> rules::MinimumSpacing for LEFDesignRuleAdapter<'a, L>
172where
173    L::Coord: ToPrimitive + FromPrimitive,
174{
175    fn min_spacing_absolute(&self, layer_id: &Self::LayerId) -> Option<Self::Distance> {
176        self.layer_mapping
177            .get(layer_id)
178            .and_then(|layer| match layer {
179                Layer::MasterSlice(_) => unimplemented!("Min spacing for MASTERSLICE layers."),
180                Layer::Cut(_) => {
181                    // log::warn!("Not implemented: minimum spacing for CUT layers.");
182                    // TODO: minimum spacing for CUT layers
183                    None
184                }
185                Layer::Routing(routing_layer) => {
186                    // Get spacing based on routing_layer.spacing_table or routing_layer.spacing.
187                    get_absolute_min_spacing_of_routing_layer(routing_layer)
188                }
189            })
190            .map(|d| self.lef_distance_to_db(d))
191    }
192
193    fn min_spacing(
194        &self,
195        layer_id: &Self::LayerId,
196        run_length: Self::Distance,
197        width: Self::Distance,
198    ) -> Option<Self::Distance> {
199        let run_length = self.db_distance_to_lef(run_length);
200        let width = self.db_distance_to_lef(width);
201
202        self.layer_mapping
203            .get(layer_id)
204            .and_then(|layer| match layer {
205                Layer::MasterSlice(_) => unimplemented!("Min spacing for MASTERSLICE layers."),
206                Layer::Cut(_) => {
207                    // TODO: unimplemented!("Min spacing for CUT layers.");
208                    None
209                }
210                Layer::Routing(routing_layer) => {
211                    // Get spacing based on routing_layer.spacing_table or routing_layer.spacing.
212                    get_min_spacing_of_routing_layer(routing_layer, run_length, width)
213                }
214            })
215            .map(|d| self.lef_distance_to_db(d))
216    }
217}
218
219impl<'a, L: db::LayoutBase> rules::PreferredRoutingDirection for LEFDesignRuleAdapter<'a, L>
220where
221    L::Coord: ToPrimitive + FromPrimitive,
222{
223    fn preferred_routing_direction(&self, layer_id: &Self::LayerId) -> Option<db::Orientation2D> {
224        self.layer_mapping
225            .get(layer_id) // Find LEF layer.
226            .and_then(|layer| match layer {
227                Layer::Routing(routing_layer) => {
228                    match routing_layer.direction {
229                        RoutingDirection::Vertical => Some(db::Orientation2D::Vertical),
230                        RoutingDirection::Horizontal => Some(db::Orientation2D::Horizontal),
231                        RoutingDirection::Diag45 => {
232                            // TODO
233                            None
234                        }
235                        RoutingDirection::Diag135 => {
236                            // TODO
237                            None
238                        }
239                    }
240                }
241                _ => None, // No preferred routing direction for other layer types.
242            })
243    }
244}
245
246impl<'a, L> rules::RoutingRules for LEFDesignRuleAdapter<'a, L>
247where
248    L: db::LayoutBase,
249    L::Coord: ToPrimitive + FromPrimitive,
250{
251    fn default_pitch(&self, layer_id: &Self::LayerId) -> Option<(Self::Distance, Self::Distance)> {
252        self.layer_mapping
253            .get(layer_id)
254            .and_then(|layer| match layer {
255                Layer::MasterSlice(_) => unimplemented!("Default pitch for MASTERSLICE layers."),
256                Layer::Cut(_) => None, // TODO
257                Layer::Routing(routing_layer) => Some(routing_layer.pitch),
258            })
259            .map(|(pitch_x, pitch_y)| {
260                (
261                    self.lef_distance_to_db(pitch_x),
262                    self.lef_distance_to_db(pitch_y),
263                )
264            })
265    }
266}
267
268/// Get the minimal spacing on the given layer.
269/// Return `None` if there's no spacing rule defined.
270/// TODO: Currently only SPACINGTABLEs are considered. Also support SPACING statements.
271fn get_absolute_min_spacing_of_routing_layer(routing_layer: &lef_ast::RoutingLayer) -> Option<f64> {
272    if let Some(spacing_table) = &routing_layer.spacing_table {
273        spacing_table
274            .spacings
275            .first()
276            .and_then(|spacings| spacings.first())
277            .copied()
278            .or(Some(0.))
279    } else {
280        // Derive spacing from SPACING statements.
281        routing_layer
282            .spacing
283            .iter()
284            .map(|spacing_rule| spacing_rule.min_spacing)
285            // Find minimum.
286            .reduce(|min, x| if x < min { x } else { min })
287    }
288}
289
290/// Get the minimal spacing on the given layer.
291/// Return `None` if there's no spacing rule defined.
292/// TODO: Currently only SPACINGTABLEs are considered. Also support SPACING statements.
293fn get_min_spacing_of_routing_layer(
294    routing_layer: &lef_ast::RoutingLayer,
295    parallel_runlength: f64,
296    width: f64,
297) -> Option<f64> {
298    if let Some(spacing_table) = &routing_layer.spacing_table {
299        // Find correct row for the given width.
300        let row = spacing_table
301            .spacings
302            .iter()
303            .zip(&spacing_table.widths)
304            .filter(|(row, &w)| w <= width)
305            .last()
306            .map(|(row, _)| row);
307        row.and_then(|row| {
308            // Find correct value based on the runlength.
309            row.iter()
310                .zip(&spacing_table.parallel_run_lengths)
311                .filter(|(spacing, &run_length)| run_length <= parallel_runlength)
312                .last()
313                .map(|(&spacing, _)| spacing)
314        })
315    } else {
316        // TODO: Derive spacing from SPACING statements.
317        get_absolute_min_spacing_of_routing_layer(routing_layer)
318    }
319}
320
321impl<'a, L> rules::MinimumWidth for LEFDesignRuleAdapter<'a, L>
322where
323    L: db::LayoutBase,
324    L::Coord: FromPrimitive,
325{
326    fn min_width(
327        &self,
328        layer_id: &Self::LayerId,
329        shape_length: Option<Self::Distance>,
330    ) -> Option<Self::Distance> {
331        self.layer_mapping
332            .get(layer_id)
333            .and_then(|layer| match layer {
334                Layer::MasterSlice(_) => {
335                    unimplemented!("Minimum width for LEF 'masterslice' layers is not implemented.")
336                }
337                Layer::Cut(_) => {
338                    None
339                    // TODO unimplemented!("Minimum width for LEF 'cut' layers is not implemented.")
340                }
341                Layer::Routing(routing_layer) => routing_layer.min_width,
342            })
343            .map(|d| self.lef_distance_to_db(d))
344    }
345}
346
347impl<'a, L> rules::DefaultWidth for LEFDesignRuleAdapter<'a, L>
348where
349    L: db::LayoutBase,
350    L::Coord: FromPrimitive,
351{
352    fn default_width(
353        &self,
354        layer_id: &Self::LayerId,
355        shape_length: Option<Self::Distance>,
356    ) -> Option<Self::Distance> {
357        self.layer_mapping
358            .get(layer_id)
359            .and_then(|layer| match layer {
360                Layer::MasterSlice(_) => {
361                    unimplemented!("Default width for LEF 'masterslice' layers is not implemented.")
362                }
363                Layer::Cut(_) => {
364                    None
365                    // TODO: unimplemented!("Default width for LEF 'cut' layers is not implemented.")
366                }
367                Layer::Routing(routing_layer) => Some(routing_layer.width),
368            })
369            .map(|d| self.lef_distance_to_db(d))
370    }
371}
372
373#[cfg(test)]
374mod tests {
375    use crate::lef_parser::read_lef_chars;
376    use crate::lef_tech_adapter::LEFDesignRuleAdapter;
377    use db::technology::rules::*;
378    use db::traits::*;
379    use libreda_db::prelude as db;
380
381    const LEF_DATA: &'static str = r#"
382VERSION 5.5 ;
383NAMESCASESENSITIVE ON ;
384BUSBITCHARS "[]" ;
385DIVIDERCHAR "/" ;
386
387PROPERTYDEFINITIONS
388  LAYER contactResistance REAL ;
389END PROPERTYDEFINITIONS
390
391UNITS
392  DATABASE MICRONS 1000 ;
393END UNITS
394MANUFACTURINGGRID 0.0025 ;
395LAYER poly
396  TYPE MASTERSLICE ;
397END poly
398
399LAYER contact
400  TYPE CUT ;
401  SPACING 0.075 ;
402  PROPERTY contactResistance 10.5 ;
403END contact
404
405LAYER metal1
406  TYPE ROUTING ;
407  DIRECTION HORIZONTAL ;
408  PITCH 0.19 ;
409  WIDTH 0.065 ;
410  MINWIDTH 0.05 ;
411  SPACING 0.065 ;
412  RESISTANCE RPERSQ 0.38 ;
413
414  SPACINGTABLE
415    PARALLELRUNLENGTH   0.0  1.0
416    WIDTH 0.0           0.1  0.3
417    WIDTH 0.5           0.4  0.5
418  ;
419
420END metal1
421
422LAYER via1
423  TYPE CUT ;
424  SPACING 0.075 ;
425  PROPERTY contactResistance 5.69 ;
426END via1
427
428LAYER metal2
429    TYPE ROUTING ;
430    DIRECTION VERTICAL ;
431    PITCH 0.19 ;
432    WIDTH 0.07 ;
433    SPACING 0.075 ;
434END metal2
435
436LAYER OVERLAP
437  TYPE OVERLAP ;
438END OVERLAP
439
440VIA M2_M1_via DEFAULT
441  LAYER metal1 ;
442    RECT -0.0675 -0.0325 0.0675 0.0325 ;
443  LAYER via1 ;
444    RECT -0.0325 -0.0325 0.0325 0.0325 ;
445  LAYER metal2 ;
446    RECT -0.035 -0.0675 0.035 0.0675 ;
447END M2_M1_via
448
449VIARULE M2_M1 GENERATE
450  LAYER metal1 ;
451    ENCLOSURE 0 0.035 ;
452  LAYER metal2 ;
453    ENCLOSURE 0 0.035 ;
454  LAYER via1 ;
455    RECT -0.0325 -0.0325 0.0325 0.0325 ;
456    SPACING 0.14 BY 0.14 ;
457END M2_M1
458
459VIARULE M1_POLY GENERATE
460  LAYER poly ;
461    ENCLOSURE 0 0 ;
462  LAYER metal1 ;
463    ENCLOSURE 0 0.035 ;
464  LAYER contact ;
465    RECT -0.0325 -0.0325 0.0325 0.0325 ;
466    SPACING 0.14 BY 0.14 ;
467END M1_POLY
468
469SPACING
470  SAMENET metal1 metal1 0.065 ;
471  SAMENET metal2 metal2 0.07 ;
472  SAMENET metal6 metal6 0.14 ;
473  SAMENET metal5 metal5 0.14 ;
474  SAMENET metal4 metal4 0.14 ;
475  SAMENET metal3 metal3 0.07 ;
476  SAMENET metal7 metal7 0.4 ;
477  SAMENET metal8 metal8 0.4 ;
478  SAMENET metal9 metal9 0.8 ;
479  SAMENET metal10 metal10 0.8 ;
480END SPACING
481
482END LIBRARY
483
484    "#;
485
486    fn create_empty_layout() -> (db::Chip, Vec<<db::Chip as db::LayoutIds>::LayerId>) {
487        // Create an empty layout with some layers which match the LEF layer names.
488        let mut layout = db::Chip::new();
489        layout.set_dbu(1000);
490
491        let layer1 = layout.create_layer(1, 0);
492        layout.set_layer_name(&layer1, Some("metal1".into()));
493
494        let layer2 = layout.create_layer(2, 0);
495        layout.set_layer_name(&layer2, Some("metal2".into()));
496
497        (layout, vec![layer1, layer2])
498    }
499
500    #[test]
501    fn test_lef_rule_adapter_pitch() {
502        let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
503
504        let (layout, layers) = create_empty_layout();
505        let layer1 = &layers[0];
506
507        let rules = LEFDesignRuleAdapter::new(&lef, &layout);
508
509        dbg!(rules.layer_mapping[layer1]);
510
511        // Try to fetch design rules.
512        assert_eq!(rules.default_pitch(layer1), Some((190, 190)));
513        assert_eq!(rules.default_pitch_preferred_direction(layer1), Some(190));
514    }
515
516    #[test]
517    fn test_lef_rule_adapter_min_width() {
518        let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
519
520        let (layout, layers) = create_empty_layout();
521        let layer1 = &layers[0];
522
523        let rules = LEFDesignRuleAdapter::new(&lef, &layout);
524
525        dbg!(rules.layer_mapping[layer1]);
526
527        // Try to fetch design rules.
528        assert_eq!(rules.min_width(layer1, None), Some(50));
529    }
530
531    #[test]
532    fn test_lef_rule_adapter_default_width() {
533        let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
534
535        let (layout, layers) = create_empty_layout();
536        let layer1 = &layers[0];
537
538        let rules = LEFDesignRuleAdapter::new(&lef, &layout);
539
540        dbg!(rules.layer_mapping[layer1]);
541
542        // Try to fetch design rules.
543        assert_eq!(rules.default_width(layer1, None), Some(65));
544    }
545
546    #[test]
547    fn test_lef_rule_adapter_spacing_table() {
548        let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
549
550        let (layout, layers) = create_empty_layout();
551        let layer1 = &layers[0];
552        let layer2 = &layers[1];
553
554        let rules = LEFDesignRuleAdapter::new(&lef, &layout);
555
556        // Try to fetch design rules.
557
558        assert_eq!(rules.min_spacing_absolute(layer1), Some(100));
559
560        assert_eq!(rules.min_spacing(layer1, 0, 0), Some(100));
561
562        assert_eq!(rules.min_spacing(layer1, 999, 0), Some(100));
563        assert_eq!(rules.min_spacing(layer1, 1000, 0), Some(300));
564
565        assert_eq!(rules.min_spacing(layer1, 0, 499), Some(100));
566        assert_eq!(rules.min_spacing(&layer1, 0, 500), Some(400));
567    }
568
569    #[test]
570    fn test_lef_rule_adapter_min_spacing() {
571        let lef = read_lef_chars(LEF_DATA.chars()).expect("Failed to parse LEF");
572
573        let (layout, layers) = create_empty_layout();
574        let layer1 = &layers[0];
575        let layer2 = &layers[1];
576
577        let rules = LEFDesignRuleAdapter::new(&lef, &layout);
578
579        dbg!(rules.layer_mapping[layer2]);
580
581        // Spacing rules on metal2 without SPACINGTABLE
582        assert_eq!(rules.min_spacing(layer2, 0, 0), Some(75));
583        assert_eq!(rules.min_spacing_absolute(layer2), Some(75));
584    }
585}