use crate::db::{TerminalId, Direction};
use crate::db::traits::*;
use num_traits::PrimInt;
pub trait SimpleBufferInsertion<LN: LayoutEdit + NetlistEdit>
where LN::Coord: PrimInt {
type Error;
fn insert_buffers(
&self,
chip: &mut LN,
signal_source: TerminalId<LN>,
signal_sinks: &Vec<TerminalId<LN>>,
) -> Result<(Vec<LN::CellInstId>, Vec<LN::NetId>), Self::Error>;
fn add_buffer_tree_on_net(
&self,
chip: &mut LN,
net: &LN::NetId,
) -> Result<(Vec<LN::CellInstId>, Vec<LN::NetId>), Self::Error> {
if chip.is_constant_net(net) {
let parent_name = chip.cell_name(&chip.parent_cell_of_net(net));
log::warn!("Net '{:?}' in '{}' probably requires a tie cell instead of a buffer.", net, parent_name);
}
let mut sources = vec![]; let mut sinks = vec![];
for t in chip.each_terminal_of_net(net) {
match &t {
TerminalId::PinId(p) => {
match chip.pin_direction(p) {
Direction::Input => sources.push(t),
Direction::Output => sinks.push(t),
d => {
let cell_name = chip.cell_name(&chip.parent_cell_of_pin(&p));
let pin_name = chip.pin_name(p);
panic!("Cannot handle pin direction of pin '{}' in cell '{}': {:?} (must be input or output)", pin_name, cell_name, d)
}
}
}
TerminalId::PinInstId(p) => {
match chip.pin_direction(&chip.template_pin(p)) {
Direction::Input => sinks.push(t),
Direction::Output => sources.push(t),
d => {
let pin = chip.template_pin(p);
let cell_name = chip.cell_name(&chip.parent_cell_of_pin(&pin));
let pin_name = chip.pin_name(&pin);
panic!("Cannot handle pin direction of pin '{}' in cell '{}': {:?} (must be input or output)", pin_name, cell_name, d)
}
}
}
}
}
log::debug!("Number of drivers: {}", sources.len());
log::debug!("Number of sinks: {}", sinks.len());
if sources.len() != 1 {
log::error!("Net must be driven by exactly one output pin but net {:?} is driven by {} output pins.",
chip.net_name(net),
sources.len()
);
for driver in &sources {
let pin = match driver {
TerminalId::PinId(p) => p.clone(),
TerminalId::PinInstId(p) => chip.template_pin(p)
};
let pin_name = chip.pin_name(&pin);
let cell = chip.parent_cell_of_pin(&pin);
let cell_name = chip.cell_name(&cell);
log::error!("Pin '{}' of cell '{}' drives the net.", pin_name, cell_name)
}
}
if !sources.is_empty() {
assert_eq!(sources.len(), 1, "Cannot handle more than one signal driver.");
let source = sources[0].clone();
self.insert_buffers(chip, source, &sinks)
} else {
log::warn!("Skip buffer tree on net '{:?}': No driver found.", chip.net_name(net));
Ok((vec![], vec![]))
}
}
}