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