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

//! Dummy implementation of an interconnect delay model: The delay is always zero.

use crate::traits::*;
use libreda_db::netlist::prelude::TerminalId;
use libreda_db::prelude::{NetlistBase, NetlistUtil};

/// Interconnect delay model which reports zero delay for
/// a source and target terminal which belong to the same net
/// and 'no delay' if the terminals don't belong to the same net.
pub struct ZeroInterconnectDelayModel<D> {
    delay_model: D,
}

impl<D> ZeroInterconnectDelayModel<D> {
    /// Create a new interconnect delay model which returns a zero-delay for each interconnect.
    /// The model derives the data types for delays from the supplied `delay_model`.
    pub fn new(delay_model: D) -> Self {
        Self { delay_model }
    }
}

impl<D> LoadBase for ZeroInterconnectDelayModel<D>
where
    D: LoadBase,
{
    type Load = D::Load;

    fn sum_loads(&self, load1: &Self::Load, load2: &Self::Load) -> Self::Load {
        self.delay_model.sum_loads(load1, load2)
    }
}

impl<D> TimingBase for ZeroInterconnectDelayModel<D>
where
    D: TimingBase,
{
    type Signal = D::Signal;
    type LogicValue = D::LogicValue;
}

/// Delegate `DelayModel` implementation to `self.delay_model`.
impl<D> DelayBase for ZeroInterconnectDelayModel<D>
where
    D: DelayBase,
{
    type Delay = D::Delay;

    fn summarize_delays(&self, signal1: &Self::Signal, signal2: &Self::Signal) -> Self::Signal {
        self.delay_model.summarize_delays(signal1, signal2)
    }

    fn get_delay(&self, from: &Self::Signal, to: &Self::Signal) -> Self::Delay {
        self.delay_model.get_delay(from, to)
    }
}

impl<D, N: NetlistBase> InterconnectDelayModel<N> for ZeroInterconnectDelayModel<D>
where
    D: DelayBase,
{
    fn interconnect_output(
        &self,
        netlist: &N,
        source_terminal: &TerminalId<N>,
        input_signal: &Self::Signal,
        target_terminal: &TerminalId<N>,
        output_load: &Self::Load,
    ) -> Option<Self::Signal> {
        // Both terminals should be connected to the same net. Otherwise, there's no defined
        // interconnect delay.
        let source_net = netlist.net_of_terminal(source_terminal);
        let target_net = netlist.net_of_terminal(target_terminal);

        if source_net.is_some() && source_net == target_net {
            // Return the input signal without any delay.
            Some(input_signal.clone())
        } else {
            None
        }
    }
}