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
// Copyright (c) 2021-2022 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

//! Export libreda-db structures to LEF data structures.

use libreda_db::prelude as db;
use libreda_db::prelude::reference_access::*;
use libreda_db::prelude::CoordinateType;
use libreda_db::traits::*;

use std::collections::HashMap;

use super::export::LefDefExportError;
use super::lef_ast::{Shape, SignalUse, LEF};
use crate::lef_ast::Macro;
use num_traits::{NumCast, PrimInt};

/// Control the export into DEF structures.
#[derive(Clone)]
pub struct LEFExportOptions<C: L2NBase> {
    /// Provide alternative names for layers. For all other layers
    /// the default name defined in the `L2NBase` type will be used.
    pub layer_mapping: HashMap<C::LayerId, String>,
    /// Take the die-area from this layer.
    /// The layer must contain a single shape.
    pub outline_layer: Option<C::LayerId>,
    /// Enable export of pins.
    pub export_pins: bool,
    /// If a macro with some name already exists, overwrite it instead of throwing an error.
    pub overwrite_existing_macros: bool,
}

impl<C: L2NBase> Default for LEFExportOptions<C> {
    fn default() -> Self {
        Self {
            layer_mapping: Default::default(),
            outline_layer: None,
            export_pins: true,
            overwrite_existing_macros: false,
        }
    }
}

/// Populate a [`LEF`] structure with a MACRO (cell).
pub fn export_macro_to_lef<C, Crd>(
    options: &LEFExportOptions<C>,
    chip: &C,
    macro_cell: &C::CellId,
    lef: &mut LEF,
) -> Result<(), LefDefExportError>
where
    Crd: NumCast + Ord + CoordinateType + PrimInt + std::fmt::Display,
    C: L2NBase<Coord = Crd>,
{
    let macro_name = chip.cell_name(macro_cell).into();

    {
        // Check for name conflicts.
        let macro_already_exists = lef.library.macros.contains_key(&macro_name);
        if macro_already_exists & !options.overwrite_existing_macros {
            return Err(LefDefExportError::NameAlreadyExists(macro_name));
        }
    }

    let mut lef_macro = Macro::default();
    lef_macro.name = macro_name.clone();
    lef_macro.pins = todo!();
    lef_macro.obs = todo!();

    // Append the macro to the LEF library.
    lef.library.macros.insert(macro_name, lef_macro);

    Ok(())
}