1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Trait definition for buffer insertion algorithms.
use crate::db::{Direction, TerminalId};
use crate::db::traits::*;
use num_traits::PrimInt;
/// Create a simple buffer tree between a specified source pin and
/// a set of sink pins.
/// The insertion strategy is up to the trait implementation.
pub trait SimpleBufferInsertion<LN: LayoutEdit + NetlistEdit>
where
LN::Coord: PrimInt,
{
/// Error type that is returned on failure.
type Error;
/// Create a buffer tree between the source terminal
/// and the sinks. The terminals are given together with their location to enable creation of
/// a placement-aware buffer tree.
///
/// On success: Return a list of created cell instances and a list of created nets.
///
/// # Note
/// All further information (which buffer to use, how many buffers to place, where to place them, etc.)
/// is to be defined by the implementation of this trait.
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>;
/// Replace the net by a buffer tree.
/// 1) Identify signal driver and sinks by the direction of the pins.
/// 2) Call `insert_buffers()`.
///
/// On success: Return a list of created cell instances and a list of created nets.
fn add_buffer_tree_on_net(
&self,
chip: &mut LN,
net: &LN::NetId,
) -> Result<(Vec<LN::CellInstId>, Vec<LN::NetId>), Self::Error> {
// Check if the net is a special net (LOW or HIGH).
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
);
}
// Find the sinks of the net and the source that drives the net.
let mut sources = vec![]; // There should be only one source.
let mut sinks = vec![];
for t in chip.each_terminal_of_net(net) {
// A pin of the parent cell is considered to be a source when it's direction is 'INPUT',
// however a pin instance that connects to a child instance is considered a sink when it's direction is 'INPUT'.
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()
);
// Print drivers of the net for easier debugging.
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![]))
}
}
}