From b37e2834ae58ff2ce9e270af662dbf9f1d81233c Mon Sep 17 00:00:00 2001 From: Arya Reais-Parsi Date: Fri, 2 Dec 2022 23:46:56 +1300 Subject: [PATCH 1/3] just give me a lef --- layout21converters/Cargo.toml | 7 ++ layout21converters/src/proto2lef.rs | 104 ++++++++++++++++++++++++++++ lef21/src/lib.rs | 1 + 3 files changed, 112 insertions(+) create mode 100644 layout21converters/src/proto2lef.rs diff --git a/layout21converters/Cargo.toml b/layout21converters/Cargo.toml index 6d5caa5..c6bb502 100644 --- a/layout21converters/Cargo.toml +++ b/layout21converters/Cargo.toml @@ -29,6 +29,13 @@ path = "src/lef2yaml.rs" test = true bench = false +# Converts VLSIR layout proto-format files to LEF descriptions using Layout21. +[[bin]] +name = "proto2lef" +path = "src/proto2lef.rs" +test = true +bench = false + [dependencies] gds21 = {path = "../gds21"} lef21 = {path = "../lef21"} diff --git a/layout21converters/src/proto2lef.rs b/layout21converters/src/proto2lef.rs new file mode 100644 index 0000000..edde2ea --- /dev/null +++ b/layout21converters/src/proto2lef.rs @@ -0,0 +1,104 @@ +//! # proto2gds +//! +//! VLSIR protobuf schema (Layout) to LEF converter +//! + +use clap::Parser; +use std::error::Error; +//use chrono::NaiveDateTime; +use gds21::GdsLibrary; +use layout21protos::conv as proto_converters; +use layout21protos::tech as protos; +use layout21raw as raw; +use raw::utils::Ptr; + +// => The doc-comment on `ProgramOptions` here is displayed by the `clap`-generated help docs => + +/// LEF to Lef21 YAML Schema Converter +#[derive(Parser)] +struct ProgramOptions { + /// VLSIR Layout protobuf (binary) input file + #[clap(short = 'i', long, default_value = "")] + proto: String, + /// LEF output file + #[clap(short = 'o', long, default_value = "")] + lef: String, + /// VLSIR Technology protobuf (binary) input file + #[clap(short = 't', long, default_value = "")] + tech: String, + /// Verbose output mode + #[clap(short, long)] + verbose: bool, +} + +/// The main entry point. +/// All logic is offloaded to `_main` for sake of testing. +fn main() -> Result<(), Box> { + let options = ProgramOptions::parse(); + _main(&options) +} + +/// All the real logic, with `ProgramOptions` argument for sake of testing +fn _main(options: &ProgramOptions) -> Result<(), Box> { + let proto_library = match proto_converters::open(&options.proto) { + Err(err) => panic!("Couldn't read layout protobuf: {}", err), + Ok(lib) => lib, + }; + + if options.verbose { + println!("read: {:?}", &options.proto); + } + + let tech_library: protos::Technology = match proto_converters::open(&options.tech) { + Err(err) => panic!("Couldn't read tech protobuf: {}", err), + Ok(lib) => lib, + }; + + if options.verbose { + println!("read: {:?}", &options.tech); + } + + let tech_layers = raw::data::Layers::from_proto(&tech_library)?; + + if options.verbose { + println!("assembled technology {:?} layer mapping", tech_library.name); + } + + let library = match raw::Library::from_proto(proto_library, Some(Ptr::new(tech_layers))) { + Err(err) => panic!("Couldn't load library from protobuf: {}", err), + Ok(lib) => lib, + }; + + //// Load LEF from file to a [LefLibrary] + // arya: returns a LayoutResult + let lef_library = layout21raw::lef::LefExporter::export(&library)?; + + // arya: in lef21/src/write.rs; this returns LefResult<()> + lef21::save(&lef_library, &options.lef)?; + + if options.verbose { + println!("wrote {:?}", &options.lef); + } + + Ok(()) +} + +//#[cfg(test)] +//mod tests { +// use super::*; +// +// #[test] +// fn roundtrip_to_golden_file() -> Result<(), Box> { +// // The golden file was created by running the program: +// // $ cargo run -- -i resources/macro.lef -o resources/macro.yaml +// +// // TODO(aryap): this +// +// Ok(()) +// } +// +// /// Grab the full path of resource-file `fname` +// fn resource(rname: &str) -> String { +// format!("{}/resources/{}", env!("CARGO_MANIFEST_DIR"), rname) +// } +//} diff --git a/lef21/src/lib.rs b/lef21/src/lib.rs index 70ef378..990fa5e 100644 --- a/lef21/src/lib.rs +++ b/lef21/src/lib.rs @@ -112,6 +112,7 @@ mod data; pub use data::*; mod read; mod write; +pub use write::save; // Unit tests #[cfg(test)] From a84111affbb09fa29492e6fe544baa7f856dd7b8 Mon Sep 17 00:00:00 2001 From: Arya Reais-Parsi Date: Sat, 3 Dec 2022 20:59:15 +1300 Subject: [PATCH 2/3] make "Invalid un-named layer for LEF export" slightly more descriptive --- layout21raw/src/lef.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout21raw/src/lef.rs b/layout21raw/src/lef.rs index aaf766f..5101ee3 100644 --- a/layout21raw/src/lef.rs +++ b/layout21raw/src/lef.rs @@ -125,7 +125,7 @@ impl<'lib> LefExporter<'lib> { let layers = self.lib.layers.read()?; let name = self.unwrap( layers.get_name(layerkey), - format!("Invalid un-named layer for LEF export"), + format!("Invalid un-named layer for LEF export: {:?}", layerkey), )?; Ok(name.to_string()) } From d17f58b6ab9edd515e8e4b4eac6b568940cc1434 Mon Sep 17 00:00:00 2001 From: Arya Reais-Parsi Date: Mon, 5 Dec 2022 10:10:15 +1300 Subject: [PATCH 3/3] load layer names when importing them from the pb tech file --- layout21raw/src/proto.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/layout21raw/src/proto.rs b/layout21raw/src/proto.rs index 3864a0d..856fefe 100644 --- a/layout21raw/src/proto.rs +++ b/layout21raw/src/proto.rs @@ -698,6 +698,8 @@ impl Layers { .entry(layer_pb.index) .or_insert(Layer::from_num(layer_pb.index as i16)); + layer.name = Some(layer_pb.name.clone()); + let sub_index = layer_pb.sub_index as i16; let layer_purpose = match &layer_pb.purpose { Some(purpose) => Layers::proto_to_internal_layer_purpose(sub_index, &purpose.r#type()),