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
// 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::{TerminalId, Direction};

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![]))
        }
    }
}