summaryrefslogtreecommitdiff
path: root/tb/gfx_shader_bind/testbench/checkers.py
blob: 256b83fa23890bd673c1da1ee697259720cc67f6 (plain)
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
import cocotb
from cocotb.triggers import RisingEdge, ReadOnly

from cocotb_coverage.coverage import CoverCheck

from .common import log

class PipelineIntegrityChecker:
    def __init__(self, dut, name, clk):
        self._clk, self._dut = clk, dut
        self._queue = [None] * dut.front.bind_.BIND_STAGES.value
        self._ready_sticky = False

        @CoverCheck(
            f'{name}.runnable_tx_ready',
            f_pass = lambda ready: not self._ready_sticky and     ready,
            f_fail = lambda ready:     self._ready_sticky and not ready,
        )
        def sample_ready(ready):
            self._ready_sticky = self._ready_sticky or ready

        @CoverCheck(
            f'{name}.in_to_out_integrity',
            f_pass = lambda group: group == self._queue[0] and group is not None,
            f_fail = lambda group: group != self._queue[0],
        )
        def sample_wave_group(group):
            pass

        self._sample_ready = sample_ready
        self._sample_wave_group = sample_wave_group

        cocotb.start_soon(self._run())

    async def _run(self):
        while True:
            await RisingEdge(self._clk)
            await ReadOnly()

            self._sample_ready(self._dut.runnable_in_ready.value)

            if self._dut.wave_valid.value:
                self._sample_wave_group(self._dut.wave_group.value)
            else:
                self._sample_wave_group(None)

            new_group = None
            if self._dut.runnable_out_valid.value:
                new_group = self._dut.runnable_out_data.value

            self._queue[:-1] = self._queue[1:]
            self._queue[-1] = new_group

class PcChecker:
    def __init__(self, dut, name, clk, *, mem, pc_table):
        self._clk, self._dut = clk, dut
        self._mem, self._pc_table = mem, pc_table

        @CoverCheck(
            f'{name}.pc_ok',
            f_pass = lambda wave: wave.insn is not None and self._pc_ok(wave),
            f_fail = lambda wave: wave.insn is not None and not self._pc_ok(wave),
        )
        def sample_wave(wave):
            pass

        self.sample_wave = sample_wave

    def _pc_ok(self, wave):
        pc = self._pc_table[wave.group] * 4

        expected = self._mem.read_cached(pc)
        if type(expected) is int:
            expected = (expected,)

        if wave.insn not in expected:
            log.error(f'group {wave.group} outputs insn {wave.insn}, but any of {expected} was expected')
            return False

        return True