use libertyparse::{Liberty, Unparsed};
use indexmap::IndexSet;
use std::env;
use std::fs::{self, File};
use std::ops::Range;
use std::io::{BufWriter, Write};
fn read_liberty(path: impl AsRef<std::path::Path>) -> (String, Liberty) {
let s = fs::read_to_string(path)
.expect("Error reading liberty source file");
let lib = match Liberty::parse_str(&s) {
Ok(lib) => lib,
Err(e) => panic!("{e}")
};
(s, lib)
}
fn main() {
clilog::init_stderr_color_debug();
let args: Vec<String> = env::args().collect();
assert!(args.len() == 4,
"Usage: {} <old_lib_path> <new_lib_path> <write_out>",
args[0]);
let (_, lib_old) = read_liberty(&args[1]);
clilog::info!("Old liberty file {}", args[1]);
let (old_libwise, old_cellwise, old_pinwise, old_timingwise) =
lib_old.debug_report_unparsed();
let (s_new, lib_new) = read_liberty(&args[2]);
clilog::info!("New liberty file {}", args[2]);
let (mut new_libwise, mut new_cellwise, mut new_pinwise, mut new_timingwise) =
lib_new.debug_report_unparsed();
for s in old_libwise {
new_libwise.remove(&s);
}
for s in old_cellwise {
new_cellwise.remove(&s);
}
for s in old_pinwise {
new_pinwise.remove(&s);
}
for s in old_timingwise {
new_timingwise.remove(&s);
}
clilog::info!("Removing {} lib-wise items: {:?}",
new_libwise.len(), new_libwise);
clilog::info!("Removing {} cell-wise items: {:?}",
new_cellwise.len(), new_cellwise);
clilog::info!("Removing {} pin-wise items: {:?}",
new_pinwise.len(), new_pinwise);
clilog::info!("Removing {} timing-wise items: {:?}",
new_timingwise.len(), new_timingwise);
let mut removed_spans: Vec<Range<usize>> = Vec::new();
let mut insert_into_removed_spans =
|v: &Vec<Unparsed>, filt: &IndexSet<&str>| {
for u in v {
if filt.contains(u.keyword.as_str()) {
removed_spans.push(u.span.clone());
}
}
};
for (_, lib) in &lib_new.libs {
insert_into_removed_spans(&lib.unparsed, &new_libwise);
for (_, cell) in &lib.cells {
insert_into_removed_spans(&cell.unparsed, &new_cellwise);
for (_, pin) in &cell.pins {
insert_into_removed_spans(&pin.unparsed, &new_pinwise);
for timing in &pin.timings {
insert_into_removed_spans(&timing.unparsed, &new_timingwise);
}
}
}
}
println!("Removing {} snippets from {} and saving to {}",
removed_spans.len(), args[2], args[3]);
removed_spans[..].sort_unstable_by_key(|rng| rng.start);
let f = File::create(&args[3]).unwrap();
let mut f = BufWriter::new(f);
let mut i = 0; for span in removed_spans {
f.write(s_new[i..span.start].as_bytes()).unwrap();
i = span.end;
}
f.write(s_new[i..].as_bytes()).unwrap();
}