libreda_lefdef/lib.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//! LEF and DEF input/output for the LibrEDA framework.
7//!
8//! LEF and DEF have their own data structures which are kept very close to the both file formats.
9//! The [`import`] module provides functions to convert LEF and DEF structures
10//! into a type which supports the [`L2NEdit`] trait.
11//! Similar the [`export`] module helps converting [`L2NBase`] types into DEF structures.
12//!
13//! # Current limitations
14//!
15//! Currently there's no writer implemented for LEF because normally place and route tools
16//! will not modify the LEF file. There was just no need yet.
17//!
18//! Data import from LEF and DEF is quite minimal yet. From DEF
19//! there is no routing information being imported. Currently, design import from DEF
20//! is only useful as input for placment and routing but not for post-routing stages.
21//!
22//! # Examples
23//!
24//! ## Read and import a LEF File
25//!
26//! ```
27//! use std::fs::File;
28//! use std::io::BufReader;
29//! use libreda_lefdef::lef_parser;
30//!
31//! // Open a LEF file.
32//! let f = File::open("./tests/data/lef_examples/freepdk45/gscl45nm.lef").unwrap();
33//! // Create a buffered reader for faster reading.
34//! let mut buf = BufReader::new(f);
35//!
36//! // Read the LEF data.
37//! let result = lef_parser::read_lef_bytes(&mut buf);
38//!
39//! if result.is_err() {
40//! // Handle IO errors and parsing errors.
41//! println!("Failed to parse LEF: {:?}", result);
42//! }
43//!
44//! // Access the LEF structure.
45//! let lef = result.expect("Failed to parse LEF.");
46//!
47//! // Import a LEF library into the DB format.
48//! use libreda_lefdef::import;
49//! use libreda_lefdef::libreda_db::prelude::*;
50//! let mut chip = Chip::new();
51//! let import_options = import::LEFImportOptions::default();
52//! import::import_lef_into_db(&import_options, &lef, &mut chip)
53//! .expect("Failed to import LEF.");
54//! ```
55//!
56//! ## Read and import a DEF File
57//!
58//! ```
59//! use std::fs::File;
60//! use std::io::BufReader;
61//! use libreda_lefdef::def_parser;
62//!
63//! // Open a DEF file.
64//! let f = File::open("./tests/data/def_examples/dummy.def").unwrap();
65//! // Create a buffered reader for faster reading.
66//! let mut buf = BufReader::new(f);
67//!
68//! // Read the LEF data.
69//! let result = def_parser::read_def_bytes(&mut buf);
70//!
71//! if result.is_err() {
72//! // Handle IO errors and parsing errors.
73//! println!("Failed to parse DEF: {:?}", result);
74//! }
75//!
76//! // Access the DEF structure.
77//! let def = result.expect("Failed to parse DEF.");
78//!
79//! // Import a DEF design into the DB format.
80//! // Note that in this example the DEF file does not contain any components (cell instances)
81//! // because otherwise this example would require to also import a (LEF) library first.
82//! use libreda_lefdef::import;
83//! use libreda_lefdef::libreda_db::prelude::*;
84//! // Create an empty layout.
85//! let mut chip = Chip::new();
86//!
87//! let mut import_options = import::DEFImportOptions::default();
88//! // Disable import of wiring for the sake of simplicity.
89//! // This way, a LEF structure is not necessary during the DEF import.
90//! import_options.import_wiring = false;
91//!
92//! // Start the import.
93//! import::import_def_into_db(&import_options, None, &def, &mut chip)
94//! .expect("Failed to import DEF.");
95//! ```
96//!
97//! ## Export to DEF
98//!
99//! Designs can be exported to DEF. However, DEF has a flat hierarchy and supports only a top-level design with
100//! child instances, called 'components'. A design must eventually be flattened before exported to DEF.
101//!
102//! The export to DEF first creates a DEF data-structure which can then be serialized.
103//!
104//! ```
105//! use libreda_lefdef::libreda_db::prelude::*;
106//! use libreda_lefdef::DEF;
107//! use libreda_lefdef::export::{export_db_to_def, DEFExportOptions};
108//!
109//! // Create a design to be exported.
110//! let mut chip = Chip::new();
111//! let outline_layer = chip.create_layer(1, 0); // Outline layer is necessary for exporting to DEF.
112//!
113//! // The design must contain at least one cell, which will be the top-level.
114//! let top = chip.create_cell("TOP".into());
115//! // Create cell outline.
116//! chip.insert_shape(&top, &outline_layer, Rect::new((0, 0), (10, 10)).into());
117//!
118//! // Populate a DEF structure with the data from the `chip`.
119//! let mut def = DEF::default();
120//! let mut options = DEFExportOptions::default();
121//! options.outline_layer = Some(outline_layer);
122//! // Do the conversion.
123//! let result = export_db_to_def(&options, &chip, &top, &mut def);
124//! assert!(result.is_ok()); // Handle errors.
125//! ```
126//!
127//! ## Write DEF
128//!
129//! A `DEF` structure can be serialized into the DEF format.
130//!
131//! ```
132//! use libreda_lefdef::DEF;
133//! use libreda_lefdef::def_writer::*;
134//!
135//! // Create a new empty DEF.
136//! let mut def = DEF::default();
137//! // Fill it with data. Consider using the export functions for this.
138//! def.design_name = Some("MyDesign".to_string());
139//!
140//! // Serialize to a 'writer'. This can be any type implementing the `Write` trait.
141//! let mut buffer: Vec<u8> = Vec::new();
142//! let result = write_def(&mut buffer, &def);
143//! assert!(result.is_ok()); // Handle errors.
144//!
145//! ```
146//!
147//!
148//!
149//!
150//! [`L2NEdit`]: trait@libreda_db::traits::L2NEdit
151//! [`L2NBase`]: trait@libreda_db::traits::L2NBase
152
153#![deny(missing_docs)]
154// TODO: Remove those once this crate stabilizes.
155#![allow(unused)]
156
157pub use libreda_db;
158
159// Public exports.
160pub mod def_parser;
161pub mod def_writer;
162pub mod lef_parser;
163
164pub mod common;
165pub mod def_ast;
166pub mod lef_ast;
167
168pub use def_ast::DEF;
169pub use lef_ast::LEF;
170
171pub mod export;
172pub mod import;
173mod lef_export;
174
175mod stream_parser;
176
177// TODO: Implementations of netlist/layout views.
178mod def_impl;
179mod lef_impl;
180mod lef_tech_adapter;
181
182pub use crate::def_parser::DEFReaderConfig;
183pub use crate::def_writer::DEFWriterError;
184pub use crate::lef_tech_adapter::LEFDesignRuleAdapter;
185pub use crate::stream_parser::LefDefParseError;
186use std::fs::File;
187use std::io::{BufReader, BufWriter, Read, Write};
188use std::path::Path;
189
190// Implement shortcuts for loading/storing LEF and DEF.
191impl LEF {
192 /// Deserialize a LEF from a `Write` trait object.
193 ///
194 pub fn load<R: Read>(reader: &mut R) -> Result<LEF, LefDefParseError> {
195 // Read the LEF data.
196 lef_parser::read_lef_bytes(reader)
197 }
198
199 /// Shortcut for reading a LEF library from a file.
200 pub fn load_file(path: impl AsRef<Path>) -> Result<LEF, LefDefParseError> {
201 let f =
202 File::open(path).map_err(|_err| LefDefParseError::Other("Failed to open LEF file."))?;
203 // Create a buffered reader for faster reading.
204 let mut buf = BufReader::new(f);
205
206 Self::load(&mut buf)
207 }
208
209 // /// Shortcut for writing a LEF library to a file.
210 // pub fn store_file(&self, path: impl AsRef<Path>) -> Result<(), LefDefError> {
211 // unimplemented!()
212 // }
213 //
214 // /// Serialize to a `Write` trait object.
215 // pub fn store<W: Write>(&self, writer: &mut W) -> Result<(), LefDefError> {
216 // unimplemented!()
217 // }
218}
219
220impl DEF {
221 /// Deserialize a DEF from a `Write` trait object.
222 pub fn load<R: Read>(
223 config: &DEFReaderConfig,
224 reader: &mut R,
225 ) -> Result<DEF, LefDefParseError> {
226 // Read the DEF data.
227 def_parser::read_def_bytes(reader)
228 }
229
230 /// Shortcut for reading a LEF library from a file.
231 pub fn load_file(
232 config: &DEFReaderConfig,
233 path: impl AsRef<Path>,
234 ) -> Result<DEF, LefDefParseError> {
235 let f =
236 File::open(path).map_err(|_err| LefDefParseError::Other("Failed to open DEF file."))?;
237 // Create a buffered reader for faster reading.
238 let mut buf = BufReader::new(f);
239
240 Self::load(config, &mut buf)
241 }
242
243 /// Shortcut for writing a LEF library to a file.
244 pub fn store_file(&self, path: impl AsRef<Path>) -> Result<(), DEFWriterError> {
245 let f = File::create(path)?;
246 let mut buf = BufWriter::new(f);
247 self.store(&mut buf)
248 }
249
250 /// Serialize to a `Write` trait object.
251 pub fn store<W: Write>(&self, writer: &mut W) -> Result<(), DEFWriterError> {
252 def_writer::write_def(writer, self)
253 }
254}