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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
 * 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)
    }
}