libreda-lefdef 0.0.2

LEF/DEF input/output for libreda-db.
Documentation
/*
 * Copyright (c) 2021-2021 Thomas Kramer.
 *
 * This file is part of LibrEDA 
 * (see https://codeberg.org/libreda/libreda-lefdef).
 *
 * 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/>.
 */

//! LEF and DEF input/output for the LibrEDA framework.
//!
//! LEF and DEF have their own data structures which are kept very close to the both file formats.
//! The [`import`] module provides functions to convert LEF and DEF structures
//! into a type which supports the [`L2NEdit`] trait.
//! Similar the [`export`] module helps converting [`L2NBase`] types into DEF structures.
//!
//! # Current limitations
//!
//! Currently there's no writer implemented for LEF because normally place and route tools
//! will not modify the LEF file. There was just no need yet.
//!
//! Data import from LEF and DEF is quite minimal yet. From DEF
//! there is no routing information being imported. Currently, design import from DEF
//! is only useful as input for placment and routing but not for post-routing stages.
//!
//! # Examples
//!
//! ## Read and import a LEF File
//!
//! ```
//! use std::fs::File;
//! use std::io::BufReader;
//! use libreda_lefdef::lef_parser;
//!
//! // Open a LEF file.
//! let f = File::open("./tests/data/lef_examples/freepdk45/gscl45nm.lef").unwrap();
//! // Create a buffered reader for faster reading.
//! let mut buf = BufReader::new(f);
//!
//! // Read the LEF data.
//! let result = lef_parser::read_lef_bytes(&mut buf);
//!
//! if result.is_err() {
//!     // Handle IO errors and parsing errors.
//!     println!("Failed to parse LEF: {:?}", result);
//! }
//!
//! // Access the LEF structure.
//! let lef = result.expect("Failed to parse LEF.");
//!
//! // Import a LEF library into the DB format.
//! use libreda_lefdef::import;
//! use libreda_lefdef::libreda_db::prelude::*;
//! let mut chip = Chip::new();
//! let import_options = import::LEFImportOptions::default();
//! import::import_lef_into_db(&import_options, &lef, &mut chip)
//!   .expect("Failed to import LEF.");
//! ```
//!
//! ## Read and import a DEF File
//!
//! ```
//! use std::fs::File;
//! use std::io::BufReader;
//! use libreda_lefdef::def_parser;
//!
//! // Open a DEF file.
//! let f = File::open("./tests/data/def_examples/dummy.def").unwrap();
//! // Create a buffered reader for faster reading.
//! let mut buf = BufReader::new(f);
//!
//! // Read the LEF data.
//! let result = def_parser::read_def_bytes(&mut buf);
//!
//! if result.is_err() {
//!     // Handle IO errors and parsing errors.
//!     println!("Failed to parse DEF: {:?}", result);
//! }
//!
//! // Access the DEF structure.
//! let def = result.expect("Failed to parse DEF.");
//!
//! // Import a DEF design into the DB format.
//! // Note that in this example the DEF file does not contain any components (cell instances)
//! // because otherwise this example would require to also import a (LEF) library first.
//! use libreda_lefdef::import;
//! use libreda_lefdef::libreda_db::prelude::*;
//! let mut chip = Chip::new();
//! let import_options = import::DEFImportOptions::default();
//! import::import_def_into_db(&import_options, &def, &mut chip)
//!   .expect("Failed to import DEF.");
//! ```
//!
//! ## Export to DEF
//!
//! Designs can be exported to DEF. However, DEF has a flat hierarchy and supports only a top-level design with
//! child instances, called 'components'. A design must eventually be flattened before exported to DEF.
//!
//! The export to DEF first creates a DEF data-structure which can then be serialized.
//!
//! ```
//! use libreda_lefdef::libreda_db::prelude::*;
//! use libreda_lefdef::DEF;
//! use libreda_lefdef::export::{export_db_to_def, DEFExportOptions};
//!
//! // Create a design to be exported.
//! let mut chip = Chip::new();
//! // The design must contain at least one cell, which will be the top-level.
//! let top = chip.create_cell("TOP".into());
//!
//! // Populate a DEF structure with the data from the `chip`.
//! let mut def = DEF::default();
//! let options = DEFExportOptions::default();
//! // Do the conversion.
//! let result = export_db_to_def(&options, &chip, &top, &mut def);
//! assert!(result.is_ok()); // Handle errors.
//! ```
//!
//! ## Write DEF
//!
//! A `DEF` structure can be serialized into the DEF format.
//!
//! ```
//! use libreda_lefdef::DEF;
//! use libreda_lefdef::def_writer::*;
//!
//! // Create a new empty DEF.
//! let mut def = DEF::default();
//! // Fill it with data. Consider using the export functions for this.
//! def.design_name = Some("MyDesign".to_string());
//!
//! // Serialize to a 'writer'. This can be any type implementing the `Write` trait.
//! let mut buffer: Vec<u8> = Vec::new();
//! let result = write_def(&mut buffer, &def);
//! assert!(result.is_ok()); // Handle errors.
//!
//! ```
//!
//!
//!
//!
//! [`L2NEdit`]: libreda_db::traits::L2NEdit
//! [`L2NBase`]: libreda_db::traits::L2NBase

#![deny(missing_docs)]

// TODO: Remove those once this crate stabilizes.
#![allow(unused)]

pub use libreda_db;

// Public exports.
pub mod lef_parser;
pub mod def_parser;
pub mod def_writer;

pub mod lef_ast;
pub mod def_ast;
pub mod common;

pub use lef_ast::LEF;
pub use def_ast::DEF;

pub mod import;
pub mod export;

mod stream_parser;

// TODO: Implementations of netlist/layout views.
mod lef_impl;
mod def_impl;
mod lef_tech_adapter;


use std::fs::File;
use std::path::Path;
use std::io::{BufReader, Read, Write, BufWriter};
pub use crate::def_parser::DEFReaderConfig;
pub use crate::stream_parser::LefDefParseError;
pub use crate::def_writer::DEFWriterError;
pub use crate::lef_tech_adapter::LEFDesignRuleAdapter;

// Implement shortcuts for loading/storing LEF and DEF.
impl LEF {

    /// Deserialize a LEF from a `Write` trait object.
    ///
    pub fn load<R: Read>(reader: &mut R) -> Result<LEF, LefDefParseError> {
        // Read the LEF data.
        lef_parser::read_lef_bytes(reader)
    }

    // /// Shortcut for reading a LEF library from a file.
    // pub fn load_file(path: impl AsRef<Path>) -> Result<LEF, LefDefParseError> {
    //     let f = File::open(path)?;
    //     // Create a buffered reader for faster reading.
    //     let mut buf = BufReader::new(f);
    //
    //     Self::load(&mut buf)
    // }

    // /// Shortcut for writing a LEF library to a file.
    // pub fn store_file(&self, path: impl AsRef<Path>) -> Result<(), LefDefError> {
    //     unimplemented!()
    // }
    //
    // /// Serialize to a `Write` trait object.
    // pub fn store<W: Write>(&self, writer: &mut W) -> Result<(), LefDefError> {
    //     unimplemented!()
    // }
}

impl DEF {

    /// Deserialize a DEF from a `Write` trait object.
    pub fn load<R: Read>(config: &DEFReaderConfig, reader: &mut R) -> Result<DEF, LefDefParseError> {
        // Read the DEF data.
        def_parser::read_def_bytes(reader)
    }

    // /// Shortcut for reading a LEF library from a file.
    // pub fn load_file(config: &DEFReaderConfig, path: impl AsRef<Path>) -> Result<DEF, LefDefParseError> {
    //     let f = File::open(path)?;
    //     // Create a buffered reader for faster reading.
    //     let mut buf = BufReader::new(f);
    //
    //     Self::load(config, &mut buf)
    // }

    /// Shortcut for writing a LEF library to a file.
    pub fn store_file(&self, path: impl AsRef<Path>) -> Result<(), DEFWriterError> {
        let f = File::create(path)?;
        let mut buf = BufWriter::new(f);
        self.store(&mut buf)
    }

    /// Serialize to a `Write` trait object.
    pub fn store<W: Write>(&self, writer: &mut W) -> Result<(), DEFWriterError> {
        def_writer::write_def(writer, self)
    }
}