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
// Copyright (c) 2021-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

//! Abstraction of the cell delay computation.

use super::delay_base::DelayBase;
use crate::traits::CellModel;
use libreda_db::prelude::NetlistBase;

/// A delay arc within a cell.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct CellDelayArc<PinId> {
    /// Input pin of the delay arc.
    pub input_pin: PinId,
    /// Output pin of the delay arc.
    pub output_pin: PinId,
}

/// Define the computation of the cell delay.
/// A combinational delay from an input `i` to an output `o` should depend on
/// * what is attached to the output `o` (the load),
/// * on what signal arrives at input `i`
/// * and on the state of the other inputs.
pub trait CellDelayModel<N: NetlistBase>: CellModel<N> + DelayBase {
    /// Propagate a signal from the `input_pin` to the `output_pin`.
    /// This is used as a more general form of computing the cell delay.
    /// The `input_pin` and the `output_pin` must be pins of the same cell.
    ///
    /// # Parameters
    /// `other_inputs`: Values at other input pins. If a value is not specified, this implies the default (for example 'unkown').
    ///
    /// Returns the output signal or `None` if there is no delay arc from the selected input to selected output.
    fn cell_output(
        &self,
        netlist: &N,
        input_pin: &N::PinId,
        input_signal: &Self::Signal,
        output_pin: &N::PinId,
        output_load: &Self::Load,
        other_inputs: &impl Fn(&N::PinId) -> Option<Self::LogicValue>,
    ) -> Option<Self::Signal>;

    /// Iterate over the output pins of all delay arcs starting at `related_pin`.
    fn delay_arcs(
        &self,
        netlist: &N,
        cell_id: &N::CellId,
    ) -> Box<dyn Iterator<Item = CellDelayArc<N::PinId>> + '_>;

    /// Iterate over the output pins of all delay arcs starting at `related_pin`.
    fn delay_arcs_from_pin(
        &self,
        netlist: &N,
        input_pin: &N::PinId,
    ) -> Box<dyn Iterator<Item = N::PinId> + '_> {
        let cell_id = netlist.parent_cell_of_pin(input_pin);
        let input_pin = input_pin.clone();
        Box::new(
            self.delay_arcs(netlist, &cell_id)
                .filter_map(move |arc| (arc.input_pin == input_pin).then_some(arc.output_pin)),
        )
    }

    /// Iterate over the related pins of all delay arcs ending at `output_pin`.
    fn delay_arcs_reversed(&self, output_pin: &N) -> Box<dyn Iterator<Item = N::PinId> + '_>;
}