4 releases

0.0.5 Jun 5, 2024
0.0.4 Jun 5, 2024
0.0.3 Jun 4, 2024
0.0.2 Mar 14, 2022

#525 in Parser implementations

Download history 1/week @ 2024-09-17 16/week @ 2024-09-24

112 downloads per month

AGPL-3.0-or-later

315KB
7K SLoC

LEF/DEF parser and writer

LEF (Library Exchange Format) and DEF (Design Exchange Format) are industry standard file formats for describing standard cell libraries, technology data (LEF) and whole designs including layout and netlists (DEF).

This crate provides input and output functions for this formats including datastructures for their representation.

Documentation

Documentation is generated from source with:

git clone [this repo]
cd [this repo]
cargo doc --open

Or alternatively find the documentation hosted here.

TODOs

  • support for serde

References

Licence

  • The program code is licensed under the AGPLv3
  • Some test data from FreePDK45 and Sky130 is licensed under Apache 2.0

lib.rs:

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::*;
// Create an empty layout.
let mut chip = Chip::new();

let mut import_options = import::DEFImportOptions::default();
// Disable import of wiring for the sake of simplicity.
// This way, a LEF structure is not necessary during the DEF import.
import_options.import_wiring = false;

// Start the import.
import::import_def_into_db(&import_options, None, &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();
let outline_layer = chip.create_layer(1, 0); // Outline layer is necessary for exporting to DEF.

// The design must contain at least one cell, which will be the top-level.
let top = chip.create_cell("TOP".into());
// Create cell outline.
chip.insert_shape(&top, &outline_layer, Rect::new((0, 0), (10, 10)).into());

// Populate a DEF structure with the data from the `chip`.
let mut def = DEF::default();
let mut options = DEFExportOptions::default();
options.outline_layer = Some(outline_layer);
// 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.

Dependencies

~4.5MB
~91K SLoC