FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

cocotbでテストパタンを記述する(どんな記述ができる?)

前回に引き続き、cocotbによりテストパタンを書いている。 AXIの挙動を真似るのは大変だ。でも、このあたりがうまく攻略できるようになると、例えばISSPythonのIFを供えれば、ISSとの協調シミュレーションも可能になるのではないか。 あとは、なるべくランダムな要素も入れたいので、Pythonをうまく活用してパタンのカバレッジを上げていきたい。

1. 待ち時間をランダムに設定する

例えば、リクエストが発行されてから、応答するまでの待ち時間をランダムに設定するためには、PythonのRandom関数を使って応答すれば良い。

        wait_time = random.randint(0, 10)
        for i in range(0, wait_time):
            yield FallingEdge(self.dut.CPU_CLK)
            if self.dut.IF_MARVALID == 0:
                raise TestFailure("[NG] IF_MARVILD goes down")

2. 別のモデルを挿入することは可能なのか?

例えば、AXIのマスタはテスト対象そのものだが、スレーブに別のVerilogファイルを含めることは可能だろうか? あるいは、もう一つ上の階層でVerilogで囲んでやる必要があるかもしれない。この辺の調査はあまりできていない。 少なくとも、現在はパタンの環境として、

class tb_mag_ifu(object):
    def __init__(self, dut, dubug=True):
        self.dut = dut
...
@cocotb.test()
def basic_test(dut):
    """basic_test"""
    tb = tb_mag_ifu(dut)

まあこの程度しか指定していない。ここでmag_ifuがテスト対象な訳だが、これ以外に例えばAXIメモリなどのモデルを挿入することはできるのだろうか。まだ良く分からない。

3. バグ?関数を定義すると挙動が変わる場合がある

例えば、この二つのコードは同一の意味だと思っているのだがどうだろうか?

    @cocotb.coroutine
    def gen_and_check(self, id):
...

        wait_time = random.randint(0, 10)
        for i in range(0, wait_time):
            yield FallingEdge(self.dut.CPU_CLK)
            if self.dut.IF_MARVALID == 0:
                raise TestFailure("[NG] IF_MARVILD goes down")
        yield RisingEdge(self.dut.CPU_CLK)
        self.dut.IF_MARREADY <= 1
        yield RisingEdge(self.dut.CPU_CLK)
...
    def wait_until_marready(self):
        wait_time = random.randint(0, 10)
        for i in range(0, wait_time):
            yield FallingEdge(self.dut.CPU_CLK)
            if self.dut.IF_MARVALID == 0:
                raise TestFailure("[NG] IF_MARVILD goes down")
        yield RisingEdge(self.dut.CPU_CLK)
        self.dut.IF_MARREADY <= 1
        yield RisingEdge(self.dut.CPU_CLK)

    @cocotb.coroutine
    def gen_and_check(self, id):
...
    wait_until_marready()

なんだか良く分からないが、上記の2つでパタンの挙動に違いがでる。というか下記の関数を定義した場合には、パタンが正常に終了してくれなかった。 何だろう?ちょっと調べてみたほうが良さそうだ。

...