Esempio n. 1
0
    def __init__(self, fc_init=[[0]*6]*8, *args, **kwargs):
        self.log = logging.getLogger(f"cocotb.pcie.{type(self).__name__}.{id(self)}")
        self.log.name = f"cocotb.pcie.{type(self).__name__}"

        self.parent = None
        self.rx_handler = None

        self.max_link_speed = None
        self.max_link_width = None

        self.tx_queue = Queue(1)
        self.tx_queue_sync = Event()

        self.rx_queue = Queue()

        self.cur_link_speed = None
        self.cur_link_width = None

        self.time_scale = get_sim_steps(1, 'sec')

        # ACK/NAK protocol
        # TX
        self.next_transmit_seq = 0x000
        self.ackd_seq = 0xfff
        self.retry_buffer = Queue()

        # RX
        self.next_recv_seq = 0x000
        self.nak_scheduled = False
        self.ack_nak_latency_timer = 0

        self.max_payload_size = 128
        self.max_latency_timer = 0

        self.send_ack = Event()

        self._ack_latency_timer_cr = None

        # Flow control
        self.send_fc = Event()

        self.fc_state = [FcChannelState(fc_init[k], self.start_fc_update_timer) for k in range(8)]

        self.fc_initialized = False
        self.fc_init_vc = 0
        self.fc_init_type = FcType.P

        self.fc_idle_timer_steps = get_sim_steps(10, 'us')
        self.fc_update_steps = get_sim_steps(30, 'us')

        self._fc_update_timer_cr = None

        super().__init__(*args, **kwargs)

        # VC0 is always active
        self.fc_state[0].active = True

        cocotb.fork(self._run_transmit())
        cocotb.fork(self._run_receive())
        cocotb.fork(self._run_fc_update_idle_timer())
Esempio n. 2
0
async def test_time_units_eq_None(dut):
    """Test deprecation warning when time units are None"""
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always")
        Timer(1, units=None)
        assert issubclass(w[-1].category, DeprecationWarning)
        assert 'Using units=None is deprecated, use units="step" instead.' in str(
            w[-1].message)
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always")
        Clock(dut.clk, 2, units=None)
        assert issubclass(w[-1].category, DeprecationWarning)
        assert 'Using units=None is deprecated, use units="step" instead.' in str(
            w[-1].message)
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always")
        get_sim_steps(222, units=None)
        assert issubclass(w[-1].category, DeprecationWarning)
        assert 'Using units=None is deprecated, use units="step" instead.' in str(
            w[-1].message)
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always")
        await cocotb.triggers.with_timeout(example(),
                                           timeout_time=12_000_000,
                                           timeout_unit=None)
        assert issubclass(w[-1].category, DeprecationWarning)
        assert 'Using timeout_unit=None is deprecated, use timeout_unit="step" instead.' in str(
            w[-1].message)
Esempio n. 3
0
 def __init__(self, signal, period, units=None):
     BaseClock.__init__(self, signal)
     self.period = get_sim_steps(period, units)
     self.half_period = get_sim_steps(period / 2.0, units)
     self.frequency = 1.0 / get_time_from_sim_steps(self.period, units='us')
     self.hdl = None
     self.signal = signal
     self.coro = None
     self.mcoro = None
Esempio n. 4
0
 def __init__(self, signal, period, units=None):
     BaseClock.__init__(self, signal)
     self.period = get_sim_steps(period, units)
     self.half_period = get_sim_steps(period / 2.0, units)
     self.frequency = 1.0 / get_time_from_sim_steps(self.period,units='us')
     self.hdl = None
     self.signal = signal
     self.coro = None
     self.mcoro = None
Esempio n. 5
0
 def __init__(self, signal, period, units="step"):
     BaseClock.__init__(self, signal)
     if units is None:
         warnings.warn(
             'Using units=None is deprecated, use units="step" instead.',
             DeprecationWarning, stacklevel=2)
         units="step"  # don't propagate deprecated value
     self.period = get_sim_steps(period, units)
     self.half_period = get_sim_steps(period / 2.0, units)
     self.frequency = 1.0 / get_time_from_sim_steps(self.period, units='us')
     self.hdl = None
     self.signal = signal
     self.coro = None
     self.mcoro = None
Esempio n. 6
0
    async def _run_clock(self, period):
        half_period = get_sim_steps(period / 2.0, 'ns')
        t = Timer(half_period)

        while True:
            await t
            self.dut.output_clk.value = 1
            await t
            self.dut.output_clk.value = 0
Esempio n. 7
0
async def test_get_sim_steps(_):

    # test invalid round_mode specifier
    with pytest.raises(ValueError,
                       match="^Invalid round_mode specifier: notvalid"):
        utils.get_sim_steps(1, "step", round_mode="notvalid")

    # test default, update if default changes
    with pytest.raises(ValueError):
        utils.get_sim_steps(0.5, "step")

    # test valid
    with pytest.raises(ValueError):
        utils.get_sim_steps(0.5, "step", round_mode="error")
    assert utils.get_sim_steps(24.0, "step", round_mode="error") == 24
    assert utils.get_sim_steps(1.2, "step", round_mode="floor") == 1
    assert utils.get_sim_steps(1.2, "step", round_mode="ceil") == 2
    assert utils.get_sim_steps(1.2, "step", round_mode="round") == 1
Esempio n. 8
0
async def test_get_sim_steps(_):

    # test invalid round_mode specifier
    with pytest.raises(ValueError) as e:
        utils.get_sim_steps(1, "step", "notvalid")
    assert "invalid" in str(e).lower()

    # test default, update if default changes
    with pytest.raises(ValueError):
        utils.get_sim_steps(0.5, "step")

    # test valid
    with pytest.raises(ValueError):
        utils.get_sim_steps(0.5, "step", "error")
    assert utils.get_sim_steps(24.0, "step", "error") == 24
    assert utils.get_sim_steps(1.2, "step", "floor") == 1
    assert utils.get_sim_steps(1.2, "step", "ceil") == 2
    assert utils.get_sim_steps(1.2, "step", "round") == 1
Esempio n. 9
0
    async def _run_clock(self, period):
        half_period = get_sim_steps(period / 2.0, 'ns')
        t = Timer(half_period)

        while True:
            await t
            self.rx_clk <= 1
            await t
            self.rx_clk <= 0
Esempio n. 10
0
    def __init__(self, time_ps, units=None):
        """
        Args:
           time_ps (numbers.Real or decimal.Decimal): The time value.
               Note that despite the name this is not actually in picoseconds
               but depends on the *units* argument.
           units (str or None, optional): One of
               ``None``, ``'fs'``, ``'ps'``, ``'ns'``, ``'us'``, ``'ms'``, ``'sec'``.
               When no *units* is given (``None``) the timestep is determined by
               the simulator.

        Examples:

            >>> await Timer(100, units='ps')

            The time can also be a ``float``:

            >>> await Timer(100e-9, units='sec')

            which is particularly convenient when working with frequencies:

            >>> freq = 10e6  # 10 MHz
            >>> await Timer(1 / freq, units='sec')

            Other builtin exact numeric types can be used too:

            >>> from fractions import Fraction
            >>> await Timer(Fraction(1, 10), units='ns')

            >>> from decimal import Decimal
            >>> await Timer(Decimal('100e-9'), units='sec')

            These are most useful when using computed durations while
            avoiding floating point inaccuracies.

        See Also:
            :func:`~cocotb.utils.get_sim_steps`

        Raises:
            TriggerException: If a negative value is passed for Timer setup.

        .. versionchanged:: 1.5
            Raise an exception when Timer uses a negative value as it is undefined behavior.
            Warn for 0 as this will cause erratic behavior in some simulators as well.
        """
        GPITrigger.__init__(self)
        if time_ps <= 0:
            if time_ps == 0:
                warnings.warn(
                    "Timer setup with value 0, which might exhibit undefined behavior in some simulators",
                    category=RuntimeWarning,
                    stacklevel=2)
            else:
                raise TriggerException(
                    "Timer value time_ps must not be negative")
        self.sim_steps = get_sim_steps(time_ps, units)
Esempio n. 11
0
    async def _run_clocks(self, period):
        half_period = get_sim_steps(period / 2.0, 'ns')
        t = Timer(half_period)

        while True:
            await t
            self.tx_clk.value = 1
            self.rx_clk.value = 1
            await t
            self.tx_clk.value = 0
            self.rx_clk.value = 0
Esempio n. 12
0
    def __init__(self, time_ps, units=None):
        """
        Args:
           time_ps (numbers.Real or decimal.Decimal): The time value.
               Note that despite the name this is not actually in picoseconds
               but depends on the *units* argument.
           units (str or None, optional): One of
               ``None``, ``'fs'``, ``'ps'``, ``'ns'``, ``'us'``, ``'ms'``, ``'sec'``.
               When no *units* is given (``None``) the timestep is determined by
               the simulator.

        Examples:

            >>> await Timer(100, units='ps')

            The time can also be a ``float``:

            >>> await Timer(100e-9, units='sec')

            which is particularly convenient when working with frequencies:

            >>> freq = 10e6  # 10 MHz
            >>> await Timer(1 / freq, units='sec')

            Other builtin exact numeric types can be used too:

            >>> from fractions import Fraction
            >>> await Timer(Fraction(1, 10), units='ns')

            >>> from decimal import Decimal
            >>> await Timer(Decimal('100e-9'), units='sec')

            These are most useful when using computed durations while
            avoiding floating point inaccuracies.

        See Also:
            :func:`~cocotb.utils.get_sim_steps`
        """
        GPITrigger.__init__(self)
        self.sim_steps = get_sim_steps(time_ps, units)
Esempio n. 13
0
 def __init__(self, time_ps, units=None):
     GPITrigger.__init__(self)
     self.sim_steps = get_sim_steps(time_ps, units)
Esempio n. 14
0
    def __init__(self, time=None, units="step", *, time_ps=None):
        """
        Args:
           time (numbers.Real or decimal.Decimal): The time value.

               .. versionchanged:: 1.5.0
                  Previously this argument was misleadingly called `time_ps`.

           units (str, optional): One of
               ``'step'``, ``'fs'``, ``'ps'``, ``'ns'``, ``'us'``, ``'ms'``, ``'sec'``.
               When *units* is ``'step'``,
               the timestep is determined by the simulator (see :make:var:`COCOTB_HDL_TIMEPRECISION`).

        Examples:

            >>> await Timer(100, units='ps')

            The time can also be a ``float``:

            >>> await Timer(100e-9, units='sec')

            which is particularly convenient when working with frequencies:

            >>> freq = 10e6  # 10 MHz
            >>> await Timer(1 / freq, units='sec')

            Other builtin exact numeric types can be used too:

            >>> from fractions import Fraction
            >>> await Timer(Fraction(1, 10), units='ns')

            >>> from decimal import Decimal
            >>> await Timer(Decimal('100e-9'), units='sec')

            These are most useful when using computed durations while
            avoiding floating point inaccuracies.

        See Also:
            :func:`~cocotb.utils.get_sim_steps`

        Raises:
            TriggerException: If a negative value is passed for Timer setup.

        .. versionchanged:: 1.5
            Raise an exception when Timer uses a negative value as it is undefined behavior.
            Warn for 0 as this will cause erratic behavior in some simulators as well.

        .. versionchanged:: 1.5
            Support ``'step'`` as the the *units* argument to mean "simulator time step".

        .. deprecated:: 1.5
            Using None as the the *units* argument is deprecated, use ``'step'`` instead.
        """
        GPITrigger.__init__(self)
        if time_ps is not None:
            if time is not None:
                raise TypeError("Gave argument to both the 'time' and deprecated 'time_ps' parameter")
            time = time_ps
            warnings.warn(
                "The parameter name 'time_ps' has been renamed to 'time'. Please update your invocation.",
                DeprecationWarning, stacklevel=2)
        else:
            if time is None:
                raise TypeError("Missing required argument 'time'")
        if time <= 0:
            if time == 0:
                warnings.warn("Timer setup with value 0, which might exhibit undefined behavior in some simulators",
                              category=RuntimeWarning,
                              stacklevel=2)
            else:
                raise TriggerException("Timer value time_ps must not be negative")
        if units is None:
            warnings.warn(
                'Using units=None is deprecated, use units="step" instead.',
                DeprecationWarning, stacklevel=2)
            units = "step"  # don't propagate deprecated value
        self.sim_steps = get_sim_steps(time, units)
Esempio n. 15
0
 def __init__(self, time_ps, delta_neg, delta_pos, units=None):
     GPITrigger.__init__(self)
     self.sim_steps = get_sim_steps(time_ps, units)
     self.delta_neg = delta_neg
     self.delta_pos = delta_pos
Esempio n. 16
0
 def __init__(self, time_ps, units=None):
     GPITrigger.__init__(self)
     self.sim_steps = get_sim_steps(time_ps, units)
Esempio n. 17
0
 def sim_steps(self):
     # lazy so we don't call into the simulator until we need to
     return get_sim_steps(self._time_ps, self._units)