use std::collections::{HashSet, HashMap};
use crate::db::*;
pub struct BufferRemover {
non_inverting_buffer_cells: HashSet<String>,
inverting_buffer_cells: HashSet<String>,
}
impl BufferRemover {
pub fn register_non_inverting_buffer(&mut self, name: String) {
self.non_inverting_buffer_cells.insert(name);
}
pub fn register_inverting_buffer(&mut self, name: String) {
self.inverting_buffer_cells.insert(name);
}
fn get_valid_buffer_cells_by_names<N>(&self, netlist: &N, names: &HashSet<String>) -> HashMap<N::CellId, (N::PinId, N::PinId)>
where N: NetlistBase {
names.iter()
.filter_map(|name| netlist.cell_by_name(name.as_str()))
.filter_map(|cell| {
let cell = netlist.cell_ref(&cell);
let inputs: Vec<_> = cell.each_input_pin().collect();
let outputs: Vec<_> = cell.each_input_pin().collect();
if inputs.len() == 1 && outputs.len() == 1 {
let i = inputs.into_iter().next().unwrap().id();
let o = outputs.into_iter().next().unwrap().id();
Some((cell.id(), (i, o)))
} else {
None
}
})
.collect()
}
pub fn remove_non_inverting_buffers<N>(&self, netlist: &mut N, top: &N::CellId) -> usize
where N: NetlistEdit {
let buffer_cells = self.get_valid_buffer_cells_by_names(netlist, &self.non_inverting_buffer_cells);
let mut num_removed_instances = 0;
for (buffer_cell, (input_pin, output_pin)) in buffer_cells {
let buffer_instances: Vec<_> = netlist.cell_ref(top)
.each_cell_instance()
.filter(|inst| inst.template_id() == buffer_cell)
.map(|inst| inst.id())
.collect();
for inst in buffer_instances {
self.remove_non_inverting_buffer(netlist, &inst, &input_pin, &output_pin);
num_removed_instances += 1;
}
}
num_removed_instances
}
fn remove_non_inverting_buffer<N>(&self, netlist: &mut N, buffer_instance: &N::CellInstId, input_pin: &N::PinId, output_pin: &N::PinId)
where N: NetlistEdit {
let input_net = netlist.net_of_pin_instance(&netlist.pin_instance(buffer_instance, input_pin));
let output_net = netlist.net_of_pin_instance(&netlist.pin_instance(buffer_instance, output_pin));
netlist.remove_cell_instance(buffer_instance);
if let (Some(i), Some(o)) = (input_net, output_net) {
netlist.replace_net(&o, &i);
}
}
}